我正在编写一个程序,我需要绘制任意数量边的多边形,每个边都由一个动态变化的给定公式进行翻译。有一些相当有趣的数学,但我被困在这个问题上。
如何计算正多边形(一个所有角度相等的顶点)的顶点坐标,仅给出边数,理想情况下(但不是必须)具有原点在中心?
例如:六边形可能具有以下几点(均为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;
我主要对这里的算法感兴趣,但C#中的示例会很有用。我甚至不知道从哪里开始。 我该如何实施?它甚至可能吗?!
谢谢。
答案 0 :(得分:54)
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
是环绕圆的半径。抱歉错误的语言No Habla C#。
基本上任意两个顶点之间的角度是 2 pi / n ,并且所有顶点距离原点的距离 r 。
编辑: 如果你想让中心不是原点,那就说在(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));
}
答案 1 :(得分:20)
点数等于边数。
您需要的角度是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
会将第一个点水平指向原点右侧。
答案 2 :(得分:2)
抱歉,我现在手头没有完整的解决方案,但您应该尝试寻找2D渲染圈子。圆形(x,y,r)的所有经典实现都使用像您描述的绘制多边形(但有50多个边)。
答案 3 :(得分:2)
假设顶点到原点的距离为1.并说(1,0)始终是多边形的坐标。
给定顶点数(比如n),将(1,0)定位到下一个坐标所需的旋转角度为(360 / n)。
此处所需的计算是旋转坐标。这是它的本质; Rotation Matrix
说theta = 360 / n;
[cos(theta) -sin(theta)]
[sin(theta) cos(theta)]
将是你的旋转矩阵。
如果你知道线性代数,你就已经知道我的意思了。如果不只是看看Matrix Multiplication
答案 4 :(得分:0)
嗯,如果你测试这里列出的所有版本,你会发现实现不好。您可以使用: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
如果你测试这个,你会发现所有的点都在你给出的确切距离(半径)。另外不要忘记声明earthRadius。
private const double earthRadius = 6371.01;
这计算十边形的坐标。你看到使用的角度是36度。您可以将360度分割为任意数量的边,并将结果放在角度变量中。 无论如何..我希望这能帮助你@rmx!
答案 5 :(得分:0)
为常规多边形生成一组坐标的一种可能实现是:
定义多边形中心,半径和第一个顶点 1 。
旋转顶点n-时间 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);
}
}
Point是一个将坐标包装成单个数据结构的简单类:
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个顶点。
答案 6 :(得分:-1)
简单的方法是: 让我们取N-gone(边数)和边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)
你可以进行for循环