Вычислить координаты правильных многоугольных вершин
Я пишу программу, в которой мне нужно нарисовать многоугольники произвольного числа сторон, причем каждый из них переводится по данной формуле, которая изменяется динамически. Есть довольно интересная математика, но я застрял в этом вопросе.
Как я могу вычислить координаты вершин правильного многоугольника (в котором все углы равны), , учитывая только количество сторон и в идеале (но не обязательно), имеющих начало координат в центре?
Например: шестиугольник может иметь следующие точки (все 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;
Меня интересует главным образом алгоритм, но примеры в С# были бы полезны. Я даже не знаю, с чего начать. Как мне его реализовать? Возможно ли это?!
Спасибо.
Ответы
Ответ 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)
Вы можете сделать это для цикла