Нарисуйте многоугольник в C

Мне нужно нарисовать многоугольник из "n" сторон, учитывая 2 точки (центр и 1 его вершины), которые мне просто нужны. Я много читал, и все это то, что я смог понять (я не знаю, правильно ли это):

Хорошо, я беру расстояние между 2 точками (радиус) с теоремой Пифагора:

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.


Изменить: я не хочу, чтобы заполнить многоугольник, просто нарисуйте его.

6 ответов

Решение

Посмотрим что 360/sides на самом деле возвращается, если sides не фактор 360 (это целочисленное деление - посмотрите, что на самом деле возвращает 360/7).

Нет необходимости использовать градусы вообще - используйте 2*Math_PI/(double)nsides и работать в радианах.

также вы можете опустить последнюю строку, используя функцию модуля (модуль nsides).

Если у вас более 7 сторон, вы не сможете хранить все очки. Вам не нужно хранить все точки, если вы просто рисуете многоугольник, а не сохраняете его - только последнюю точку и текущую.

Вы должны использовать радианы во всех ваших расчетах. Вот полная программа, которая иллюстрирует, как лучше всего это сделать:

#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).
  • они плохо влияют на угол, так как это приведет вас к определенному квадранту (неправильная отправная точка).

Вы пытаетесь нарисовать заполненную поли, я думаю?

Если вы попытаетесь нарисовать полис с помощью примитива линии, вам будет очень больно. Dicroce действительно дал вам очень хороший совет по этому вопросу.

Лучше всего найти примитив, который заполняет вас, и предоставить ему список координат. Это зависит от вас, чтобы определить координаты, чтобы дать его.

Я думаю, что главная проблема заключается в: atan2(abs(y - yc), abs(x - xc)); дает вам радианы, а не градусы, просто конвертируйте его в градусы и попробуйте.

/* 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, если он у вас есть.

Я не собираюсь просто давать вам ответ, но у меня есть несколько советов. Во-первых, узнайте, как рисование линий работает внутри и снаружи. Когда у вас это получится, попробуйте написать заполненный треугольник. Как правило, заполненные многоугольники рисуются по 1 горизонтальной линии сканирования за раз, сверху вниз. Ваша задача - определить начальную и конечную координату x для каждой строки сканирования. Обратите внимание, что край многоугольника следует за прямой линией (подсказка, подсказка)...:)

Другие вопросы по тегам