前言
实现五角星和五边形的相互转换。
一、题目描述
正五边形和五角星有共同的五个顶点,编写程序实现这两个图形的相互变换过程。
二、环境
使用Visual Studio2019的开发环境,使用opengl编写
三、实现过程
首先确定五个点的坐标,可以把一个圆等分五分进而找到。对这五个点进行连线就可以得到一个五边形。假设五边形最高点记为1,顺时针旋转依次得到各点为2、3、4、5。
那么五边形变化为五角星可以由各点的移动得到,即2->3,3->5,4->2,5->4,而顶点1的位置始终不变化,而从五角星变化为五边形就是个逆过程,可以把从0递增至1的参数t再递减至0就可以实现。再定时调用是坐标轨迹改变的函数就可以实现二者的相互转换。
三、代码实现
pentagram.cpp
#include <Gl/glut.h>
#include <iostream>
#include <Windows.h>
#include <math.h>
using namespace std;
const GLdouble Pi = 3.1415926536f;
/**
* 五角星各个点坐标位置大约如下所示
* 1
* 5 2
* 4 3
*
*/
GLdouble a = 0.8; //顶点的纵坐标
GLdouble bx = a * cos(18 * Pi / 180); //为求方便,赋为定值
GLdouble by = a * sin(18 * Pi / 180);
GLdouble cx = a * cos(54 * Pi / 180);
GLdouble cy = -a * sin(54 * Pi / 180);
GLdouble t = 0.0; //
GLdouble x1 = 0; //因为相对y轴对称,所以只需改变正负号
GLdouble y11 = a ;
GLdouble x2 = bx;
GLdouble y2 = by;
GLdouble x3 = cx;
GLdouble y3 = cy;
GLdouble x4 = -cx;
GLdouble y4 = cy;
GLdouble x5 = -bx;
GLdouble y5 = by;
bool count1 = 1; //决定五边形变为五角星
bool count2 = 0; //决定五角星变为五边形
void display(void)
{
glLoadIdentity();//恢复初始坐标系
glClearColor(0, 0, 0, 0); //glClearColor 函数指定 glClear用于清除颜色缓冲区的红色、绿色、蓝色和 alpha 值,清除颜色设为黑色
glClear(GL_COLOR_BUFFER_BIT); //清除颜色缓冲以及深度缓冲,把整个窗口清除为黑色的任务
glColor4f(1, 1, 1, 0); //设定的是绘笔的颜色,即绘制出的图形颜色值
glPushMatrix();//调用glPushMatrix其实就是把当前状态做一个副本放入堆栈之中
//做了一些移动或旋转等变换后,使用glPushMatrix();OpenGL 会把这个变换后的位置和角度保存起来。
glBegin(GL_LINE_LOOP); //绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,
//第n和n + 1个顶点定义了线段n,绘制n条线段。
//指定点
glVertex2f(x1, y11);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glVertex2f(x4, y4);
glVertex2f(x5, y5);
glEnd();
glPopMatrix();//做第二次移动或旋转变换,再用glPopMatrix();OpenGL 就把刚刚保存的那个位置和角度恢复。
glutSwapBuffers(); // 交换缓冲区
}
void move(int d)
{
if (count1) //五边形变为五角星
{
x2 = (1 - t) * bx + t * cx; //2->3
y2 = (1 - t) * by + t * cy;
x3 = (1 - t) * cx - t * bx; //3->5
y3 = (1 - t) * cy + t * by;
x4 = -(1 - t) * cx + t * bx; //4->2
y4 = (1 - t) * cy + t * by;
x5 = -(1 - t) * bx - t * cx; //5->4
y5 = (1 - t) * by + t * cy;
t = t + 0.01;
//cout << t << endl;
//再次循环
if (y4 >= by) {
count1 = 0;
count2 = 1;
}
}
if (count2) //五角星变为五边形
{
x2 = (1 - t) * bx + t * cx; //2->3
y2 = (1 - t) * by + t * cy;
x3 = (1 - t) * cx - t * bx; //3->5
y3 = (1 - t) * cy + t * by;
x4 = -(1 - t) * cx + t * bx; //4->2
y4 = (1 - t) * cy + t * by;
x5 = -(1 - t) * bx - t * cx; //5->4
y5 = (1 - t) * by + t * cy;
t = t - 0.01;
if (y4 <= cy) {
count1 = 1;
count2 = 0;
}
}
display();
glutTimerFunc(33, move, 1); //每隔33毫秒调用一次move()函数
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv); //初始化GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);//双缓冲区窗口,默认颜色模式
//glutInitWindowPosition(100, 100);//确定窗口位置,距离屏幕左边和上边的像素数,
glutInitWindowSize(500, 500);//窗口的宽度和高度
glutCreateWindow("pentagram");//创建窗口
glutDisplayFunc(&display); //函数负责渲染,调用该函数
move(1);
glutMainLoop(); //持续显示,当窗口改变会重新绘制图形
return 0;
}
四、运行结果
可以展现五边形和五角星之间的动态转换过程,下面展示在变化过程中的两个状态:
总结
虽然上述代码能够实现要求,但是代码不够简洁,需要修正。继续努力!另代码参考有其他博主的思考,但由于时间久远,我已记不得当初参考的文章,见谅。