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
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);
if (iAngleGrads[pictureNumber][0] > 0)
{
glRasterPos2f(-1.5, 0.7);
printString(“above target”);
glRasterPos2f(-1.5f, 0.5f);
sprintf (buffer, "%3.2f %%", ((float)iAngleGrads[pictureNumber][0]/3.6));
printString(buffer);
}
if (iAngleGrads[pictureNumber][1] > 0)
{
glRasterPos2f(0.0f, -0.7f);
printString(“inside target”);
glRasterPos2f(0.0f, -0.9f);
sprintf (buffer, "%3.2f %%", ((float)iAngleGrads[pictureNumber][1]/3.6));
printString(buffer);
}
if (iAngleGrads[pictureNumber][2] > 0)
{
glRasterPos2f(0.75f, 0.7f);
printString(“below target”);
glRasterPos2f(0.75f, 0.5f);
sprintf (buffer, "%3.2f %%", ((float)iAngleGrads[pictureNumber][2]/3.6));
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)
{
glShadeModel (GL_FLAT);
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
}
CDrawGraph::CDrawGraph(int iAngleGrads[9][3],
float fHeight,
float fRadiusFactor,
int iRelativeInitialAngleGrads,
float fDisplRadFact, // Displacement radius factor
int iN[9],
int iHypo[9],
int iHi[9],
int iLo[9]
)
{
int k;
int j;
for (k=0; k<iGraphs; k++)
{
for (j=0; j<iPies; j++)
{
this->iAngleGrads[k][j] = iAngleGrads[k][j];
}
}
this->fHeight = fHeight;
this->fRadiusFactor = fRadiusFactor;
this->iRelativeInitialAngleGrads = iRelativeInitialAngleGrads;
this->fDisplRadFact = fDisplRadFact;
for (k=0; k<iGraphs; k++)
{
this->iN[k] = iN[k];
this->iHypo[k] = iHypo[k];
this->iHi[k] = iHi[k];
this->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;
BYTE byRedMask, byGreenMask, byBlueMask;
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 << pfd.cColorBits;
hHeap = GetProcessHeap();
lpPalette = (LPLOGPALETTE) HeapAlloc(hHeap, 0,
sizeof(LOGPALETTE) + (nColors *
sizeof(PALETTEENTRY)));
lpPalette->palVersion = 0x300;
lpPalette->palNumEntries = nColors;
byRedMask = (1 << pfd.cRedBits) - 1;
byGreenMask = (1 << pfd.cGreenBits) - 1;
byBlueMask = (1 << pfd.cBlueBits) - 1;
for(i = 0; i < nColors; i++)
{
lpPalette->palPalEntry[i].peRed =
(((i >> pfd.cRedShift) & byRedMask) * 255) /
byRedMask;
lpPalette->palPalEntry[i].peGreen =
(((i >> pfd.cGreenShift) & byGreenMask) * 255) /
byGreenMask;
lpPalette->palPalEntry[i].peBlue =
(((i >> pfd.cBlueShift) & byBlueMask) * 255) /
byBlueMask;
lpPalette->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<iGraphs; k++)
{
if ((0==(k % iPies)) && (k >= 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)
{
float fDisplAngRadians; // Displacement angle grads
float fAngleRadians;
float fSweepAngleRadians;
int iInitialAngleGrads;
int i;
int j;
int k;
k = kGraph;
glClearColor(1.0, 1.0, 1.0, 0.0);
iInitialAngleGrads = 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:
iInitialAngleGrads = iRelativeInitialAngleGrads;
break;
case 1 :
iInitialAngleGrads = iInitialAngleGrads + iAngleGrads[k][j-1];
break;
case 2 :
iInitialAngleGrads = iInitialAngleGrads + iAngleGrads[k][j-1];
break;
default:
break;
}
// We calculate here the displacement of the center
fDisplAngRadians =
((float)iInitialAngleGrads +
(float)(iAngleGrads[k][j]) / 2.0) * (PI/180.0);
// 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 (fDisplRadFact*cos(fDisplAngRadians),
fDisplRadFact*sin(fDisplAngRadians), 0.0);
for (i=0; i<=(2*iAngleGrads[k][j]); i++)
{
fAngleRadians = (((float)(iInitialAngleGrads*PI) + ((float)(i/2.0)*PI)))/180.0;
glVertex3f(
fRadiusFactor * cos(fAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
0);
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3f (fDisplRadFact*cos(fDisplAngRadians),
fDisplRadFact*sin(fDisplAngRadians), fHeight);
for (i=0; i<=(2*iAngleGrads[k][j]); i++)
{
fAngleRadians = (((float)(iInitialAngleGrads*PI) + ((float)(i/2.0)*PI)))/180.0;
glVertex3f(
fRadiusFactor * cos(fAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
fHeight);
}
glEnd();
SetDarkColor(j);
if ((k==2) && (j==1) && (iAngleGrads[k][j]==360))
glColor4f(0.5, 0.5, 0.5, 1.0);
glBegin(GL_QUAD_STRIP);
for (i=0; i<=(2*iAngleGrads[k][j]); i++)
{
fAngleRadians = (((float)(iInitialAngleGrads*PI) + ((float)(i/2.0)*PI)))/180.0;
glVertex3f(
fRadiusFactor * cos(fAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
0);
glVertex3f(
fRadiusFactor * cos(fAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
fHeight);
}
glEnd();
fSweepAngleRadians = fAngleRadians;
fAngleRadians = ((iInitialAngleGrads) * PI) / 180.0;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS);
glVertex3f (fDisplRadFact*cos(fDisplAngRadians),
fDisplRadFact*sin(fDisplAngRadians), 0.0);
glVertex3f(
fRadiusFactor * cos(fAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
0);
glVertex3f(
fRadiusFactor * cos(fAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
fHeight);
glVertex3f (fDisplRadFact*cos(fDisplAngRadians),
fDisplRadFact*sin(fDisplAngRadians), fHeight);
glEnd();
glBegin(GL_QUADS);
glVertex3f (fDisplRadFact*cos(fDisplAngRadians),
fDisplRadFact*sin(fDisplAngRadians), 0.0);
glVertex3f(
fRadiusFactor * cos(fSweepAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fSweepAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
0);
glVertex3f(
fRadiusFactor * cos(fSweepAngleRadians)+fDisplRadFact*cos(fDisplAngRadians),
fRadiusFactor * sin(fSweepAngleRadians)+fDisplRadFact*sin(fDisplAngRadians),
fHeight);
glVertex3f (fDisplRadFact*cos(fDisplAngRadians),
fDisplRadFact*sin(fDisplAngRadians), 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();
}