统计图表

根据书上的例子,简单绘制了统计图表。

只是为了达到效果,没有进行面向对象的封装。

#include<Windows.h>
#include<GL/glut.h>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

const double PI = acos(-1.0);
GLsizei width = 800, height = 600;

char month[12][5] =
{
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
};

int monthData[12] = { 420, 342, 324, 310, 262, 185, 190, 196, 217, 240, 312, 438 };

struct Pos
{
    Pos(){}
    Pos(int _x, int _y) :
        x(_x), y(_y){}

    int x, y;
};

void pieChart();

void reshape(int w, int h)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}

void lineChart()
{
    glColor3d(0.0, 0.0, 0.0);
    int interval = width / 14;
    Pos pos = Pos(interval, height / 5);
    for (int i = 0; i < 12; ++i)
    {
        glRasterPos2i(pos.x, pos.y);
        for (int j = 0; j < 3; ++j)
        {
            glutBitmapCharacter(GLUT_BITMAP_8_BY_13, month[i][j]);
        }
        pos.x += interval;
    }

    int maxx = *max_element(monthData, monthData + 12) + 50;
    pos = Pos(interval, height / 5);
    int portion = height * 4 / 5;
    glBegin(GL_LINE_STRIP);
    {
        for (int i = 0; i < 12; ++i)
        {
            glVertex2i(pos.x + 10, pos.y + portion * monthData[i] / maxx);
            pos.x += interval;
        }

    }
    glEnd();

    glFlush();
}

void barChart()
{
    glColor3d(0.0, 0.0, 0.0);
    int interval = width / 14;
    Pos pos = Pos(interval, height / 5);
    for (int i = 0; i < 12; ++i)
    {
        glRasterPos2i(pos.x, pos.y);
        for (int j = 0; j < 3; ++j)
        {
            glutBitmapCharacter(GLUT_BITMAP_8_BY_13, month[i][j]);
        }
        pos.x += interval;
    }

    int maxx = *max_element(monthData, monthData + 12) + 50;
    pos = Pos(interval, height / 5);
    int portion = height * 4 / 5;

    glColor3d(0.0, 0.9, 0.0);
    for (int i = 0; i < 12; ++i)
    {
        glRecti(pos.x, pos.y + 50, pos.x + 20, pos.y + portion * monthData[i] / maxx);
        pos.x += interval;
    }

    glFlush();
}

void pieChart()
{
    Pos center = Pos(width / 2, height / 2);
    int radius = 150;
    glColor3d(0.0, 0.0, 0.0);
    glBegin(GL_LINE_LOOP);
    {
        for (int i = 0; i < 360; ++i)
        {
            double theta = PI * i / 180;
            glVertex2d(center.x + radius * cos(theta), center.y + radius * sin(theta));
        }
    }
    glEnd();

    int sum = 0;
    for (int i = 0; i < 12; ++i) sum += monthData[i];
    glBegin(GL_LINES);
    {
        double portion = 0.0;
        for (int i = 0; i < 12; ++i)
        {
            portion += (double)monthData[i] / sum;
            double theta = portion * 2 * PI;
            glVertex2d(center.x, center.y);
            glVertex2d(center.x + radius * cos(theta), center.y + radius * sin(theta));
        }
    }
    glEnd();

    glFlush();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(width, height);
    glutCreateWindow("Chart");
    glClearColor(1.0, 1.0, 1.0, 0.0);

    glutReshapeFunc(reshape);
    glutDisplayFunc(pieChart);

    glutMainLoop();
}