在C中绘制一个多边形

时间:2009-11-25 03:47:52

标签: c graphics polygon primitive atan2

我需要绘制一个给出2个点(中心和1个顶点)的“n”边的多边形,这就是我吸吮数学。我已经阅读了很多,所有这些都是我能够想到的(我不知道它是否正确):

好的,我把2点(半径)与毕达哥拉斯定理之间的距离:

sqrt(pow(abs(x - xc), 2) + pow(abs(y - yc), 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在这个图形基元中工作。


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

6 个答案:

答案 0 :(得分:2)

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

根本不需要使用学位 - 使用2*Math_PI/(double)nsides并以弧度为单位工作。

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

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

答案 1 :(得分:1)

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

#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调用,因为:

  • 他们对半径毫无用处(因为-n 2 = n 2 所有{{ 1}})。
  • 他们对角度不好,因为这会迫使你进入一个特定的象限(错误的起点)。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

你想抽出一个填充的多边形吗?

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

你最好的办法是找到一个填充你的原语并提供一个坐标列表。由你决定要给它的坐标。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

/* 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例程(如果有的话)。

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

相关问题