Thread: Who Ate All The Pie(...)s?

  1. #1
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273

    Question Who Ate All The Pie(...)s?

    Hello,

    I thought I'd have a go over the weekend at using GDI's built-in function for drawing pie segments to display some data but, as always, it's never that straightforward...

    The thing is, the Pie function expects the coordinates of points between which an arc is drawn and the segment closed by drawing lines back to the centre of the pie, defined by its bounding box. As this means the pie may be elliptical in shape, seperate radii have to be found for both axes. I've pretty much go the hang of that, but for some reason, beyond a certain point, the sign of the x-coordinate calculations have to be reversed in order to ensure that the acute angle between the coordinates is used instead of the obtuse.

    The problem is, I can't determine the condition(s) for this. It would have been much easier if this thing could just take angles!

    The following C code illustrates the dilemma. Note that I add (pi / 2) to the calculations so that the segments are drawn from north instead of east. A couple Ellipse calls are used to illustrate where each coordinate ends up as a debugging measure.
    Code:
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <math.h>
    
    #define TWOPI		2 * 3.14159265
    #define HALFPI		3.14159265 / 2
    
    #define NUMVALUES	5
    
    double g_dValues[NUMVALUES] = { 20, 20, 20, 20, 20 };
    HBITMAP g_hbmp = NULL, g_hbmpOld;
    HBRUSH g_hbrBlue, g_hbrRed;
    HDC g_hdc;
    
    BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_CLOSE:
            {
                DeleteObject(g_hbrRed);
                DeleteObject(g_hbrBlue);
                SelectObject(g_hdc, g_hbmpOld);
                DeleteObject(g_hbmp);
                DeleteDC(g_hdc);
                EndDialog(hwndDlg, 0);
                break;
            }
            case WM_INITDIALOG:
            {
                g_hdc = CreateCompatibleDC(NULL);
                g_hbrBlue = CreateSolidBrush(0xFF0000);
                g_hbrRed = CreateSolidBrush(0xFF);
                break;
            }
            case WM_PAINT:
            {
                PAINTSTRUCT ps;
    
                BeginPaint(hwndDlg, &ps);
                BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, g_hdc, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
                EndPaint(hwndDlg, &ps);
                break;
            }
            case WM_SIZE:
            {
                double dRadiusX, dRadiusY, dSums[NUMVALUES + 1];
                int i;
                POINT pt1, pt2;
    
                if (wParam != SIZE_MINIMIZED)
                {
                    if (g_hbmp)
                    {
                        SelectObject(g_hdc, g_hbmpOld);
                        DeleteObject(g_hbmp);
                    }
    
                    g_hbmp = CreateCompatibleBitmap(GetDC(NULL), LOWORD(lParam), HIWORD(lParam));
                    g_hbmpOld = SelectObject(g_hdc, g_hbmp);
                    SelectObject(g_hdc, GetSysColorBrush(COLOR_BTNFACE));
                    PatBlt(g_hdc, 0, 0, LOWORD(lParam), HIWORD(lParam), PATCOPY);
                    dSums[0] = 0;
                    for (i=0;i<NUMVALUES;i++)
                        dSums[i + 1] = dSums[i] + g_dValues[i];
    
                    dRadiusX = LOWORD(lParam) / 2.0;
                    dRadiusY = HIWORD(lParam) / 2.0;
                    for (i=0;i<NUMVALUES;i++)
                    {
                        SelectObject(g_hdc, (i & 1) ? g_hbrRed : g_hbrBlue);
                        if (dSums[i] <= dSums[NUMVALUES] / 2 || i == NUMVALUES - 1)
                            pt1.x = (int)(dRadiusX - dRadiusX * cos((TWOPI * dSums[i + 1]) / dSums[NUMVALUES] + HALFPI));
                        else
                            pt1.x = (int)(dRadiusX + dRadiusX * cos((TWOPI * dSums[i + 1]) / dSums[NUMVALUES] + HALFPI));
    
                        pt1.y = (int)(dRadiusY - dRadiusY * sin((TWOPI * dSums[i + 1]) / dSums[NUMVALUES] + HALFPI));
                        if (dSums[i] <= dSums[NUMVALUES] / 2 || i == NUMVALUES - 1)
                            pt2.x = (int)(dRadiusX - dRadiusX * cos((TWOPI * dSums[i]) / dSums[NUMVALUES] + HALFPI));
                        else
                            pt2.x = (int)(dRadiusX + dRadiusX * cos((TWOPI * dSums[i]) / dSums[NUMVALUES] + HALFPI));
    
                        pt2.y = (int)(dRadiusY - dRadiusY * sin((TWOPI * dSums[i]) / dSums[NUMVALUES] + HALFPI));
                        Pie(g_hdc, 0, 0, LOWORD(lParam), HIWORD(lParam), pt1.x, pt1.y, pt2.x, pt2.y);
                        SelectObject(g_hdc, GetStockObject(WHITE_BRUSH));
                        Ellipse(g_hdc, pt1.x - 4, pt1.y - 4, pt1.x + 4, pt1.y + 4);
                        SelectObject(g_hdc, GetStockObject(GRAY_BRUSH));
                        Ellipse(g_hdc, pt2.x - 4, pt2.y - 4, pt2.x + 4, pt2.y + 4);
                    }
    
                    InvalidateRect(hwndDlg, NULL, TRUE);
                }
    
                break;
            }
            default:
                return FALSE;
    
        }
    
        return TRUE;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        DWORD dwData[6];
        LPDLGTEMPLATE lpTemplate;
    
        ZeroMemory(dwData, sizeof(dwData));
        lpTemplate = (LPDLGTEMPLATE)dwData;
        lpTemplate->style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
        lpTemplate->x = (short)0x8000;
        lpTemplate->y = (short)0x8000;
        lpTemplate->cx = (short)0x8000;
        lpTemplate->cy = (short)0x8000;
        return DialogBoxIndirect(hInstance, lpTemplate, NULL, DialogProc);
    }
    Last edited by SMurf; 03-09-2008 at 08:59 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. useful: disk usage pie chart + graph visualization
    By doubleanti in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 06-05-2009, 04:06 PM
  2. Replies: 30
    Last Post: 02-19-2008, 10:48 PM
  3. I wanna throw a pie in his face too
    By sean in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 09-06-2003, 11:24 AM
  4. 4 and 20 Pie?
    By adrianxw in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 10-03-2002, 02:34 AM
  5. Drawing 3D pie charts
    By SMurf in forum Windows Programming
    Replies: 5
    Last Post: 02-01-2002, 05:31 PM