# Drawing 3d pies for statistical purposes

Hi,

could you please tell me how to draw 3d pies por statistical purposes. They should be displaced away from the common center.

Thanks a lot

Cuba Ramos

i would use quadrics like partial disks and cylinders,but if you want more control over your pies maybe write your own “quadrics” code.

i’d prefer the quadrics; less work

Triangle fans should work well; you can use loops between the glBegin and glEnd to vary colours or whatever based upon your statistical data. Then use another loop with a little trig and glQuads to build up the sides of the pie for depth. Use glTranslatef to put em where you want em.

Hello Sebastian and Glenn,
I am very grateful for your help.
I wrote some code but it is helpless slow (in W95 context). Would you eventually have an idea how to speed it up?. Thanks a lot.

Cuba Ramos

The code looks like this (entry point: DrawScene):

// DrawGraph.cpp : interface of the CDrawGraph class
//
/////////////////////////////////////////////////////////////////////////////

#include “stdafx.h”
#include “DrawGraph.h”
#include <math.h>
#include <GL/glut.h>

#define drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES);
glVertex2f((x1),(y1)); glVertex2f((x2),(y2)); glEnd();

// GLuint startList;
// Start, Sweep
GLdouble gldAngles[][2] = {
{ -90.0f, 225.0f},
{ 130.0f, 90.0f},
{ 220.0f, 50.0f}
};
/*
// Start, Sweep
GLdouble gldAngles[][2] = {
{ -90.0f, 300.0f},
{ 130.0f, 90.0f},
{ 220.0f, 50.0f}
};
*/
// int iSeparationFactor = 10;
// GLdouble gldStartAngle, GLdouble gldSweepAngle;

void CDrawGraph::displayText10(int pictureNumber)
{
GLfloat white[3] = { 0.0, 0.0, 0.0 };
// GLfloat white[3] = { 1.0, 1.0, 1.0 };

// glClear(GL_COLOR_BUFFER_BIT);
// glColor3fv(white);

char buffer[100];
glColor3f(0.0, 0.0, 0.0);

{
glRasterPos2f(-1.5, 0.7);
printString(“above target”);

``````   glRasterPos2f(-1.5f, 0.5f);
printString(buffer);
``````

}

{
glRasterPos2f(0.0f, -0.7f);
printString(“inside target”);

``````   glRasterPos2f(0.0f, -0.9f);
printString(buffer);
``````

}

{
glRasterPos2f(0.75f, 0.7f);
printString(“below target”);

``````   glRasterPos2f(0.75f, 0.5f);
printString(buffer);
``````

}

// glFlush ();
}

void CDrawGraph::displayText12(int pictureNumber)
{
glColor3f(0.0, 0.0, 0.0);

char s[12];

// Legende
glRasterPos2f(-1.6f, 0.1f);
sprintf (s, “N = %2d”, iN[pictureNumber]);
printString(s);

glRasterPos2f(-1.6f, -0.2f);
sprintf (s, “Hypo: %1d”, iHypo[pictureNumber]);
printString(s);

glRasterPos2f(-1.6f, -0.5f);
sprintf (s, “Hi: %1d”, iHi[pictureNumber]);
printString(s);

glRasterPos2f(-1.6f, -0.8f);
sprintf (s, “Lo: %1d”, iLo[pictureNumber]);
printString(s);

// glFlush ();
}

void CDrawGraph::displayTitle12(int pictureNumber)
{
GLfloat white[3] = { 0.0, 0.0, 0.0 };
// GLfloat white[3] = { 1.0, 1.0, 1.0 };

// glClear(GL_COLOR_BUFFER_BIT);
// glColor3fv(white);

``````glColor3f(0.0, 0.0, 0.0);
``````

// Title
glRasterPos2f(-0.7f, 0.9f);
switch( pictureNumber )
{
case 0:
printString(“Before breakfast”);
break;
case 1 :
printString(“Before lunch”);
break;
case 2 :
printString(“Before dinner”);
break;
case 3 :
printString(“After breakfast”);
break;
case 4 :
printString(“After lunch”);
break;
case 5 :
printString(“After dinner”);
break;
case 6 :
printString(“Bed”);
break;
case 7 :
printString(“Night”);
break;
case 8 :
printString(“Overall”);
break;
default:
break;
}

}

void CDrawGraph::getRasterFont(int nPoints, bool bBold)
{
// TEXTMETRIC tm;
// CFont testFont;
// char text[100];
CSize tExtent;
int nBold;

``````if (bBold==TRUE)
nBold = 700;
else
nBold = 400;
``````

// testFont.CreateFont(-nPoints * 20, 0, 0, 0, 400, FALSE, FALSE, 0,
HFONT testFont = CreateFont(-nPoints, 0, 0, 0, nBold, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, “Arial”);

``````HDC hdc =  wglGetCurrentDC();
SelectObject (hdc, testFont);
``````

// SelectObject (hdc, GetStockObject (SYSTEM_FONT));
wglUseFontBitmaps (hdc, 0, 255, 1000);
}

void CDrawGraph::initFont(int nPoints, bool bBold)
{
getRasterFont(nPoints, bBold);
}

void CDrawGraph: rintString(char *s)
{
glPushAttrib (GL_LIST_BIT);
glListBase(1000);
// glListBase(fontOffset);
glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s);
glPopAttrib ();
}

CDrawGraph::CDrawGraph()
{
// TODO: add construction code here

}

float fHeight,
int iN[9],
int iHypo[9],
int iHi[9],
int iLo[9]
)
{
int k;
int j;

``````for (k=0; k&lt;iGraphs; k++)
{
for (j=0; j&lt;iPies; j++)
{
}
}

this-&gt;fHeight = fHeight;

for (k=0; k&lt;iGraphs; k++)
{
this-&gt;iN[k] = iN[k];
this-&gt;iHypo[k] = iHypo[k];
this-&gt;iHi[k] = iHi[k];
this-&gt;iLo[k] = iLo[k];
}
``````

}

CDrawGraph::~CDrawGraph()
{
}

// SetDCPixelFormat sets the pixel format for a device context in
// preparation for creating a rendering context.

void CDrawGraph::SetDCPixelFormat(HDC hdc)
{

``````HANDLE       hHeap;
int          nColors, i;
LPLOGPALETTE lpPalette;

static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),  // Size of this structure
1,                              // Version number
PFD_DRAW_TO_WINDOW |            // Flags
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,                  // Use RGBA pixel values
24,                             // Try to use 24-bit color
0, 0, 0, 0, 0, 0,               // Don't care about these
0, 0,                           // No alpha buffer
32, 0, 0, 0, 0,                 // 32-bit accumulation buffer
32,                             // 32-bit depth buffer
0,                              // No stencil buffer
0,                              // No auxiliary buffers
PFD_MAIN_PLANE,                 // Layer type
0,                              // Reserved (must be 0)
0, 0, 0                         // No layer masks
};

int nPixelFormat;

nPixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, nPixelFormat, &pfd);

DescribePixelFormat(hdc, nPixelFormat,
sizeof(PIXELFORMATDESCRIPTOR),
&pfd);

if(pfd.dwFlags & PFD_NEED_PALETTE)
{
nColors = 1 &lt;&lt; pfd.cColorBits;
hHeap = GetProcessHeap();

lpPalette = (LPLOGPALETTE) HeapAlloc(hHeap, 0,
sizeof(LOGPALETTE) + (nColors *
sizeof(PALETTEENTRY)));

lpPalette-&gt;palVersion = 0x300;
lpPalette-&gt;palNumEntries = nColors;

byRedMask = (1 &lt;&lt; pfd.cRedBits) - 1;
byGreenMask = (1 &lt;&lt; pfd.cGreenBits) - 1;
byBlueMask = (1 &lt;&lt; pfd.cBlueBits) - 1;

for(i = 0; i &lt; nColors; i++)
{
lpPalette-&gt;palPalEntry[i].peRed =
(((i &gt;&gt; pfd.cRedShift) & byRedMask) * 255) /
lpPalette-&gt;palPalEntry[i].peGreen =
(((i &gt;&gt; pfd.cGreenShift) & byGreenMask) * 255) /
lpPalette-&gt;palPalEntry[i].peBlue =
(((i &gt;&gt; pfd.cBlueShift) & byBlueMask) * 255) /
lpPalette-&gt;palPalEntry[i].peFlags = 0;
}
``````

// Create the palette and free the allocated memory
m_hPalette = CreatePalette(lpPalette);
HeapFree(hHeap, 0, lpPalette);

// Realize the color palette
if(m_hPalette != NULL)
{
SelectPalette(hdc, m_hPalette, FALSE);
RealizePalette(hdc);
}
}
}

//---------------------------------------------------------------
// CDrawGraph:: D r a w S c e n e
//
// DrawScene uses OpenGL commands to draw a number of
// objects in a scene.

void CDrawGraph: rawScene()
{
// Define a few colors. In OpenGL, RGB values are specified as
// floating-point numbers between 0.0 and 1.0.

// Clear the color and depth buffers.
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Set up the viewpoint
// Note coordinate system is:
//
// y
//
// ^
// | z-axis points out
// |
// |
// z (.)-----------> x
//
//

``````int k;
int i;
int j;
i = 0;
j = 0;
for (k=0; k&lt;iGraphs; k++)
{
if ((0==(k % iPies)) && (k &gt;= iPies))
{
i = 0;
++j;
}
::glViewport((-cx/3) + ((i)*(cx/3)) + cx/90, (cy/3) - ((j)*(cy/3)), cx, cy);
init (k);
display (k);
++i;
}

::glViewport(cx/6, -cy/6, cx, cy);
glColor3f(0.0, 0.0, 0.0);
drawOneLine (0.0f, 0.0f, 4.0f, 0.0f);
drawOneLine (0.0f, 0.0f, 0.0f, -4.0f);
glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0x0101);	/* dotted */
::glViewport(0, -cy/6, cx, cy);
drawOneLine (-6.5f, 0.0f, 10.0f, 0.0f);
::glViewport(cx/6, 0, cx, cy);
drawOneLine (0.0f, 10.0f, 0.0f, -10.0f);
::glViewport(-cx/6, 0, cx, cy);
drawOneLine (0.0f, 5.0f, 0.0f, -5.0f);
glDisable (GL_LINE_STIPPLE);

::glViewport(0, 0, cx, cy);
``````

// Render the scene in the window’s DC
// SwapBuffers(wglGetCurrentDC());
}

/////////////////////////////////////////////////////////////////////////////
void CDrawGraph::SetDarkColor(int iPie)
{
GLfloat red_mat_ambient[] = { 0.5f, 0.0f, 0.0f, 1.0f };
GLfloat green_mat_ambient[] = { 0.0f, 0.5f, 0.0f, 1.0f };
GLfloat blue_mat_ambient[] = { 0.0f, 0.0f, 0.5f, 1.0f };

switch( iPie )
{
case 0:
glColor4fv(red_mat_ambient);
break;
case 1 :
glColor4fv(green_mat_ambient);
break;
case 2 :
glColor4fv(blue_mat_ambient);
break;
default:
break;
}

}

/////////////////////////////////////////////////////////////////////////////
void CDrawGraph::SetColor(int iPie)
{
GLfloat red_mat_ambient[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat green_mat_ambient[] = { 0.0, 1.0, 0.0, 1.0 };
GLfloat blue_mat_ambient[] = { 0.0, 0.0, 1.0, 1.0 };

switch( iPie )
{
case 0:
glColor4fv(red_mat_ambient);
break;
case 1 :
glColor4fv(green_mat_ambient);
break;
case 2 :
glColor4fv(blue_mat_ambient);
break;
default:
break;
}

}

/* Everything above this line could be in a library

• that defines a font. To make it work, you’ve got

• to call makeRasterFont() before you start making

• calls to printString().
*/
/////////////////////////////////////////////////////////////////////////////
void CDrawGraph::init(int kGraph)
{
int i;
int j;
int k;

k = kGraph;

glClearColor(1.0, 1.0, 1.0, 0.0);

glEnable(GL_DEPTH_TEST);

startList = glGenLists(iPies);

// draw 3 pies
for (j=0; j<iPies; j++)
{
glNewList(startList+j, GL_COMPILE);
// glNewList(startList+j+k, GL_COMPILE);

``````	SetColor(j);
if ((k==2) && (j==1) && (iAngleGrads[k][j]==360))
glColor4f(0.8, 0.8, 0.8, 1.0);

switch( j )
{
case 0:
break;
case 1 :
break;
case 2 :
break;
default:
break;
}
``````

// We calculate here the displacement of the center

// glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

``````	glLineWidth(1.0f);
``````

// glPolygonMode(GL_FRONT, GL_LINE);

// Surfaces

// triangle fan

``````	glBegin(GL_TRIANGLE_FAN);
{
glVertex3f(
0);
}
glEnd();

glBegin(GL_TRIANGLE_FAN);
{
glVertex3f(
fHeight);
}
glEnd();

SetDarkColor(j);
if ((k==2) && (j==1) && (iAngleGrads[k][j]==360))
glColor4f(0.5, 0.5, 0.5, 1.0);

{
glVertex3f(
0);
glVertex3f(
fHeight);
}
glEnd();

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glVertex3f(
0);
glVertex3f(
fHeight);
glEnd();

glVertex3f(
0);
glVertex3f(
fHeight);
glEnd();

// Legende
``````

/*
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(1.0, 0.0, 0.0, 1.0);
glRasterPos2i(20, 60);
printString(“Hello”);
*/
glEndList();

``````}
``````

}

void CDrawGraph::display(int kGraph)
{

``````int j;
int k;
float x;
float y;
float z;

k = kGraph;

x = (k + 1) * 2.55f;
y = (k + 1) * 1.4f;
z = (k + 1) * 0.0f;
``````

// glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_LINE_SMOOTH);
glPushMatrix();
for (j=0; j<iPies; j++)
{
glPushMatrix();
if (k==0)
{
// glTranslatef(-x, y, z);
}
initFont(12, TRUE);
displayTitle12(k);
initFont(12, FALSE);
displayText12(k);
initFont(10, FALSE);
displayText10(k);
glPolygonMode(GL_FRONT, GL_LINE);
glColor3f(0.0, 0.0, 0.0);
// glLineWidth(0.0f);
glRectf (-1.7f, -0.9f, -0.9f, 0.38f);
glPushMatrix();
glRotatef(-45.0f, 1.0f, 0.0f, 0.0f);
glCallList(startList+j);
// glCallList(startList+j+k);
glPopMatrix();
glPopMatrix();

``````	glDeleteLists(startList+j, 1);
}
glPopMatrix();
``````

/*
glPushMatrix();

// glTranslatef(-x, y, z);
initFont(12);
displayText12(1);
initFont(10);
displayText10(1);

``````glPolygonMode(GL_FRONT, GL_LINE);
glColor3f(0.0, 0.0, 0.0);
``````

// glLineWidth(0.0f);
glRectf (-3.0f, -1.5f, -1.4f, 0.0);
glPopMatrix();
*/
glFlush();

}