这一篇将提供一套生成五星红旗的算法,代码中满满都是正能量。上一篇文章是生成N芒星,五角星是就芒星的一种,所以不难生成一个五角星的图像。中华人民共和国国旗是五星红旗,旗面为红色,长宽比例为3:2。左上方缀黄色五角星五颗,四颗小星环拱在一颗大星的右面,并各有一个角尖正对大星的中心点。1、4颗黄星对齐,2、3颗黄星对齐。
代码如下:
h
1 class CPixel5StarsRedFlag : public IPixelEquation
2 {
3 public:
4 CPixel5StarsRedFlag();
5
6 const char* GetName() const
7 {
8 return "Five Stars Red Flag";
9 }
10
11 unsigned int CalculatePixel(unsigned int x, unsigned int y);
12
13 struct Star
14 {
15 float posX;
16 float posY;
17 float radius;
18 float angle;
19 };
20 bool IsPointInStar(float x, float y, Star& star);
21
22 private:
23 float m_list_sin[5];
24 float m_list_cos[5];
25
26 Star m_list_stars[5];
27 };
头文章中定义了一个结构体Star,用于决定五角星的位置,大小,旋转角度。需要为每一颗星设置其合适的数值,我提供的代码所用参数是我多次试出来的,与实际不会绝对地相符。
cpp
1 CPixel5StarsRedFlag::CPixel5StarsRedFlag()
2 {
3 m_width = 1680;
4 m_height = 1120;
5
6 for (int i = 0; i < 5; i++)
7 {
8 m_list_sin[i] = sinf((i - 0.5f)*2*PI/5);
9 m_list_cos[i] = cosf((i - 0.5f)*2*PI/5);
10 }
11
12 m_list_stars[0].posX = m_width*0.2f;
13 m_list_stars[0].posY = m_height*0.35f;
14 m_list_stars[0].radius = m_height*0.1f;
15 m_list_stars[0].angle = 0.0f;
16
17 float r = m_list_stars[0].radius * 3.0f;
18
19 m_list_stars[1].posX = m_list_stars[0].posX + r*cosf(PI/4);
20 m_list_stars[1].posY = m_list_stars[0].posY + r*sinf(PI/4);
21 m_list_stars[1].radius = m_list_stars[0].radius*0.5f;
22 m_list_stars[1].angle = -PI/8;
23
24 m_list_stars[2].posX = m_list_stars[0].posX + r*cosf(PI/12);
25 m_list_stars[2].posY = m_list_stars[0].posY + r*sinf(PI/12);
26 m_list_stars[2].radius = m_list_stars[0].radius*0.5f;
27 m_list_stars[2].angle = -PI/24;
28
29 m_list_stars[3].posX = m_list_stars[0].posX + r*cosf(-PI/12);
30 m_list_stars[3].posY = m_list_stars[0].posY + r*sinf(-PI/12);
31 m_list_stars[3].radius = m_list_stars[0].radius*0.5f;
32 m_list_stars[3].angle = PI/24;
33
34 m_list_stars[4].posX = m_list_stars[0].posX + r*cosf(-PI/4);
35 m_list_stars[4].posY = m_list_stars[0].posY + r*sinf(-PI/4);
36 m_list_stars[4].radius = m_list_stars[0].radius*0.5f;
37 m_list_stars[4].angle = PI/8;
38 }
39
40 bool CPixel5StarsRedFlag::IsPointInStar(float x, float y, Star& star)
41 {
42 float i = x - star.posX;
43 float j = y - star.posY;
44
45 if (i*i + j*j > star.radius*star.radius)
46 {
47 return false;
48 }
49
50 float _s = sinf(star.angle);
51 float _c = cosf(star.angle);
52
53 Vec2 P;
54 P.x = i*_c - j*_s;
55 P.y = i*_s + j*_c;
56
57 Vec2 listPoints[5];
58 for (unsigned int m = 0; m < 5; m++)
59 {
60 listPoints[m].x = star.radius*m_list_sin[m];
61 listPoints[m].y = star.radius*m_list_cos[m];
62 }
63
64 bool bCenter = true;
65 for (unsigned int m = 0; m < 5; m++)
66 {
67 Vec2& v = listPoints[m];
68 Vec2& vL1 = listPoints[(m + 4)%5];
69 Vec2& vL2 = listPoints[(m + 3)%5];
70 Vec2& vR1 = listPoints[(m + 1)%5];
71 Vec2& vR2 = listPoints[(m + 2)%5];
72
73 if (!IsPointInAngle(vL2, v, vR2, P))
74 {
75 bCenter = false;
76 }
77 else if (IsSameSide(vL1, vR1, v, P))
78 {
79 return true;
80 }
81 }
82
83 return bCenter;
84 }
85
86 unsigned int CPixel5StarsRedFlag::CalculatePixel(unsigned int x, unsigned int y)
87 {
88 unsigned int red = 0xffff0000;
89 unsigned int yellow = 0xfffff000;
90
91 float i = (float)x;
92 float j = (float)y;
93
94 for (unsigned int m = 0; m < 5; ++m)
95 {
96 if (IsPointInStar(i, j, m_list_stars[m]))
97 {
98 return yellow;
99 }
100 }
101
102 return red;
103 }
基类IPixelEquation的代码见:Why数学图像生成工具
关于结构体Vec2的定义及相关函数见:二维平面上判断点在三角形内的最优算法
代码中没有太考究图形之间的比例,与实际会略有不符。生成图像如下:
相应软件:
相关文章:
算法之美---100幅由程序生成的图像,总有一幅让你感到惊艳[上]
算法之美---100幅由程序生成的图像,总有一幅让你感到惊艳[下]
-------------------------------------------------------
我本没打算太考究国旗的细节,但既然有网友指出了,那就做到完美吧。
绘制方法 | 标准 |
---|---|
修改了下它的构造函数:
CPixel5StarsRedFlag::CPixel5StarsRedFlag() { m_width = 1680; m_height = 1120; for (int i = 0; i < 5; i++) { m_list_sin[i] = sinf((i - 0.5f)*2*PI/5); m_list_cos[i] = cosf((i - 0.5f)*2*PI/5); } float cellSize = m_height/20.0f; float disX; float disY; m_list_stars[0].posX = cellSize*5.0f; m_list_stars[0].posY = cellSize*5.0f; m_list_stars[0].radius = cellSize*3.0f; m_list_stars[0].angle = 0.0f; float r = m_list_stars[0].radius * 3.0f; m_list_stars[1].posX = cellSize*10.0f; m_list_stars[1].posY = cellSize*2.0f; m_list_stars[1].radius = m_list_stars[0].radius/3.0f; disX = m_list_stars[0].posX - m_list_stars[1].posX; disY = m_list_stars[0].posY - m_list_stars[1].posY; m_list_stars[1].angle = PI + atan2f(disX, disY); m_list_stars[2].posX = cellSize*12.0f; m_list_stars[2].posY = cellSize*4.0f; m_list_stars[2].radius = m_list_stars[1].radius; disX = m_list_stars[0].posX - m_list_stars[2].posX; disY = m_list_stars[0].posY - m_list_stars[2].posY; m_list_stars[2].angle = PI + atan2f(disX, disY); m_list_stars[3].posX = cellSize*12.0f; m_list_stars[3].posY = cellSize*7.0f; m_list_stars[3].radius = m_list_stars[1].radius; disX = m_list_stars[0].posX - m_list_stars[3].posX; disY = m_list_stars[0].posY - m_list_stars[3].posY; m_list_stars[3].angle = PI + atan2f(disX, disY); m_list_stars[4].posX = cellSize*10.0f; m_list_stars[4].posY = cellSize*9.0f; m_list_stars[4].radius = m_list_stars[1].radius; disX = m_list_stars[0].posX - m_list_stars[4].posX; disY = m_list_stars[0].posY - m_list_stars[4].posY; m_list_stars[4].angle = PI + atan2f(disX, disY); }