C # Рисование многоугольников с использованием угловых градусов и триггера

Я пытаюсь создать простые формы, шестиугольник, пятиугольник, треугольник и т. Д., Имея начальную точку и вычисляя, где должны быть другие точки для каждой вершины. И я продолжаю создавать прямые линии или причудливые перекрывающиеся полигоны. Я использую метод ниже, чтобы попытаться вычислить вершины шестиугольника, затем делаю простой graphics.DrawPolygon(pen, aptsVertices), чтобы нарисовать его позже. Любая помощь будет оценена по достоинству.

protected override void CalculateVertices()
{
    //member variables
    aptsVertices = new Point[6];
    deg = 120;
    rad = deg * (Math.PI / 180);

    double nSinDeg = Math.Sin(rad);
    double nCosDeg = Math.Cos(rad);

    aptsVertices[0] = ptFirstVertex;

    for(int i = 1; i < aptsVertices.Length; i++)
    {
        double x = aptsVertices[i - 1].X - nCosDeg * nSideLength;
        double y = aptsVertices[i - 1].Y - nSinDeg * nSideLength;
        aptsVertices[i] = new Point((int)x, (int)y);

        //recalculate the degree for the next vertex
        deg += 120;
        rad = deg * (Math.PI / 180);

        nSinDeg = Math.Sin(rad);
        nCosDeg = Math.Cos(rad);
    }
}

person jb.    schedule 11.11.2010    source источник


Ответы (4)


Хорошо, проблема в вашем deg += 120. На самом деле вам нужно уменьшить deg на step = 60° (или увеличить, в зависимости от желаемого направления строительства) *.

Вот код для общего количества сторон:

public static Point[] CalculateVertices(int nSides, int nSideLength, Point ptFirstVertex)
{
    if (nSides < 3)
        throw new ArgumentException("Polygons can't have less than 3 sides...");

    var aptsVertices = new Point[nSides];
    var deg = (180.0 * (nSides - 2)) / nSides;
    var step = 360.0 / nSides;
    var rad = deg * (Math.PI / 180);

    double nSinDeg = Math.Sin(rad);
    double nCosDeg = Math.Cos(rad);

    aptsVertices[0] = ptFirstVertex;

    for (int i = 1; i < aptsVertices.Length; i++)
    {
        double x = aptsVertices[i - 1].X - nCosDeg * nSideLength;
        double y = aptsVertices[i - 1].Y - nSinDeg * nSideLength;
        aptsVertices[i] = new Point((int)x, (int)y);


        //recalculate the degree for the next vertex
        deg -= step;
        rad = deg * (Math.PI / 180);

        nSinDeg = Math.Sin(rad);
        nCosDeg = Math.Cos(rad);

    }
    return aptsVertices;
}

*

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

P.S.
Я использовал статический метод только потому, что мне было удобнее тестировать, но вы все равно можете использовать свой метод экземпляра.

person digEmAll    schedule 11.11.2010
comment
очень приятно, я ценю помощь. - person jb.; 12.11.2010

Пока я не продумывал ваш алгоритм; ИМХО, лучше было бы определить центральную точку; и пусть ваш код вычислит другие точки (шесть, в случае шестиугольника), используя point [i] = new Point (center.x + sideLength * cos ((Math.PI * i) / 6), center.y + sideLength * sin ((Math.PI * i) / 6));.

person sanjoyd    schedule 11.11.2010
comment
Вычисление координат центральной точки из координат первой вершины должно быть тривиальным. - person sanjoyd; 11.11.2010
comment
если кому-то интересно, на странице ниже есть алгоритм, использующий центральную точку: vcskicks.com/regular- polygon.php - person prestomanifesto; 10.08.2011

Статическая функция, приведенная выше, верна, однако, поскольку она вычисляет точки как целые числа, появляются ошибки округления. Даже для 5-стороннего многоугольника вычисления вершин будут отклоняться на несколько пикселей.

Я заменил класс Point, который использует двойные, а не целые числа, чтобы удалить ошибки округления. Вы можете просто округлить до ближайшего целого числа, когда рисуете вершины.

В остальном код точно такой же.

public static PointD[] CalculateVertices(int nSides, int nSideLength, PointD ptFirstVertex)
{
    //calculate the points for a polygon of N sides
    if (nSides < 3)
        throw new ArgumentException("Polygons can't have less than 3 sides...");

    var aptsVertices = new PointD[nSides];
    var deg = (180.0 * (nSides - 2)) / nSides;
    var step = 360.0 / nSides;
    var rad = deg * (Math.PI / 180);

    double nSinDeg = Math.Sin(rad);
    double nCosDeg = Math.Cos(rad);

    aptsVertices[0] = ptFirstVertex;

    for (int i = 1; i < aptsVertices.Length; i++)
    {
        double x = aptsVertices[i - 1].X - nCosDeg * nSideLength;
        double y = aptsVertices[i - 1].Y - nSinDeg * nSideLength;
        aptsVertices[i] = new PointD(x, y);

        //recalculate the degree for the next vertex
        deg -= step;
        rad = deg * (Math.PI / 180);

        nSinDeg = Math.Sin(rad);
        nCosDeg = Math.Cos(rad);

    }
    return aptsVertices;
}

Это новый класс точек.

public class PointD
{
    public double X, Y;
    public PointD(double _x, double _y)
    {
        X = _x;
        Y = _y;
    }
}
person jpreed00    schedule 03.07.2012

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

Я использовал приведенный выше код, но, используя центральную точку для установки первой вершины и смещая первую степень, я смог создать многоугольник вокруг центральной точки. Я также добавил метод расчета длины стороны на основе радиуса.

Вот что я придумал (код в Objective-C):

-(NSArray *) calculateVertices:(int)numSides center:(CGPoint)ctr{
NSMutableArray *vertices = [[NSMutableArray alloc] init];

if (numSides < 3) {
    return vertices;
}

float deg = ((180.0 * (numSides-2) / numSides)-180)/2;

float step = 360.0 / numSides;
float rad = deg * (M_PI / 180);

double nSinDeg = sin(rad);
double nCosDeg = cos(rad);

int sl = [self calculateSideLength:numSides];

CGPoint firstPoint = CGPointMake(ctr.x, ctr.y-radius);    
[vertices addObject:[NSValue valueWithCGPoint:firstPoint]];

for (int i = 1; i < numSides; i++) {
    NSValue *vp = [vertices objectAtIndex:i-1];
    CGPoint pp =[vp CGPointValue];
    double x = pp.x - nCosDeg * sl;
    double y = pp.y - nSinDeg * sl;
    CGPoint np = CGPointMake(x, y);
    [vertices addObject:[NSValue valueWithCGPoint:np]];

    deg -= step;
    rad = deg * (M_PI / 180);

    nSinDeg = sin(rad);
    nCosDeg = cos(rad);

}

return vertices;

}

-(int) calculateSideLength:(int)numSides{
   int length = (2*radius)*sin(M_PI/numSides);
   return length;
}

ПРИМЕЧАНИЕ: радиус установлен как свойство класса, поэтому вы не видите его нигде. Кроме того, я не хотел, чтобы он генерировал исключение, если сторон меньше 3, поскольку я проверял количество сторон в другом месте.

У меня просто вопрос, что лучше передать длину стороны в качестве параметра или, как я, и вызвать метод из моего метода?

person coopersita    schedule 07.10.2012