当前位置: 首页 > news >正文

openGl绘制五星红旗

目录

  • 一、核心思路
    • 1. 分析五星红旗各个比例、尺寸
      • 1. 红色旗面:
      • 2. 五角星:
    • 2. 绘制思路
  • 二、源码


一、核心思路

1. 分析五星红旗各个比例、尺寸

在这里插入图片描述

1. 红色旗面:

长宽比 3:2

2. 五角星:

至于绘制五角星的方法,详情参考我的另一篇博客VS-openGL 绘制五角星

(1)位置与内外接圆半径

前提 将红色旗面等分为四个矩形,再将左上角矩形长等分为15份,宽等分为10份,这里每份大小为单位1,并以左上角的顶点为原点,来记录各个五角星的坐标。
大五角星 圆心(5,-5),外接圆半径R=3,内接圆半径r=1.15;
小五角星 ①(10,-2),②(12,-4),③(12,-7),④(10,-9),外接圆半径R=1,内接圆半径r=0.38
举例:绘制长300宽200的国旗,国旗左上顶点(x,y),则大五角星的属性应当进行如下计算:
将长300的国旗等分为四个矩形,每个矩形的长度为300÷2=150,将矩形等分为15份,每份的大小为150÷15=10,则大五角星的圆心坐标为(x + 5 * 10 , y - 5 * 10),外接圆半径R=3 * 10,内接圆半径r=1.15 * 10。小五角星同理省略…

(2)小五角星指向问题

前提

  • 我绘制的五角星,默认有一个外顶点是竖直向上的;
  • 五星红旗中四个小五角星都有一个外顶点指向大五角星的圆心;

综上所述:我们需要将绘制出来的部分小五角星进行旋转(去指向大五角星的圆心),为了便于计算旋转的角度,我默认将竖直向上的那个外顶点旋转至指向大五角星的圆心。

旋转角度 每个小五角星都有自己的β角(并固定的某一个角),可以看我给的图片,有标注

  • 小五角星①:逆时针旋转180°-β角度,cosβ=3/(根号34),通过cos值,推算β值(通过余弦值计算度数的网站),β=59.3°,旋转度数:180°-59.3°= 120.7°
  • 小五角星②:逆时针旋转Π-β角度,cosβ=1/[5*(根号2)],β=81.9°,旋转度数:98.1°
  • 小五角星③:不用旋转
  • 小五角星④:逆时针旋转β角度,cosβ=4/(根号41),β=51.6°

2. 绘制思路

思路如下:(也是编写代码的思路)

  1. 绘制红色旗面
  2. 绘制大五角星
  3. 绘制小五角星

二、源码

#include <GL/glew.h>//OpenGL扩展库
#include <GL/glut.h>//OpenGL工具库
#include <stdio.h>
#include <math.h>


// 定义Π
#define PI 3.14159265

// 定义坐标结构体
struct Vertex {
	double x;
	double y;
};

// ####绘制五角星方法####

// 绘制黄色三角形函数
void drawYellowTriangle(Vertex Vertex_Fir, Vertex Vertex_Sec, Vertex Vertex_Thi) {
	// 设置填充的颜色
	glColor3f(255, 255, 0);
	// 设置绘制类型
	glBegin(GL_TRIANGLES);
	// 第一个坐标
	glVertex2f(Vertex_Fir.x, Vertex_Fir.y);
	// 第二个坐标
	glVertex2f(Vertex_Sec.x, Vertex_Sec.y);
	// 第三个坐标
	glVertex2f(Vertex_Thi.x, Vertex_Thi.y);
	glEnd();
}

// 获取外圆五角星的五顶点(参数:大圆圆心坐标以及半径)
Vertex* getExternalVertex(Vertex Center_Vertex, double R) {
	// 定义Vertex结构体数组,包括五个顶点和一个圆心
	Vertex* externalVertex = new Vertex[6];
	double alpha = 2 * PI / 5;
	double thet = PI / 10;
	double bet = 2 * PI / 10;
	// 圆心坐标
	externalVertex[0].x = Center_Vertex.x, externalVertex[0].y = Center_Vertex.y;
	// 其余五个顶点
	externalVertex[1].x = Center_Vertex.x, externalVertex[1].y = Center_Vertex.y + R;
	externalVertex[2].x = Center_Vertex.x + R * cos(thet), externalVertex[2].y = Center_Vertex.y + R * sin(thet);
	externalVertex[3].x = Center_Vertex.x + R * sin(bet), externalVertex[3].y = Center_Vertex.y - R * cos(bet);
	externalVertex[4].x = Center_Vertex.x - R * sin(bet), externalVertex[4].y = Center_Vertex.y - R * cos(bet);
	externalVertex[5].x = Center_Vertex.x - R * cos(thet), externalVertex[5].y = Center_Vertex.y + R * sin(thet);
	return externalVertex;
}

// 获取内圆五角星的五顶点(参数:小圆圆心坐标以及半径)
Vertex* getInternalVertex(Vertex Center_Vertex, double r) {
	// 定义Vertex结构体数组,包括五个顶点和一个圆心
	Vertex* internalVertex = new Vertex[6];
	double alpha = 2 * PI / 5;
	double thet = PI / 10;
	double bet = (PI - alpha) / 2;
	// 圆心坐标
	internalVertex[0].x = Center_Vertex.x, internalVertex[0].y = Center_Vertex.y;
	// 其余五个顶点
	internalVertex[1].x = Center_Vertex.x + r * cos(bet), internalVertex[1].y = Center_Vertex.y + r * sin(bet);
	internalVertex[2].x = Center_Vertex.x + r * cos(thet), internalVertex[2].y = Center_Vertex.y - r * sin(thet);//
	internalVertex[3].x = Center_Vertex.x, internalVertex[3].y = Center_Vertex.y - r;//
	internalVertex[4].x = Center_Vertex.x - r * cos(thet), internalVertex[4].y = Center_Vertex.y - r * sin(thet);
	internalVertex[5].x = Center_Vertex.x - r * cos(bet), internalVertex[5].y = Center_Vertex.y + r * sin(bet);
	return internalVertex;
}

// ####绘制红旗方法####

// 绘制红色矩阵函数
void drawRedRect(Vertex* vertex) {
	// 设置绘制类型
	glShadeModel(GL_FLAT);
	glBegin(GL_POLYGON);
	// 设置填充的颜色,默认以第一个点的颜色进行纯色填充
	glColor3f(1, 0, 0);
	// 第一个坐标
	glVertex2f(vertex[0].x, vertex[0].y);
	// 第二个坐标
	glVertex2f(vertex[1].x, vertex[1].y);
	// 第三个坐标
	glVertex2f(vertex[2].x, vertex[2].y);
	// 第四个坐标
	glVertex2f(vertex[3].x, vertex[3].y);
	glEnd();
}


// 设置背景颜色
void setBackgroundColor(void) {
	glClearColor(0.2, 0.3, 0.3, 0.5);
}



// 绘制国旗
void draw(void) {
	// 清除清缓存
	glClear(GL_COLOR_BUFFER_BIT);

	// ### 一、绘制红色矩形 ###
	Vertex* rectVertex=new Vertex[4];
	rectVertex[0].x = 10, rectVertex[0].y = 410;//左上角(高1000)
	rectVertex[1].x = 10, rectVertex[1].y = 10;//左下角
	rectVertex[2].x = 610, rectVertex[2].y = 10;//右下角(宽1500)
	rectVertex[3].x = 610, rectVertex[3].y = 410;//右上角
	drawRedRect(rectVertex);

	// ### 二、绘制五角星 ###

	// # <1>大五角星 #
	// 1. 定义圆心、大小圆半径
	Vertex Center_Vertex;
	Center_Vertex.x = 110, Center_Vertex.y = 310;//圆心以显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向
	double R = 60;
	double r = 23;
	// 2. 获取内外顶点
	Vertex* externalVertex = getExternalVertex(Center_Vertex, R);
	Vertex* internalVertex = getInternalVertex(Center_Vertex, r);
	// 3. 绘制黄色五角星
	for (int i = 1; i < 6; i++) {
		drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
		if (i < 5) {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i + 1]);
		}
		else {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
		}
	}

	// # <2>小五角星① #
	// 1. 定义圆心、大小圆半径
	Center_Vertex.x = 210, Center_Vertex.y = 370;//圆心以显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向
	R = 20;
	r = 7.6;
	// 2. 获取内外顶点
	externalVertex = getExternalVertex(Center_Vertex, R);
	internalVertex = getInternalVertex(Center_Vertex, r);

	// 3.几何变换(旋转一定角度)
	glPushMatrix();//几何变换的边界起点
	glTranslatef(210, 370, 0);//移动回初始位置
	glRotatef(120.7, 0, 0, 1);//绕z轴旋转,即xoy平面以原点为中心逆时针旋转
	glTranslatef(-210, -370, 0);//移动回原点
	

	// 4. 绘制黄色五角星
	for (int i = 1; i < 6; i++) {
		drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
		if (i < 5) {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i + 1]);
		}
		else {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
		}
	}

	glPopMatrix();//几何变换的边界终点(只对边界内的图形进行几何变换)
	


	// # <3>小五角星② #
	// 1. 定义圆心、大小圆半径
	Center_Vertex.x = 250, Center_Vertex.y = 330;//圆心以显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向
	R = 20;
	r = 7.6;
	// 2. 获取内外顶点
	externalVertex = getExternalVertex(Center_Vertex, R);
	internalVertex = getInternalVertex(Center_Vertex, r);
	// 3.几何变换(旋转一定角度)
	glPushMatrix();//几何变换的边界起点
	glTranslatef(250, 330, 0);//移动回初始位置
	glRotatef(98.1, 0, 0, 1);//绕z轴旋转,即xoy平面以原点为中心逆时针旋转
	glTranslatef(-250, -330, 0);//移动回原点
	// 4. 绘制黄色五角星
	for (int i = 1; i < 6; i++) {
		drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
		if (i < 5) {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i + 1]);
		}
		else {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
		}
	}
	glPopMatrix();//几何变换的边界终点(只对边界内的图形进行几何变换)



	// # <4>小五角星③ #
	// 1. 定义圆心、大小圆半径
	Center_Vertex.x = 250, Center_Vertex.y = 270;//圆心以显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向
	R = 20;
	r = 7.6;
	// 2. 获取内外顶点
	externalVertex = getExternalVertex(Center_Vertex, R);
	internalVertex = getInternalVertex(Center_Vertex, r);
	// 3. 绘制黄色五角星
	for (int i = 1; i < 6; i++) {
		drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
		if (i < 5) {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i + 1]);
		}
		else {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
		}
	}
	


	// # <5>小五角星④ #
	// 1. 定义圆心、大小圆半径
	Center_Vertex.x = 210, Center_Vertex.y = 230;//圆心以显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向
	R = 20;
	r = 7.6;
	// 2. 获取内外顶点
	externalVertex = getExternalVertex(Center_Vertex, R);
	internalVertex = getInternalVertex(Center_Vertex, r);
	// 3.几何变换(旋转一定角度)
	glPushMatrix();//几何变换的边界起点
	glTranslatef(210, 230, 0);//移动回初始位置
	glRotatef(51.6, 0, 0, 1);//绕z轴旋转,即xoy平面以原点为中心逆时针旋转
	glTranslatef(-210, -230, 0);//移动回原点
	// 4. 绘制黄色五角星
	for (int i = 1; i < 6; i++) {
		drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
		if (i < 5) {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[i + 1]);
		}
		else {
			drawYellowTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
		}
	}
	glPopMatrix();//几何变换的边界终点(只对边界内的图形进行几何变换)

	glutSwapBuffers();//交换缓冲(双缓冲时使用)
}

void reshape(int width, int height)
{
	glViewport(0, 0, width, height);//设置视区

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, width, 0, height);//设置图形数据范围
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int main() {
	// 窗口的坐标是电脑屏幕左上角为原点,向右为x轴正方向;向下为y轴正方向
	glutInitWindowPosition(10, 10); //定义窗口位置与大小
	glutInitWindowSize(1200, 700);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); //初始化显示模式
	glutCreateWindow("五星红旗"); //定义窗口名称

	setBackgroundColor(); // 设置背景色

	glutDisplayFunc(draw); //图形绘制函数
	glutReshapeFunc(reshape); //窗口重绘函数
	glutMainLoop(); //无限循环函数 
	return 0;
}

编码中的一些问题与思考 :我绘制的五角星是由多个三角形多次绘画构成的,那么我进行几何变换(旋转)的时候如何让整个五角星都进行旋转,而不是只有其中某个三角进行了旋转?
个人理解的答案 :将需要旋转的图形的绘制代码,放在一个边界之内 (glPushMatrix();),则边界内的才会进行几何变换,边界外的不受影响。
详情参考OpenGL图像平移、旋转基本操作总结

相关文章:

  • 【数据结构】二叉树
  • HTML常用标签二
  • 高数(下) 第十二章:无穷级数
  • 【GOF】三种工厂模式~
  • 算法 |【实验5.2】1-深度优先搜索暴力求解旅行商问题
  • OpenCV-Python学习(2)—— OpenCV 图像的读取和显示
  • Unity技术手册-初识编辑器(上)
  • 基于Java+SpringBoot+vue+elementui图书商城系统设计实现
  • 电子病历结构化之实体识别(附完整项目代码)
  • 手写Spring——bean的扫描、加载和实例化
  • 【Vue】Vue的v-if、v-if-else、v-else-if、v-show的使用
  • 【设计模式】创建型模式:单例模式
  • Sentry、Loki 轻量级日志系统部署及应用
  • Spring Boot 统一功能处理
  • qsort:我很强,了解一下(详解过程)
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • interface和setter,getter
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Javascript 原型链
  • Making An Indicator With Pure CSS
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • 闭包--闭包之tab栏切换(四)
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 从0到1:PostCSS 插件开发最佳实践
  • 从PHP迁移至Golang - 基础篇
  • 大主子表关联的性能优化方法
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 利用jquery编写加法运算验证码
  • 浅谈Golang中select的用法
  • 区块链分支循环
  • 详解NodeJs流之一
  • 新书推荐|Windows黑客编程技术详解
  • linux 淘宝开源监控工具tsar
  • #laravel 通过手动安装依赖PHPExcel#
  • #stm32整理(一)flash读写
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (ibm)Java 语言的 XPath API
  • (Java)【深基9.例1】选举学生会
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (poj1.3.2)1791(构造法模拟)
  • (独孤九剑)--文件系统
  • (二)正点原子I.MX6ULL u-boot移植
  • (六)软件测试分工
  • (循环依赖问题)学习spring的第九天
  • ******之网络***——物理***
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • @DataRedisTest测试redis从未如此丝滑
  • @requestBody写与不写的情况
  • [acwing周赛复盘] 第 94 场周赛20230311