Re: PieChart
From: Jerry Coffin (jcoffin_at_taeus.us)
Date: 05/16/04
- Previous message: Kwan: "Help with Model Dialog in WinXP."
- In reply to: Cina: "PieChart"
- Next in thread: Cina: "Re: PieChart"
- Reply: Cina: "Re: PieChart"
- Messages sorted by: [ date ] [ thread ]
Date: Sun, 16 May 2004 01:31:03 -0600
In article <uuhZrqvOEHA.2716@tk2msftngp13.phx.gbl>,
nospam@microsoft.com says...
> Hi All, I want to draw a Pie Chart depending upon certain mathematical
> calcuations. My result is a % value which I want to display via the Pie
> Chart..I know the CDC::Pie method for rendering the Pie Chart....
> How do I control the visualizalation of the Chart like I want to draw 30%,
> 66% etc......with the Pie Chart.....
Here's some demo code. With a (VS 6) AppWizard-generated app, start
by adding something like this to your_document.h:
#include <vector>
// this describes one section of the chart -- the percentage and
// color for that slice of the pie.
struct section {
double percent;
DWORD color;
section(double p, DWORD c) : percent(p), color(c) {}
};
Then in your document class, define a vector of them:
std::vector<section> sections;
You'll need to add some code to initialize the sections with the
right values. For demo purposes, I added this to OnNewDocument:
// three equal slices in red, green and blue:
sections.push_back(section(33.33, RGB(0,0,255)));
sections.push_back(section(33.33, RGB(0,255,0)));
sections.push_back(section(33.33, RGB(255,0,0)));
Now the hard(er) part: drawing the data into a pie-chart. I've
started by defining a couple of types to store our data:
struct circle {
POINT center;
int radius;
};
struct pie_section {
POINT one;
POINT two;
double end_angle;
};
Then we have a routine to take the data about a pie section, and
figure up the points that define that section's part of a circle.
This is really fairly basic trig -- starting with polar coordinates
(i.e. a center and an angle) and converting them to rectangular
(cartesian) coordinates:
pie_section pie_sect(double start_angle,
circle const &c,
section const &s)
{
double angle, end_angle;
pie_section ret;
angle = s.percent / 100.0 * 2.0 * 3.1416;
end_angle = start_angle + angle;
ret.one.x = static_cast<int>(c.center.x +
c.radius * cos(end_angle));
ret.one.y = static_cast<int>(c.center.y +
c.radius * sin(end_angle));
ret.two.x = static_cast<int>(c.center.x +
c.radius * cos(start_angle));
ret.two.y = static_cast<int>(c.center.y +
c.radius * sin(start_angle));
ret.end_angle = end_angle;
return ret;
}
One side-note here: Windows expects coordinates to run clockwise, but
trig functions run counter-clockwise. Therefore, I've swapped the
start and the end angles, so each of our pie sections runs clockwise.
That gives us enough to draw each section, so OnDraw gets code like
this added to do the drawing:
double start_angle = 0.0;
CRect rect;
GetClientRect(&rect);
// figure up coordinates of a circle so it will fill as much of the
// client area as possible and still remain a circle.
circle c;
c.center.x = rect.Width()/2;
c.center.y = rect.Height()/2;
c.radius = min(rect.Width()/2, rect.Height()/2);
// box is a square that encloses the circle we're going to draw in.
// I.e. this rect is basically the same as the center/radius of our
// circle, only in cartesian coords.
CRect box;
box.left = c.center.x-c.radius;
box.right = c.center.x+c.radius;
box.top = c.center.y-c.radius;
box.bottom = c.center.y+c.radius;
// Now, step through each section in the pie chart, convert its angle
// to rectangle coords, and then draw it out in the selected color.
//
for (int i=0; i<pDoc->sections.size(); ++i) {
CBrush brush;
brush.CreateSolidBrush(pDoc->sections[i].color);
pDC->SelectObject(brush);
pie_section p = pie_sect(start_angle, c, pDoc->sections[i]);
pDC->Pie(box, p.one, p.two);
start_angle = p.end_angle;
brush.DeleteObject();
}
and that finishes the job. If you want to adjust the starting angle,
it's in radians. As usual for trig functions, it starts at the right
side of the circle and progresses counter-clockwise from there.
For the sake of clarity, this code does essentially no checking of
the inputs. If your slices don't add up to 100%, it'll do its best
to draw something, but the results probably won't be what you want.
It also deletes a brush while it's still selected into a DC -- which
isn't right, but the code to do it right clutters up the loop and you
(hopefully) already know about doing that (i.e. when you select the
brush, you should dave the handle of the brush that was already
there. Before you delete the brush, you should select the original
brush back into the DC).
--
Later,
Jerry.
The universe is a figment of its own imagination.
- Previous message: Kwan: "Help with Model Dialog in WinXP."
- In reply to: Cina: "PieChart"
- Next in thread: Cina: "Re: PieChart"
- Reply: Cina: "Re: PieChart"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|