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.
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));
}
où 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));
}
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.
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).
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
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!
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.
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