web-dev-qa-db-ja.com

正多角形の頂点の座標を計算します

私は、任意の数の辺のポリゴンを描画する必要があるプログラムを書いています。各辺は、動的に変化する特定の式によって変換されます。かなり興味深い数学がいくつか含まれていますが、私はこの問題に悩まされています。

正多角形(すべての角度が等しいもの)の頂点の座標を計算するにはどうすればよいですか辺の数のみを指定、理想的には(ただし必ずしも必要ではありません)中心に原点がある?

たとえば、六角形には次のポイントがあります(すべてfloatsです)。

( 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#の例が役に立つでしょう。どこから始めればいいのかさえわからない。 どのように実装すればよいですか?可能ですか?!

ありがとうございました。

29
Nobody
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は外接円の半径です。間違った言語で申し訳ありません。

基本的に、任意の2つの頂点間の角度は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));
}
55
deinst

ポイントの数は辺の数と同じです。

必要な角度は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になるため、単に無視してください。

cossinを入れ替えると、最初のポイントが原点の右側に水平方向に向けられます。

20
ChrisF

現在、完全な解決策はありませんが、2Dレンダリングオブサークルを探してみてください。 circle(x、y、r)のすべての従来の実装では、描画用に説明したようなポリゴンを使用します(ただし、50以上の辺があります)。

2
Rock

頂点から原点までの距離が1であるとします。そして、(1、0)は常にポリゴンの座標です。

頂点の数(nなど)を指定すると、(1、0)を次の座標に配置するために必要な回転角度は(360/n)になります。

ここで必要な計算は、座標を回転させることです。ここにそれがあります。 回転マトリックス

シータ= 360/nと言います。

[cos(theta) -sin(theta)]
[sin(theta) cos(theta)]

あなたの回転行列になります。

あなたが線形代数を知っているなら、あなたはすでに私が何を意味するか知っています。見ていない場合は 行列乗算

2
tafa

ここにリストされているすべてのバージョンをテストすると、実装が適切でないことがわかります。中心からポリゴンの生成された各ポイントまでの距離を確認するには、次のようにします。 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

これをテストすると、すべてのポイントが指定した正確な距離(radius)にあることがわかります。また、earthRadiusを宣言することを忘れないでください。

private const double earthRadius = 6371.01;

十角形の座標を計算します。使用されている角度は36度です。 360度を任意の数の辺に分割して、結果を角度変数に入れることができます。とにかく.. @rmxがお役に立てば幸いです。

0
danvasiloiu

通常のポリゴンの座標のセットを生成する1つの可能な実装は、次のとおりです。

polygon centerradiusおよびfirst vertexを定義します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。私の場合、最初の頂点は中心から水平方向に半径lenghtだけ平行移動されます。

2 n正則ポリゴンにはn個の頂点があります。

0
Ziezi