私は、任意の数の辺のポリゴンを描画する必要があるプログラムを書いています。各辺は、動的に変化する特定の式によって変換されます。かなり興味深い数学がいくつか含まれていますが、私はこの問題に悩まされています。
正多角形(すべての角度が等しいもの)の頂点の座標を計算するにはどうすればよいですか辺の数のみを指定、理想的には(ただし必ずしも必要ではありません)中心に原点がある?
たとえば、六角形には次のポイントがあります(すべて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#の例が役に立つでしょう。どこから始めればいいのかさえわからない。 どのように実装すればよいですか?可能ですか?!
ありがとうございました。
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));
}
ポイントの数は辺の数と同じです。
必要な角度は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
を入れ替えると、最初のポイントが原点の右側に水平方向に向けられます。
現在、完全な解決策はありませんが、2Dレンダリングオブサークルを探してみてください。 circle(x、y、r)のすべての従来の実装では、描画用に説明したようなポリゴンを使用します(ただし、50以上の辺があります)。
ここにリストされているすべてのバージョンをテストすると、実装が適切でないことがわかります。中心からポリゴンの生成された各ポイントまでの距離を確認するには、次のようにします。 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がお役に立てば幸いです。
通常のポリゴンの座標のセットを生成する1つの可能な実装は、次のとおりです。
polygon center、radiusおよび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個の頂点があります。