Berechnen Sie zunächst den Mittelpunkt. Sortieren Sie dann die Punkte mit einem beliebigen Sortieralgorithmus. Verwenden Sie jedoch eine spezielle Vergleichsroutine, um festzustellen, ob ein Punkt kleiner als der andere ist.
Mit dieser einfachen Berechnung können Sie überprüfen, ob ein Punkt (a) links oder rechts vom anderen (b) in Bezug auf die Mitte liegt:
det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y)
Wenn das Ergebnis Null ist, befinden sie sich auf derselben Linie von der Mitte. Wenn es positiv oder negativ ist, befindet es sich auf der einen oder anderen Seite, sodass ein Punkt vor dem anderen liegt. Mit dieser Funktion können Sie eine Beziehung erstellen, die kleiner als ist, um Punkte zu vergleichen und die Reihenfolge zu bestimmen, in der sie im sortierten Array angezeigt werden sollen. Aber Sie müssen definieren, wo der Anfang dieser Reihenfolge ist. Ich meine, welcher Winkel der Startwinkel sein wird (z. B. die positive Hälfte der x-Achse).
Der Code für die Vergleichsfunktion kann folgendermaßen aussehen:
bool less(point a, point b)
{
if (a.x - center.x >= 0 && b.x - center.x < 0)
return true;
if (a.x - center.x < 0 && b.x - center.x >= 0)
return false;
if (a.x - center.x == 0 && b.x - center.x == 0) {
if (a.y - center.y >= 0 || b.y - center.y >= 0)
return a.y > b.y;
return b.y > a.y;
}
// compute the cross product of vectors (center -> a) x (center -> b)
int det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y);
if (det < 0)
return true;
if (det > 0)
return false;
// points a and b are on the same line from the center
// check which point is closer to the center
int d1 = (a.x - center.x) * (a.x - center.x) + (a.y - center.y) * (a.y - center.y);
int d2 = (b.x - center.x) * (b.x - center.x) + (b.y - center.y) * (b.y - center.y);
return d1 > d2;
}
Dadurch werden die Punkte ab 12 Uhr im Uhrzeigersinn sortiert. Punkte zur selben "Stunde" werden ab denjenigen bestellt, die weiter vom Zentrum entfernt sind.
Wenn Sie ganzzahlige Typen verwenden (die in Lua nicht wirklich vorhanden sind), müssen Sie sicherstellen, dass die Variablen det, d1 und d2 von einem Typ sind, der das Ergebnis der durchgeführten Berechnungen enthalten kann.
Wenn Sie etwas erreichen möchten, das solide und so konvex wie möglich aussieht, dann suchen Sie wahrscheinlich einen konvexen Rumpf . Sie können es mit dem Graham Scan berechnen . In diesem Algorithmus müssen Sie die Punkte auch im Uhrzeigersinn (oder gegen den Uhrzeigersinn) ab einem speziellen Drehpunkt sortieren. Dann wiederholen Sie jedes Mal einfache Schleifenschritte, wenn Sie prüfen, ob Sie nach links oder rechts abbiegen und der konvexen Hülle neue Punkte hinzufügen. Diese Prüfung basiert auf einem Kreuzprodukt wie in der obigen Vergleichsfunktion.
Bearbeiten:
Es wurde eine weitere if-Anweisung hinzugefügt if (a.y - center.y >= 0 || b.y - center.y >=0)
, um sicherzustellen, dass Punkte mit x = 0 und negativem y beginnend mit denjenigen sortiert werden, die weiter von der Mitte entfernt sind. Wenn Sie sich nicht um die Reihenfolge der Punkte in derselben 'Stunde' kümmern, können Sie diese if-Anweisung weglassen und immer zurückkehren a.y > b.y
.
Die ersten if-Anweisungen wurden durch Hinzufügen von -center.x
und korrigiert -center.y
.
Die zweite if-Anweisung wurde hinzugefügt (a.x - center.x < 0 && b.x - center.x >= 0)
. Es war ein offensichtliches Versehen, dass es fehlte. Die if-Anweisungen könnten jetzt neu organisiert werden, da einige Überprüfungen redundant sind. Wenn beispielsweise die erste Bedingung in der ersten if-Anweisung falsch ist, muss die erste Bedingung der zweiten if-Anweisung wahr sein. Ich habe mich jedoch der Einfachheit halber entschlossen, den Code so zu belassen, wie er ist. Es ist durchaus möglich, dass der Compiler den Code optimiert und trotzdem das gleiche Ergebnis erzielt.