关于c#:计算正多边形顶点的坐标

Calculate coordinates of a regular polygon's vertices

我正在编写一个程序,在这个程序中我需要绘制任意边数的多边形,每个边都由一个动态变化的给定公式转换。其中涉及到一些相当有趣的数学问题,但我仍然坚持这个问题。

如何计算一个正多边形顶点的坐标(所有角度都相等的多边形),只给出边的数目,理想情况下(但不是必要的),原点在中心?

例如:六边形可能有以下几点(都是floats):

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));
}

其中,r是圆周的半径。抱歉,我的语言不正确。

基本上,任意两个顶点之间的角度是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));
}


点数等于边数。

你需要的角度是angle = 2 * pi / numPoints

然后从原点垂直上方开始,多边形的大小由radius给出:

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

如果你的中心是原点,那么简单地忽略centreXcentreY的术语,因为它们是0,0。

交换cossin将使第一个点水平指向原点右侧。


假设顶点到原点的距离为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循环