Calculer les coordonnées des sommets d'un polygone régulier

j'écris un programme dans lequel je dois dessiner des polygones d'un nombre arbitraire de côtés, chacun étant traduit par une formule donnée qui change dynamiquement. Il y a quelques mathématiques assez intéressantes impliquées, mais je suis coincé sur ce probelm.

Comment puis-je calculer les coordonnées des sommets d'un polygone régulier (celui dans lequel tous les angles sont égaux), donné seulement le nombre de côtés, et idéalement (mais pas impérativement) ayant à l'origine à la centre?

Par exemple: un hexagone peut avoir les points suivants (tous sont 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) )

Ma méthode ressemble à ceci:

void InitPolygonVertexCoords(RegularPolygon poly)

et les coordonnées doivent être ajoutés à cette (ou quelque chose de semblable, comme une liste):

Point[] _polygonVertexPoints;

Je m'intéresse surtout à l'algorithme ici mais les exemples en C# seraient utiles. Je ne sais même pas par où commencer. Comment dois-je le mettre en oeuvre? Est-il même possible?!

Merci vous.

25
demandé sur Nobody 2010-08-09 03:19:37

7 réponses

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 est le rayon de la circumsribing cercle. Désolé pour la mauvaise langue no Habla c#.

Fondamentalement, l'angle entre deux sommets est 2 pi / n et tous les sommets sont à une distance r à partir de l'origine.

EDIT: Si vous voulez avoir le centre ailleurs que l'origine, dites à (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));
}
51
répondu deinst 2010-08-08 23:47:44

Le nombre de points est égal au nombre de côtés.

L'angle que vous avez besoin est angle = 2 * pi / numPoints.

puis en commençant verticalement au-dessus de l'origine avec la taille du polygone étant donné par radius:

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

si votre centre est l'origine, ignorez simplement le centreX et centreY Termes car ils seront 0,0.

Permutation de la cos et sin le premier point sera pointé horizontalement vers la droite de l'origine.

20
répondu ChrisF 2010-08-08 23:36:43

Désolé, Je ne dispose pas d'une solution complète à portée de main en ce moment, mais vous devriez essayer de chercher 2D-rendu des cercles. Toutes les implémentations classiques de circle (x,y,r) utilisent un polygone comme vous l'avez décrit pour le dessin (mais avec plus de 50 côtés).

2
répondu Rock 2010-08-08 23:24:28

Dire la distance des sommets à l'origine est de 1. Et say (1, 0) est toujours une coordonnée du polygone.

étant donné le nombre de Sommets (disons n), l'angle de rotation nécessaire pour positionner (1, 0) à la coordonnée suivante serait (360/n).

le calcul requis ici est de faire tourner les coordonnées. Voici ce qu'il est; Matrice De Rotation.

Dire theta = 360/n;

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

serait votre rotation matrice.

Si vous savez l'algèbre linéaire, vous savez déjà ce que je veux dire. Si ne pas juste avoir un coup d'oeil à Multiplication Matricielle

2
répondu tafa 2010-08-08 23:33:37

hmm si vous testez toutes les versions qui sont énumérées ici, vous verrez que l'implémentation n'est pas bonne. vous pouvez vérifier la distance entre le centre de chaque point du polygone avec : http://www.movable-type.co.uk/scripts/latlong.html

maintenant j'ai beaucoup cherché et je n'ai pas pu trouver une bonne implémentation pour calculer un polyogon en utilisant le centre et le rayon...donc je suis retourné au Livre de maths et j'ai essayé de l'implémenter moi-même. À la fin, j' venu avec cette...qui est 100% bon:

            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

Si vous tester, vous verrez que tous les points sont à la distance exacte que vous donnez ( rayon ). N'oubliez pas non plus de déclarer le terradius.

private const double earthRadius = 6371.01;

cela calcule les coordonnées d'un décagone. Vous voyez l'angle utilisé est de 36 degrés. Vous pouvez diviser 360 degrés à n'importe quel nombre de côtés que vous voulez et mettre le résultat dans la variable angle. De toute façon .. j'espère que cela vous aidera @rmx!

0
répondu danvasiloiu 2015-01-26 08:53:13

Une implémentation possible de générer un ensemble de coordonnées de polygone régulier est:

Définir polygone centre,rayon et premier sommet1.

Tourner le sommet n-fois2 à un angle de: 360/ N.

dans cette implémentation j'utilise un vecteur pour stocker les coordonnées générées et une fonction récursive pour générer eux:

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

où:

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

Remarque:

Point est une classe simple pour envelopper la coordonnée dans une structure de données unique:

class Point{
public:
    Point(): x(0), y(0){ }
    Point(int xx, int yy): x(xx), y(yy) { }
private:
    int x;
    int y; 
}; 

1 en termes de (par rapport au) centre, rayon. Dans mon cas, le premier vertex est traduit du centre vers le haut horizontalement par la longueur du rayon.

2 n-polygone régulier a n sommets.

0
répondu Ziezi 2015-09-23 13:06:41

la méthode simple est: Prenons N-gone (nombre de côtés) et longueur du côté L. l'angle sera T = 360 / N. Disons qu'un vertex est situé sur l'origine.

* First vertex = (0,0)
* Second vertex = (LcosT,LsinT)
* Third vertex = (LcosT+Lcos2T, LsinT+Lsin2T)
* Fourth vertex = (LcosT+Lcos2T+Lcos3T, LsinT+Lsin2T+Lsin3T)

Vous pouvez faire dans la boucle for

-2
répondu samir 2015-01-12 10:01:55