Calculate coordinates of a regular polygon's vertices
我正在编写一个程序,在这个程序中我需要绘制任意边数的多边形,每个边都由一个动态变化的给定公式转换。其中涉及到一些相当有趣的数学问题,但我仍然坚持这个问题。
如何计算一个正多边形顶点的坐标(所有角度都相等的多边形),只给出边的数目,理想情况下(但不是必要的),原点在中心?
例如:六边形可能有以下几点(都是
1 2 3 4 5 6 | ( 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) ) |
我的方法是这样的:
1 | void InitPolygonVertexCoords(RegularPolygon poly) |
需要添加坐标(或者类似的东西,比如列表):
1 | Point[] _polygonVertexPoints; |
我主要对这里的算法感兴趣,但是C中的例子会很有用。我甚至不知道从哪里开始。我应该如何实现它?有可能吗?!
谢谢您。
1 2 3 4 | for (i = 0; i < n; i++) { printf("%f %f ",r * Math.cos(2 * Math.PI * i / n), r * Math.sin(2 * Math.PI * i / n)); } |
其中,
基本上,任意两个顶点之间的角度是2pi/n,所有顶点都在距离原点r的位置。
编辑:如果你想让中心在原点以外的某个地方,比如(x,y)
1 2 3 4 | for (i = 0; i < n; i++) { printf("%f %f ",x + r * Math.cos(2 * Math.PI * i / n), y + r * Math.sin(2 * Math.PI * i / n)); } |
点数等于边数。
你需要的角度是
然后从原点垂直上方开始,多边形的大小由
1 2 3 4 5 | for (int i = 0; i < numPoints; i++) { x = centreX + radius * sin(i * angle); y = centreY + radius * cos(i * angle); } |
如果你的中心是原点,那么简单地忽略
交换
假设顶点到原点的距离为1。假设(1,0)总是多边形的坐标。
给定顶点数(例如n),将(1,0)定位到下一个坐标所需的旋转角度为(360/n)。
这里需要的计算是旋转坐标。这是旋转矩阵。
假设theta=360/n;
1 2 | [cos(theta) -sin(theta)] [sin(theta) cos(theta)] |
将是你的旋转矩阵。
如果你知道线性代数,你已经知道我的意思了。如果不看一下矩阵乘法
抱歉,我现在没有完整的解决方案,但您应该尝试查找二维圆形渲染。圆(x,y,r)的所有经典实现都使用如您所描述的用于绘制的多边形(但有50多个边)。
为正多边形生成一组坐标的一种可能实现是:
Define polygon center, radius and first vertex1. Rotate the vertex n-times2 at an angle of: 360/n.
在此实现中,我使用向量存储生成的坐标,并使用递归函数生成它们:
1 2 3 4 5 6 7 | 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); } |
在哪里?
1 2 3 4 5 6 7 8 9 10 11 12 | 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是一个简单的类,用于将坐标包装为单个数据结构:
1 2 3 4 5 6 7 8 | 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个顶点。
hmm如果测试这里列出的所有版本,您会发现实现并不好。您可以使用http://www.movable-type.co.uk/scripts/latlong.html检查从中心到多边形每个生成点的距离。
现在我已经搜索了很多,我找不到任何好的实现来计算使用中心和半径的多边形…所以我回到数学书,并试图自己实现它。最后我想出了这个……wich是100%好的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 |
如果你测试这个,你会发现所有的点都在你给出的精确距离(半径)。也不要忘记申报地球半径。
1 | private const double earthRadius = 6371.01; |
这将计算十边形的坐标。你看这个角度是36度。可以将360度分割为任意数量的边,并将结果放入角度变量。反正…我希望这对你有帮助@rmx!
简单的方法是:让我们取n-gone(边数)和l边的长度。角度为t=360/n。假设一个顶点位于原点上。
1 2 3 4 | * First vertex = (0,0) * Second vertex = (LcosT,LsinT) * Third vertex = (LcosT+Lcos2T, LsinT+Lsin2T) * Fourth vertex = (LcosT+Lcos2T+Lcos3T, LsinT+Lsin2T+Lsin3T) |
你可以做for循环