Подтвердить что ты не робот

Вычислить координаты правильных многоугольных вершин

Я пишу программу, в которой мне нужно нарисовать многоугольники произвольного числа сторон, причем каждый из них переводится по данной формуле, которая изменяется динамически. Есть довольно интересная математика, но я застрял в этом вопросе.

Как я могу вычислить координаты вершин правильного многоугольника (в котором все углы равны), , учитывая только количество сторон и в идеале (но не обязательно), имеющих начало координат в центре?

Например: шестиугольник может иметь следующие точки (все float s):

( 1.5  ,  0.5 *Math.Sqrt(3) )
( 0    ,  1   *Math.Sqrt(3) )
(-1.5  ,  0.5 *Math.Sqrt(3) )
(-1.5  , -0.5 *Math.Sqrt(3) )
( 0    , -1   *Math.Sqrt(3) )
( 1.5  , -0.5 *Math.Sqrt(3) )

Мой метод выглядит следующим образом:

void InitPolygonVertexCoords(RegularPolygon poly)

и координаты должны быть добавлены к этому (или что-то подобное, например, список):

Point[] _polygonVertexPoints;

Меня интересует главным образом алгоритм, но примеры в С# были бы полезны. Я даже не знаю, с чего начать. Как мне его реализовать? Возможно ли это?!

Спасибо.

4b9b3361

Ответ 1

for (i = 0; i < n; i++) {
  printf("%f %f\n",r * Math.cos(2 * Math.PI * i / n), r * Math.sin(2 * Math.PI * i / n));
}

где r - радиус окружности окружности. Извините за неправильный язык Нет Habla С#.

В основном угол между любыми двумя вершинами равен 2 pi/n, а все вершины находятся на расстоянии r от начала координат.

EDIT: Если вы хотите, чтобы центр был другим, кроме начала координат, скажите в (x, y)

for (i = 0; i < n; i++) {
  printf("%f %f\n",x + r * Math.cos(2 * Math.PI * i / n), y + r * Math.sin(2 * Math.PI * i / n));
}

Ответ 2

Число точек равно числу сторон.

Требуемый угол angle = 2 * pi / numPoints.

Затем, начиная вертикально над началом координат, размер полигона задается символом radius:

for (int i = 0; i < numPoints; i++)
{
    x = centreX + radius * sin(i * angle);
    y = centreY + radius * cos(i * angle);
}

Если ваш центр является источником, просто игнорируйте члены centreX и centreY, поскольку они будут 0,0.

Перемещение cos и sin поверх будет указывать первую точку по горизонтали справа от начала координат.

Ответ 3

Извините, у меня сейчас нет полного решения, но вы должны попробовать 2D-рендеринг кругов. Все классические реализации круга (x, y, r) используют многоугольник, как вы описали для рисования (но с 50 + сторонами).

Ответ 4

Скажем, что расстояние от вершин до начала равно 1. И говорят (1, 0) всегда координата многоугольника.

Учитывая количество вершин (например, n), угол поворота, необходимый для позиционирования (1, 0) к следующей координате, будет равен (360/n).

Здесь необходимо вычислить поворот координат. Вот что это такое; Матрица вращения.

Скажите тета = 360/n;

[cos(theta) -sin(theta)]
[sin(theta) cos(theta)]

будет вашей матрицей вращения.

Если вы знаете линейную алгебру, вы уже знаете, что я имею в виду. Если вы просто не смотрите Матричное умножение

Ответ 5

hmm, если вы проверите все версии, перечисленные здесь, вы увидите, что реализация не очень хороша. вы можете проверить расстояние от центра до каждой сгенерированной точки многоугольника: http://www.movable-type.co.uk/scripts/latlong.html

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

            List<double[]> coordinates = new List<double[]>();
            #region create Polygon Coordinates
            if (!string.IsNullOrWhiteSpace(bus.Latitude) && !string.IsNullOrWhiteSpace(bus.Longitude) && !string.IsNullOrWhiteSpace(bus.ListingRadius))
            {
                double lat = DegreeToRadian(Double.Parse(bus.Latitude));
                double lon = DegreeToRadian(Double.Parse(bus.Longitude));
                double dist = Double.Parse(bus.ListingRadius);
                double angle = 36;

                for (double i = 0; i <= 360; i += angle)
                {
                    var bearing = DegreeToRadian(i);

                    var lat2 = Math.Asin(Math.Sin(lat) * Math.Cos(dist / earthRadius) + Math.Cos(lat) * Math.Sin(dist / earthRadius) * Math.Cos(bearing));
                    var lon2 = lon + Math.Atan2(Math.Sin(bearing) * Math.Sin(dist / earthRadius) * Math.Cos(lat),Math.Cos(dist / earthRadius) - Math.Sin(lat) * Math.Sin(lat2));

                    coordinates.Add(new double[] { RadianToDegree(lat2), RadianToDegree(lon2) });

                }

                poly.Coordinates = new[] { coordinates.ToArray() };
            }
            #endregion

Если вы проверите это, вы увидите, что все точки находятся на точном расстоянии, которое вы даете (радиус). Также не забудьте объявить землю Радиус.

private const double earthRadius = 6371.01;

Это вычисляет координаты декагона. Вы видите, что используемый угол составляет 36 градусов. Вы можете разделить 360 градусов на любое количество сторон, которые вы хотите, и поместить результат в переменную угла.    В любом случае.. Надеюсь, это поможет вам @rmx!

Ответ 6

Одна возможная реализация для создания набора координат для правильного многоугольника:

Определите центр полигона, радиус и первую вершину 1.
Поверните вершину n-times 2 под углом: 360/n.

В этой реализации я использую вектор для хранения сгенерированных координат и рекурсивную функцию для их создания:

void generateRegularPolygon(vector<Point>& v, Point& center, int sidesNumber, int radius){
    // converted to radians
    double angRads = 2 * PI / double(sidesNumber);
    // first vertex  
    Point initial(center.x, center.y - radius);
    rotateCoordinate(v, center, initial, angRads, sidesNumber);
}

где:

void rotateCoordinate(vector<Point>& v, Point& axisOfRotation, Point& initial, double angRads, int numberOfRotations){
    // base case: number of transformations < 0
    if(numberOfRotations <= 0) return;
    else{
        // apply rotation to: initial, around pivot point: axisOfRotation
        double x = cos(angRads) * (initial.x - axisOfRotation.x) - sin(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.x;
        double y = sin(angRads) * (initial.x - axisOfRotation.x) + cos(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.y;
        // store the result
        v.push_back(Point(x, y));
        rotateCoordinate(v, axisOfRotation, Point(x,y), angRads, --numberOfRotations);
    }
}

Примечание:

Точка - это простой класс для переноса координаты в единую структуру данных:

class Point{
public:
    Point(): x(0), y(0){ }
    Point(int xx, int yy): x(xx), y(yy) { }
private:
    int x;
    int y; 
}; 

1 в терминах (относительно) центра, радиуса. В моем случае первая вершина переводится из центра горизонтально по длине радиуса.

2 n-правильный многоугольник имеет n вершин.

Ответ 7

Простым методом является: Возьмем N-go (количество сторон) и длину стороны L. Угол будет T = 360/N. Пусть говорят, что одна вершина расположена в начале координат.

* First vertex = (0,0)
* Second vertex = (LcosT,LsinT)
* Third vertex = (LcosT+Lcos2T, LsinT+Lsin2T)
* Fourth vertex = (LcosT+Lcos2T+Lcos3T, LsinT+Lsin2T+Lsin3T)

Вы можете сделать это для цикла