Re: PieChart

From: Jerry Coffin (jcoffin_at_taeus.us)
Date: 05/16/04

  • Next message: Jeff Partch [MVP]: "Re: HBITMAP deselection"
    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.
    

  • Next message: Jeff Partch [MVP]: "Re: HBITMAP deselection"

    Relevant Pages

    • Re: PieChart
      ... I want to draw a Pie Chart depending upon certain mathematical ... My result is a % value which I want to display via the Pie ... > How do I control the visualizalation of the Chart like I want to draw 30%, ... figure up the points that define that section's part of a circle. ...
      (microsoft.public.vc.mfc)
    • Re: PieChart
      ... I want to draw a Pie Chart depending upon certain mathematical ... > figure up the points that define that section's part of a circle. ... > brush, you should dave the handle of the brush that was already ...
      (microsoft.public.vc.mfc)
    • Re: Hexagon cutting tablesaw jig
      ... The diameter of the compass place anywhere on the circle, ... Draw a segement that is the length of the width of the desired ...
      (rec.woodworking)
    • Re: NEW EVIDENCE: Circle Method has a problem!!
      ... Thanks to Randy B. there does appear to be a work around which I appreciate! ... ' Draw Axis at ... ' When the center of the circle is placed the radius distance from the ...
      (microsoft.public.vb.general.discussion)
    • Re: Ping Vinny: GSimple
      ... I was able to draw a circle, get a few distances, snap seems to work on a ... altho not on a circle. ... I assumed it could draw in 3-D, from the isometric/axonometric views of the ... How does one get those views from a 2-D drawing? ...
      (alt.machines.cnc)

    Loading