Qt5.12+OpenGL 计算机图形学(第四版)第4章 例子1
程序员文章站
2024-03-17 17:32:34
...
因为使用的是Qt框架,没有使用GLUT,所以改写了书中部分代码:
1. 文本用QString数组保存。
2. 绘制字符没有使用GLUT函数,直接使用QPainter进行绘制,Qt绘图坐标是以左上角为原点(0,0),因此,坐标也需要进行变换。
关键部分源代码,其它可以参照前面章节的例子。
a. 绘制折线图
QString label[12] = {
"Jan", "Feb", "Mar", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
GLint dataValue[12] = {
420, 342, 324, 310, 262, 185, 190, 196, 217, 240, 312, 438
};
void OpenGLWidget::lineGraph()
{
GLint month, k;
GLint xRaster = 20;
GLint yRaster = 150;
GLint x = 30;
int h = this->height();
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();
QPainter painter(this);
painter.setPen(Qt::red);
painter.setFont(QFont("Arial", 10));
for(k=0; k<12; k++) {
painter.drawText(x+k*50-5, h-dataValue[k]+10, "*");
}
painter.setPen(Qt::black);
painter.setFont(QFont("Helvecica", 12));
for(month=0; month<12; month++) {
for(k=3*month; k<3*month+3; k++)
painter.drawText(xRaster, h - yRaster, label[month]);
xRaster += 50;
}
glFlush();
}
效果图:
b. 绘制直方图
void OpenGLWidget::barChart()
{
GLint month, k;
GLint xRaster = 20;
GLint yRaster = 150;
int h = this->height();
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]);
QPainter painter(this);
painter.setPen(Qt::black);
painter.setFont(QFont("Helvecica", 12));
for(month=0; month<12; month++) {
for(k=3*month; k<3*month+3; k++)
painter.drawText(xRaster, h - yRaster, label[month]);
xRaster += 50;
}
}
效果图:
c. 绘制饼图
关于中点画圆的算法可以参考https://www.cnblogs.com/clairvoyant/p/5528067.html这篇文章,讲得还是比较清楚的。
GLsizei winWidth = 400, winHeight = 300;
const GLdouble twoPi = 6.283185;
void OpenGLWidget::pieChart()
{
QPoint circCtr, piePt;
GLint radius = winWidth / 4;
GLdouble sliceAngle, previousSliceAngle = 0.0;
GLint k, nSlices = 12;
GLfloat dataValues[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.setX(winWidth / 2);
circCtr.setY(winHeight / 2);
circleMidpoint(circCtr, radius);
for(k=0; k<nSlices; k++) {
dataSum += dataValues[k];
}
for(k=0; k<nSlices; k++) {
sliceAngle = twoPi * dataValues[k] / dataSum + previousSliceAngle;
piePt.setX(circCtr.x() + radius * cos(sliceAngle));
piePt.setY(circCtr.y() + radius * sin(sliceAngle));
glBegin(GL_LINES);
glVertex2i(circCtr.x(), circCtr.y());
glVertex2i(piePt.x(), piePt.y());
glEnd();
previousSliceAngle = sliceAngle;
}
}
void putpixel(int x0, int y0, int x, int y)
{
glBegin(GL_POINTS);
glVertex2f(x0 + x, y0 + y);
glVertex2f(x0 + x, y0 - y);
glVertex2f(x0 - x, y0 + y);
glVertex2f(x0 - x, y0 - y);
glVertex2f(x0 + y, y0 + x);
glVertex2f(x0 + y, y0 - x);
glVertex2f(x0 - y, y0 + x);
glVertex2f(x0 - y, y0 - x);
glEnd();
}
/*
* 通过中点和半径画圆
*/
void OpenGLWidget::circleMidpoint(QPoint c, int r)
{
int x, y, p;
x = 0; y = r; p = 1 - r;
while(x <= y) {
putpixel(c.x(), c.y(), x, y);
if ( p < 0 ) {
p += 2 * x + 1;
} else {
p += 2 * (x - y) + 1;
y--;
}
x++;
}
}
效果图: