【问题标题】:Draw a polygon in C用C画一个多边形
【发布时间】:2010-12-20 03:38:22
【问题描述】:

我需要在给定 2 个点(他的顶点的中心和 1 个顶点)的情况下绘制一个“n”边的多边形,这只是我在数学上很糟糕。我已经阅读了很多,所有这些都是我能够理解的(我不知道它是否正确):

好的,我用毕达哥拉斯定理取两点(半径)之间的距离:

sqrt(pow(abs(x - xc), 2) + pow(abs(y - yc), 2));

以及这2点与atan2的夹角,像这样:

atan2(abs(y - yc), abs(x - xc));

其中xc,yc是中心点,x,y是唯一知道的顶点。

我用这些数据做:

void polygon(int xc, int yc, int radius, double angle, int sides)
{
    int i;
    double ang = 360/sides; //Every vertex is about "ang" degrees from each other
    radian = 180/M_PI;
    int points_x[7]; //Here i store the calculated vertexs
    int points_y[7]; //Here i store the calculated vertexs

    /*Here i calculate the vertexs of the polygon*/
    for(i=0; i<sides; i++)
    {
        points_x[i] = xc + ceil(radius * cos(angle/radian));
        points_y[i] = yc + ceil(radius * sin(angle/radian));
        angle = angle+ang;
    }

    /*Here i draw the polygon with the know vertexs just calculated*/
    for(i=0; i<sides-1; i++)
        line(points_x[i], points_y[i], points_x[i+1], points_y[i+1]);
    line(points_y[i], points_x[i], points_x[0], points_y[0]);
}

问题是程序不能正常工作,因为它绘制的线条不像多边形。

有人对数学有足够的了解吗?我正在使用 C 和 turbo C 处理这个图形基元。


编辑:我不想填充多边形,只是绘制它。

【问题讨论】:

  • 你能澄清一下你是想要一个填充的多边形(在这种情况下,关于三角形的答案可能是相关的)还是一个未填充的多边形(你只需要你建议的周边线,而你只需要画线吗?需要
  • 尝试写一个填充三角形渲染器。通常,填充的多边形一次绘制 1 条水平扫描线,从上到下。您的工作是确定每条扫描线的起始和停止 x 坐标。请注意,多边形的边沿直线(提示,提示)。

标签: c graphics polygon primitive atan2


【解决方案1】:

我不会只给你答案,但我有一些建议。首先,了解画线的内外工作原理。完成后,尝试编写一个填充的三角形渲染器。 通常,填充的多边形一次绘制 1 条水平扫描线,从上到下。您的工作是确定每条扫描线的起始和停止 x 坐标。请注意,多边形的边缘沿着直线(提示,提示)... :)

【讨论】:

    【解决方案2】:

    如果 sides 不是 360 的因数,请考虑 360/sides 实际返回的内容(这是整数除法 - 看看 360/7 实际返回的内容)。

    根本不需要使用度数 - 使用 2*Math_PI/(double)nsides 并在整个过程中使用弧度。

    您也可以使用模函数(模块 nsides)省略最后一行。

    如果您有超过 7 个边,您将无法存储所有点。如果您只是绘制多边形而不是存储它,则不需要存储所有点 - 只是最后一个点和当前点。

    【讨论】:

      【解决方案3】:

      我猜你是想画一个填充的多边形?

      如果您要尝试使用线图元绘制多边形,您将会遇到很多痛苦。 dicroce 实际上在这方面给了你一些非常好的建议。

      最好的办法是找到一个适合您的基元并为其提供坐标列表。由您决定要给它的坐标。

      【讨论】:

      • 你为什么认为它必须被填充?这个问题没有提到这一点。事实上,它专门尝试绘制多边形的轮廓,而不是填充版本。
      【解决方案4】:

      我认为主要的问题是:atan2(abs(y - yc), abs(x - xc)); 给你的是弧度,而不是度数,只需将其转换为度数并尝试。

      【讨论】:

        【解决方案5】:
        /* all angles in radians */
        double ainc = PI*2 / sides;
        int x1, y1;
        for (i = 0; i <= sides; i++){
            double a = angle + ainc * i;
            int x = xc + radius * cos(a);
            int y = yc + radius * sin(a);
            if (i > 0) line(x1, y1, x, y);
            x1 = x; y1 = y;
        }
        

        或者,您可以将点保存在一个数组中,如果有的话,可以调用 DrawPoly 例程。

        如果你想要一个填充的多边形,如果你有一个,请调用 FillPoly。

        【讨论】:

          【解决方案6】:

          您应该在所有计算中使用弧度。这是一个完整的程序,说明了如何最好地做到这一点:

          #include <stdio.h>
          
          #define PI 3.141592653589
          
          static void line (int x1, int y1, int x2, int y2) {
              printf ("Line from (%3d,%3d) - (%3d,%3d)\n", x1, y1, x2, y2);
          }
          
          static void polygon (int xc, int yc, int x, int y, int n) {
              int lastx, lasty;
              double r = sqrt ((x - xc) * (x - xc) + (y - yc) * (y - yc));
              double a = atan2 (y - yc, x - xc);
              int i;
          
              for (i = 1; i <= n; i++) {
                  lastx = x; lasty = y;
                  a = a + PI * 2 / n;
                  x = round ((double)xc + (double)r * cos(a));
                  y = round ((double)yc + (double)r * sin(a));
                  line (lastx, lasty, x, y);
              }
          }
          
          int main(int argc, char* argv[]) {
              polygon (0,0,0,10,4);   // A diamond.
              polygon (0,0,10,10,4);  // A square.
              polygon (0,0,0,10,8);   // An octagon.
              return 0;
          }
          

          哪个输出(这里没有花哨的图形,但你应该明白):

          ===
          Line from (  0, 10) - (-10,  0)
          Line from (-10,  0) - (  0,-10)
          Line from (  0,-10) - ( 10,  0)
          Line from ( 10,  0) - (  0, 10)
          ===
          Line from ( 10, 10) - (-10, 10)
          Line from (-10, 10) - (-10,-10)
          Line from (-10,-10) - ( 10,-10)
          Line from ( 10,-10) - ( 10, 10)
          ===
          Line from (  0, 10) - ( -7,  7)
          Line from ( -7,  7) - (-10,  0)
          Line from (-10,  0) - ( -7, -7)
          Line from ( -7, -7) - (  0,-10)
          Line from (  0,-10) - (  7, -7)
          Line from (  7, -7) - ( 10,  0)
          Line from ( 10,  0) - (  7,  7)
          Line from (  7,  7) - (  0, 10)
          

          我已经按照您的原始规范编写了polygon 函数,只传入了两个坐标。顺便说一句,您不希望在计算半径和角度时使用那些 abs 调用,因为:

          • 它们对半径没有用(因为 -n2 = n2 对于所有 n)。
          • 它们不利于角度,因为这会迫使您进入特定的象限(错误的起点)。

          【讨论】:

          • 位数不足。尝试3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798 跨度>
          • @Pete,我不知道你是不是想搞笑。但即使是近似值 355/113 也足以在地球大小的圆上精确定位汽车(3m)。我怀疑你的版本可能足以在太阳系大小的球体中定位一个原子,在监视器上绘图可能有点矫枉过正。
          • 我认为超过 8 位数字对于这种工作来说是多余的——所以请原谅我开个玩笑的蹩脚尝试 :)
          • 全双精度约为 17 位十进制数字。
          猜你喜欢
          • 2023-03-10
          • 2021-09-22
          • 1970-01-01
          • 1970-01-01
          • 2021-07-05
          • 1970-01-01
          • 1970-01-01
          • 2022-11-10
          • 1970-01-01
          相关资源
          最近更新 更多