计算正多边形顶点的坐标

时间:2010-08-08 23:19:37

标签: c# algorithm math geometry polygon

我正在编写一个程序,我需要绘制任意数量边的多边形,每个边都由一个动态变化的给定公式进行翻译。有一些相当有趣的数学,但我被困在这个问题上。

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

例如:六边形可能具有以下几点(均为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#中的示例会很有用。我甚至不知道从哪里开始。 我该如何实施?它甚至可能吗?!

谢谢。

7 个答案:

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

如果您的中心是原点,则只需忽略centreXcentreY条款,因为它们将是0,0。

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

答案 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循环