Solved

Help on graphics

Posted on 2000-03-01
12
174 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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 31

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
 
LVL 31

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 31

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 31

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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Complete beginner needs help making a cron job 9 131
substring method in java 1 137
format the code in java 6 110
conditional code and condition difference 9 85
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
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.
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

730 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