OpenGL从1.0开始--绘制常用统计图

通过前面几节的学习,我们已经有能力实现一些高级的图形绘制功能。这一节我们给大家示例折线图、直方图和饼状图的绘制程序。
我们先看看要实现的效果。
这里写图片描述
下面我们默认大家已经掌握了前面的知识,并会把讲解的重点放在高级功能上。

#include <gl/glut.h>

GLsizei winWidth = 600, winHeight = 500;

GLubyte label[36] = { 'J', 'a', 'n', 'F', 'e', 'b', 'M', 'a', 'r',
'A', 'p', 'r', 'M', 'a', 'y', 'J', 'u', 'n',
'J', 'u', 'l', 'A', 'u', 'g', 'S', 'e', 'p', 'O', 'c', 't', 'N', 'o', 'v', 'D', 'e', 'c' };//月份标签数组
GLint dataValue[12] = { 420, 342, 324, 310, 262, 185, 190, 196, 217, 240, 312, 438 };//折线图数值项,对应12个月
void init(void)
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 600.0, 0.0, 500.0);
}
void linegraph(void)
{
    GLint xRaster = 25, yRaster = 150;//初始光标位置
    GLint month, k;
    GLint x = 30;
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0, 0.0, 1.0);
    glBegin(GL_LINE_STRIP);
    for (k = 0; k < 12; k++)
        glVertex2i(x + k * 50, dataValue[k]);//绘制折线
    glEnd();
    glColor3f(1.0, 0.0, 0.0);
    for (k = 0; k < 12;k++)
    {
        glRasterPos2i(xRaster + k * 50, dataValue[k] - 4);光标跟踪折线节点
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, '*');//折线节点上绘制的‘*’
    }
    glColor3f(0.0, 0.0, 0.0);
    xRaster = 20;//重置光标位置
    for (month = 0; month < 12;month++)
    {
        glRasterPos2i(xRaster, yRaster);
        for (k = 3 * month; k < 3 * month + 3;k++)
        {
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, label[k]);//标注月份

        }
        xRaster += 50;
    }
    glFlush();
}
void winReshapeFcn(GLint newWidth, GLint newHeight)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight));
    glClear(GL_COLOR_BUFFER_BIT);
}
void main(int argc, char**argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(winWidth, winHeight);
    glutCreateWindow("Line Chart Data Plot");
    init();
    glutDisplayFunc(linegraph);
    glutReshapeFunc(winReshapeFcn);
    glutMainLoop();
}

大家可以看到,看似复杂的折线图,我们通过将其元素分解为折线,‘*’节点,月份标注分别进行绘制,整个过程非常简单。在这里给大家提出一个小问题,如果将光标位置变量设置为全局变量,程序结果会出现什么变化呢?

直方图的代码也是同样非常简单,下面给大家提供一个示例。
这里写图片描述

void barChart(void)
{
    GLint xRaster = 20, yRaster = 150;
    GLint month, k;
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    for (k = 0; k < 12; k++)        
    {
        glRecti(20 + k * 50, 165, 40 + k * 50, dataValue[k]);//直方图条状图
    }
    glColor3f(0.0, 0.0, 0.0);
    for (month = 0; month < 12;month++)
    {
        glRasterPos2i(xRaster, yRaster);
        for (k = 3 * month; k < 3 * month + 3;k++)
        {
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, label[k]);//标注

        }
        xRaster += 50;
    }
    glFlush();
}

最后再给大家画一个简单的饼状图,大家可以试试自己去添加注释等信息。
这里写图片描述


#include <gl/glut.h>
#include <stdlib.h>
#include <math.h>
const GLdouble twoPi = 6.283185;
class scrPt{
public:
    GLint x, y;
};
GLsizei winWidth = 400, winHeight = 300;
void init(void)
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 200.0, 0.0, 150.0);
}
void circleMidpoint(scrPt mid, GLint r)//画圆函数
{
    int i = 0;
    glBegin(GL_LINE_LOOP);//通过细分曲线趋近圆形
    int n = 120;
    for (i = 0; i < n; i++)
    {
        glVertex2f(r*cos(twoPi / n*i) + mid.x, r*sin(twoPi / n*i) + mid.y);//圆上的连续点
    }
    glEnd();
}
void pieChart(void)
{
    scrPt circCtr, piePt;
    GLint radius = winWidth / 4;
    GLdouble sliceAngle, previousSliceAngle = 0.0;
    GLint k, nSlice = 12;
    GLfloat dataValue[12] = { 10.0, 7.0, 13.0, 5.0, 13.0, 14.0, 3.0, 16.0, 5.0, 3.0, 17.0, 8.0 };//单月份数
    GLfloat dataSum = 0.0;
    circCtr.x = winWidth / 2;//圆心
    circCtr.y = winHeight / 2;
    circleMidpoint(circCtr, radius);//根据圆心和半径画圆
    for (k = 0; k < nSlice;k++)
    {
        dataSum += dataValue[k];//计算总份数
    }
    for (k = 0; k < nSlice;k++)
    {
        sliceAngle = twoPi*dataValue[k] / dataSum + previousSliceAngle;//扇形边界线的角度
        piePt.x = circCtr.x + radius*cos(sliceAngle);//扇形边界线端点的坐标
        piePt.y = circCtr.y + radius*sin(sliceAngle);
        glBegin(GL_LINES);
        glVertex2i(circCtr.x, circCtr.y);
        glVertex2i(piePt.x, piePt.y);//绘制扇形边界线
        glEnd();
        previousSliceAngle = sliceAngle;//更新扇形边界线角度
    }
}
void displayFcn(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0, 0.0, 1.0);
    pieChart();
    glFlush();
}
void winReshapeFcn(GLint newWidth, GLint newHeight)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight));
    glClear(GL_COLOR_BUFFER_BIT);
    winWidth = newWidth;
    winHeight = newHeight;
}
void main(int argc, char**argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(winWidth, winHeight);
    glutCreateWindow("Line Chart Data Plot");
    init();
    glutDisplayFunc(displayFcn);
    glutReshapeFunc(winReshapeFcn);
    glutMainLoop();
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值