随笔-375  评论-742  文章-1 

算法生成五星红旗

      这一篇将提供一套生成五星红旗的算法,代码中满满都是正能量。上一篇文章是生成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的定义及相关函数见:二维平面上判断点在三角形内的最优算法

代码中没有太考究图形之间的比例,与实际会略有不符。生成图像如下:

相应软件:

Why数学图像生成工具

相关文章:

算法生成青天白日满地红旗

算法之美---100幅由程序生成的图像,总有一幅让你感到惊艳[上]

算法之美---100幅由程序生成的图像,总有一幅让你感到惊艳[下]

-------------------------------------------------------

      我本没打算太考究国旗的细节,但既然有网友指出了,那就做到完美吧。

绘制方法标准
Construction sheet of Flag of the People's Republic of China.svg
  1. 先将旗面划分为4个等分长方形,再将左上方长方形划分长宽15×10个方格。
  2. 大五角星的中心位于该长方形上5下5、左5右10之处。大五角星外接圆的直径为6单位长度。
  3. 四颗小五角星的中心点,第一颗位于上2下8、左10右5,第二颗位于上4下6、左12右3,第三颗位于上7下3、左12右3,第四颗位于上9下1、左10右5之处。
  4. 每颗小五角星外接圆的直径均为2单位长度。四颗小五角星均有一角尖正对大五角星的中心点。

修改了下它的构造函数:

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);
}

posted on 2014-11-01 05:17 叶飞影 阅读(...) 评论(...) 编辑 收藏