Solved

Help on graphics

Posted on 2000-03-01
12
170 Views
Last Modified: 2013-11-20
I'm writting an application in which I have to plot a 2D array. The first
approach I took was to scan each row and to display the value of each column:

for (i=0;i<nrows;i++)
{      
      pDC->MoveTo(x,y);
      for (j=0;j<ncols;j++)
      {      
            value=data[i][j];
            pDC->LineTo(x,y);
      }
}

This method works fine but I get a representation like the following:



-----------------------
---*-------------------
---*------------*------
--*-*----------*-*-----
--*-*---------*---*----
------*------*-----*---
-----*-*---------------
-----*-*---------------
-----------*-----------
----------*-*----------
---------*---*---------
-------*------*--------


and what I need is to get something like this:


-----------------------
---*-------------------
---*------------*------
--* *----------* *-----
--* *---------*   *----
------*------*     *---
-----* *---------------
-----* *---------------
-----------*-----------
----------* *----------
---------*   *---------
-------*      *--------

Can any one give me some light? I think I should use some hidden surface
algorithm but I don't know how to implement it.

TIA
0
Comment
Question by:qocarlos
  • 4
  • 3
  • 2
  • +3
12 Comments
 
LVL 8

Expert Comment

by:gelbert
ID: 2574032
Try to use CDC::PolyPolygon(). They would draw whatever shape you have based on array and fill in with specified color.The current polygon-filling mode can be retrieved or set by using the GetPolyFillMode and SetPolyFillMode member functions.

 
0
 
LVL 1

Expert Comment

by:Binder
ID: 2574039
 Hello,

     I dont´t think you need a hidden surface algorithm here. You can
solve this problem by verifiyng that each opening * has a corresponding
closing *. Between them you don´t need to draw your lines.
0
 
LVL 8

Expert Comment

by:gelbert
ID: 2574044
I could not find samples for PolyPolygon() but you can take a look at MFC samples DRAWCLI(drawvw.cpp) & OLEVIEW(shadow.cpp) which use Polygon()
0
 
LVL 3

Author Comment

by:qocarlos
ID: 2574371
Thanks for the comments.
I will try the PolyPolygon() function.
Please, check out the following page:
http://qobrue.usc.es/graphics/graphic.htm

I've put there two graphics showing what I'm trying to do.
I think the difference between both plots is evident.
The effect shown in plot labeled "WhiteWash" is what I need to get.

Thanks again for all your help


0
 
LVL 8

Expert Comment

by:VinExpert
ID: 2575532
Hi,

I feel the only difference is the lines in between the starts, That U dont want right?.
If yes, then, have one more storage area which tells U that, that perticular row is having more than one * to plot. U can get that by scanning the array once. Then, if u need to plot more than one * per row, and if already one * has been plotted, then dont call LineTo till another * is plotted. This U can do using a simple flag.

The extra array will indicate whether that row contains more than one *, right?. Then whenver U plot *, set that flag to TRUE, then dont call LineTo if it is TRUE, then When U plot the next *, set it back to FALSE......
like that the logic goes.

Try it out.

VinExpert
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2575688
Hi qocarlos,

I do not think that CDC::Polygon() allone will solve this, because you don't want a closed polygon to be drawn. So, I would suggest you to use CDC::Polygon() to 'undraw' before drawing with your code like this:

....
CPen *pOldPen;
CArray <POINT, POINT&> points;
points.SetSize( nCol );
for (i=0;i<nrows;i++)
{
 pOldPen = pDC->SelectStockObject( NULL_PEN );
 for (j=0;j<ncols;j++)
 {
  value=data[i][j];
  points[j].x = //here calculate x
  points[j].y = //and y from value
 }
 pDC->Polygon( points.GetData(), point.GetSize() );

 pDC->SelectObject( pOldPen );
// since here it's your previous code
 pDC->MoveTo(x,y);
 for (j=0;j<ncols;j++)
 {
  value=data[i][j];
  pDC->LineTo(x,y);
 }
}

hope that helps,

ZOPPO
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 30

Expert Comment

by:Zoppo
ID: 2575698
excuse me, I forgot the brush:

....
CBrush *pOldBrush = (CBrush*)pDC->SelectStockObject( NULL_BRUSH );
pDC->Polygon( points.GetData(), point.GetSize() );
pDC->SelectObject( pOldBrush );
....

and even forgot that you'll have to cast the pen like this:

....
pOldPen = (CPen*)pDC->SelectStockObject( NULL_PEN );
....

sorry,

ZOPPO
0
 
LVL 1

Expert Comment

by:ElmerFud
ID: 2576281
The only real way to do this is to draw the lines from the top down.

I would go with the hidden surface algorithm.

First, start a second CDC object.  Then draw a large rectangle on the unseen CDC.  Next, draw one of the array traces.  Fill the upper part of the divided rectange with an odd color that you don't wish to you.  Finally bitblt the unseen object ontop of the seen object and specify that the odd color is to be trasparent.

It may sound quite complicated, but I know it could be done.  For the 500 points, I'd be willing to work on your project with you.  I don't expect it would take more than an hour to add to what you've got.  If you're interested email me at roberthamilton@usa.com
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2577136
Hi,

I've tested my previous suggestion some time and made some corrections:

CPen *pOldPen;
CArray <POINT, POINT&> points;
points.SetSize( nCol+2 );
for (i=0;i<nrows;i++)
{
 pOldPen = pDC->SelectStockObject( NULL_PEN );
 for (j=0;j<ncols;j++)
 {
  value=data[i][j];
  points[j+1].x = //here calculate x
  points[j+1].y = //and y from value
 }
 points[0].x = 0;
 points[0].y = ymin; // set this y min to the y coordinate of the lower edge of the window
 points[ncols+1].x = point[ncols].x;
 points[ncols+1].y = ymin;

 CBrush *pOldBrush = (CBrush*)pDC->SelectStockObject( WHITE_BRUSH ); // we need a white brush instead a null brush of course...
 pDC->Polygon( points.GetData(), point.GetSize() );
 pDC->SelectObject( pOldBrush );
 pDC->SelectObject( pOldPen );
 // since here it's your previous code
 pDC->MoveTo(x,y);
 for (j=0;j<ncols;j++)
 {
  value=data[i][j];
  pDC->LineTo(x,y);
 }
}

ZOPPO
0
 
LVL 3

Author Comment

by:qocarlos
ID: 2577297
Hi,
Thanks to all for your really useful comments. I have implemented Zoppo solution and it worked really great.
So, Zoppo, I will award you the points. Just drop a blank answer and the points will be yours. Thanks a lot.
I have used your first comments but I didn't select any brush into the device context and used Polyline() rather than LineTo and MoveTo because it's much faster.
If I select a white brush, it also works. Do you know if this presents any advantage?

Thanks again,
Carlos
0
 
LVL 30

Accepted Solution

by:
Zoppo earned 500 total points
ID: 2579273
Hi qocarlos,

I think it doesn't mind as long a white brush is the default brush of a dc with white backgroud ... perhaps better way would be to retrieve the backgroud color of the device context and create a brush and a pen with this color and use these to undraw the area before drawing the line itself...

ZOPPO
0
 
LVL 3

Author Comment

by:qocarlos
ID: 2581068
Hi Zoppo,
Thanks a lot for all your help.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now