How to draw a 2D array of data in MFC

Hello,

I have a circle of data that is represented as:

vector<vector <unsigned char> >* data;

The first dimension of this vector is the angle of the data so there are 360 angles, and the second dimension is the bins of the data in which there are 512 bins per angle. Each bin has a value from 0 to 15 to determine the intensity of the bin. So basically, when this is all display, there will be a circle of data, with varying colors of intensity at each bin.

What is the best approach to doing this in MFC? Can anyone provide sample code on how they would draw this on the screen?

Regards,

Ellay K.

Re: How to draw a 2D array of data in MFC

If I understood what you want, the basic idea would be to calculate

the points of the polygon for each angle/bin, and fill it with the

appropriate color. The code below should calculate the points:

Code:

`const int n_angles = 360;`

const int n_bins = 512;

const double radius = 100.0; // size of circle on screen

const double angle_inc = 2.0 * 3.14159 / static_cast<double>(n_angles);

const double bin_inc = radius / static_cast<double>(n_bins);

for (int i=0; i<n_angles; ++i)

{

for (int j=0; j<n_bins; ++j)

{

double angle1 = angle_inc * i;

double angle2 = angle_inc * (i+1);

double r1 = bin_inc * j;

double r2 = bin_inc * (j+1);

double x1 = r1 * cos(angle1);

double y1 = r1 * sin(angle1);

double x2 = r2 * cos(angle1);

double y2 = r2 * sin(angle1);

double x3 = r2 * cos(angle2);

double y3 = r2 * sin(angle2);

double x4 = r1 * cos(angle2);

double y4 = r1 * sin(angle2);

// fill in the polygon consisting of the points:

// (x1,y1) , (x2,y2) , (x3,y3) , (x4,y4)

}

}

It can be made a bit more efficient, since the code above re-calculates

some sin/cos values more than it needs to.

(Code not tested).

Re: How to draw a 2D array of data in MFC

Thanks for the response. I took this code, and I tried to make it work, but nothing was displaying on the screen. So I started debugging the points, and here is an example of my 4 points:

(0, 0)

(1, 0)

(1, 0)

(0, 0)

So I guess something is incorrect with the math.

Here is my code:

Code:

` for(int i=0; i<angles; ++i)`

{

for(int j=0; j<bins; ++j)

{

double angle1 = angle_inc * i;

double angle2 = angle_inc * (i+1);

double r1 = bin_inc * j;

double r2 = bin_inc * (j+1);

CPoint pts[4];

pts[0].x = r1 * cos(angle1);

pts[0].y = r1 * sin(angle1);

pts[1].x = r2 * cos(angle1);

pts[1].y = r2 * sin(angle1);

pts[2].x = r2 * cos(angle2);

pts[2].y = r2 * sin(angle2);

pts[3].x = r1 * cos(angle2);

pts[3].y = r1 * sin(angle2);

// fill in the polygon consisting of the points:

// (x1,y1) , (x2,y2) , (x3,y3) , (x4,y4)

CRgn region;

region.CreatePolygonRgn(pts, 4, ALTERNATE);

CBrush blueBrush;

blueBrush.CreateSolidBrush(RGB(0, 0, 255));

dcMemory.FillRgn(®ion, &blueBrush);

}

}

Any idea what is wrong?

Thanks!

Re: How to draw a 2D array of data in MFC

CPoint stores x and y values as type ints. The result of

Code:

`pts[0].x = r1 * cos(angle1);`

is a double which is then stored into an int! If you look at the first few values actually calculated as double before being stored, they have values between about 0 and 1 - so are stored in pts as 0 and 1 when converted to int!

1 Attachment(s)

Re: How to draw a 2D array of data in MFC

As 2kaud mentioned, there will be some problems with int versus double.

What are your values for angles , bins , bin_inc , and , angle_inc ?

I am a bit concerned that with that many bins/angle combinations, you

could get a number of points which should be distinct (as double) becoming

the same when converted to int.

Attached is a sample image I made using OpenGL() graphics with 25 angles

and 25 bins and using random colors. Is this the type of plot you want ?

Attachment 31487

Re: How to draw a 2D array of data in MFC

What type should I use then to pass to CreatePolygonRgn() ? It takes LPPOINT's which are longs. Can I pass doubles to them?

Thanks

Re: How to draw a 2D array of data in MFC

Hello Phillip,

The data I am attempting to plot is coming from a radar, if that helps.

Re: How to draw a 2D array of data in MFC

From my previous post :

What are your values for angles , bins , bin_inc , and , angle_inc ?

I used your code with a few minor changes and it worked.

1) I did not use dcMemory

2) I offset the circle by the radius, since it looks like (0,0) is the

top left corner of the window using the default graphics.

Re: How to draw a 2D array of data in MFC

Can you post the code that has the changes you made?

I don't have my code here to post those values for the variables, but I will post them as soon as I can.

Thanks!

Re: How to draw a 2D array of data in MFC

Code:

`void CMyView::OnDraw(CDC* pDC)`

{

CviewDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!pDoc)

return;

// TODO: add draw code for native data here

int angles = 360;

int bins = 512;

const double radius = 100.0; // size of circle on screen

const double angle_inc = 2.0*3.14159267 / static_cast<double>(angles);

const double bin_inc = radius / static_cast<double>(bins);

const double xcenter = radius;

const double ycenter = radius;

for(int i=0; i<angles; ++i)

{

for(int j=0; j<bins; ++j)

{

double angle1 = angle_inc * i;

double angle2 = angle_inc * (i+1);

double r1 = bin_inc * j;

double r2 = bin_inc * (j+1);

CPoint pts[4];

pts[0].x = xcenter + r1 * cos(angle1);

pts[0].y = ycenter + r1 * sin(angle1);

pts[1].x = xcenter + r2 * cos(angle1);

pts[1].y = ycenter + r2 * sin(angle1);

pts[2].x = xcenter + r2 * cos(angle2);

pts[2].y = ycenter + r2 * sin(angle2);

pts[3].x = xcenter + r1 * cos(angle2);

pts[3].y = ycenter + r1 * sin(angle2);

// fill in the polygon consisting of the points:

// (x1,y1) , (x2,y2) , (x3,y3) , (x4,y4)

CRgn region;

region.CreatePolygonRgn(pts, 4, ALTERNATE);

CBrush blueBrush;

blueBrush.CreateSolidBrush(RGB(0, 0, 255));

pDC->FillRgn(®ion, &blueBrush);

}

}

}

This is very slow. I assume that using dcMemory speeds it up considerably.

If not, you might consider a higher performance graphics system.

You mentioned radar. That could mean a lot of things when it comes to

visualization. One way to speed it up. Just draw the basic outline, and

only draw the pixels that have something in it.

Re: How to draw a 2D array of data in MFC

Hello Philip,

Is it possible you can zip up your sample project and post it here? For some reason nothing is displaying correctly for me.

I also sent you a private message if you get a chance to read it.

I really appreciate your help.

By the way here are the values you asked for:

window size is 973, so radius is 973/2

#bins: 1024

#angles: 360

j = 0

angle1 = 0.00000000000000000

angle2 = 0.017453292611111112

r1 = 0.00000000000000000

r2 = 0.47460937500000000

pts: (486,486), (486,486), (486,486), (486,486)

j = 1

angle1 = 0.00000000000000000

angle2 = 0.017453292611111112

r1 = 0.47460937500000000

r2 = 0.94921875000000000

pts: (486,486), (486,486), (486,486), (486,486)

j = 2

angle1 = 0.00000000000000000

angle2 = 0.017453292611111112

r1 = 0.94921875000000000

r2 = 1.4238281250000000

pts: (486,486), (487,486), (487,486), (486,486)

j = 3

angle1 = 0.00000000000000000

angle2 = 0.017453292611111112

r1 = 1.4238281250000000

r2 = 1.8984375000000000

pts: (487,486), (487,486), (487,486), (487,486)

Do these seem correct?

Thanks!

1 Attachment(s)

Re: How to draw a 2D array of data in MFC

Attached.

Why not try angles = 25 and bins = 25 ? This will check that

CreatePolygonRgn/FillRgn can handle degenerate polygons.

I would guess that you would not use the full 360 x 1024 anyway.

You can plot a subset and get good results.

Re: How to draw a 2D array of data in MFC

Hello Philip,

Ok I made some progress. I got it to display if I use dc, but not when I use dcMemory. So this code works:

Code:

` CPaintDC dc(this);`

...

CRgn region;

region.CreatePolygonRgn(pts, 4, ALTERNATE);

CBrush blueBrush;

blueBrush.CreateSolidBrush(RGB(0, 0, 255));

dc.FillRgn(®ion, &blueBrush);

While this code does not draw anything:

Code:

` CPaintDC dc(this); `

CDC dcMemory;

dcMemory.CreateCompatibleDC(&dc);

...

CRgn region;

region.CreatePolygonRgn(pts, 4, ALTERNATE);

CBrush blueBrush;

blueBrush.CreateSolidBrush(RGB(0, 0, 255));

dcMemory.FillRgn(®ion, &blueBrush);

I am guessing that this happens as dcMemory can only work with functions such as BitBlt?

Thanks!