Gesucht ist die konvexe Hülle einer endlichen Menge von Punkten in der Ebene. Die Idee des Verfahrens von Graham [Gra 72] ist, aus der Punktemenge zunächst ein sternförmiges Polygon zu konstruieren und dieses anschließend in ein konvexes Polygon umzuformen.
Aus der Punktemenge (Bild 1a) wird zunächst der Punkt q mit minimaler y-Koordinate, bzw. bei mehreren Punkten mit minimaler y-Koordinate, von diesen der Punkt mit minimaler x-Koordinate gewählt. Ausgehend von q werden die Winkel zu allen anderen Punkten bestimmt (Bild 1b). Die Punkte werden nach diesem Winkel sortiert und zu einem Polygonzug verbunden. Es entsteht ein sternförmiges Polygon (Bild 1c).
Bild 1: Aus der Punktemenge konstruierter sternförmiger Polygonzug
Es kann vorkommen, dass mehrere Punkte den gleichen Winkel haben (vgl. Bild 1b). Punkte gleichen Winkels werden zusätzlich absteigend nach ihrem Abstand zu q sortiert. Bei dem entstehenden Polygonzug können sich Kanten überlappen, sodass ein nicht einfacher Polygonzug entsteht. Dieser ist aber dennoch für den Algorithmus geeignet.
Der sternförmige Polygonzug wird nun ausgehend von q durchlaufen; dabei werden konkave Ecken überbrückt (siehe konvexe Hülle eines sternförmigen Polygons). Das Ergebnis ist ein konvexes Polygon, das die konvexe Hülle der Punktemenge darstellt.
Bild 2: Aus dem sternförmigen Polygonzug erzeugtes konvexes Polygon
In folgender Realisierung des Graham-Scan-Algorithmus wird die Tatsache ausgenutzt, dass aufgrund der Sortierung der Punkte die Ecken p0 und p1 konvex sind.
Algorithmus Graham-Scan
Eingabe:
Array p mit n Punkten
Ausgabe:
Array p derart umgeordnet, dass die ersten h Einträge die Ecken des konvexen Hüllpolygons sind
Methode:
Der Algorithmus hat die kleine Unschönheit, dass die letzte Ecke des berechneten konvexe Hüllpolygons eine 180°-Ecke sein kann (vgl. Bild 2). Wenn dies stört, ist es einfach, diese noch zu entfernen.
Um die Punkte nach ihrem Winkel zu sortieren, ist es nicht nötig, die Winkel tatsächlich zu berechnen. Der Sortieralgorithmus muss nur wissen, welcher von jeweils zwei Punkten pi und pj den größeren Winkel hat. Dies lässt sich danach entscheiden, ob das Dreieck 0 pi pj einen positiven oder negativen Flächeninhalt hat. Der doppelte Flächeninhalt ergibt sich durch die einfache Berechnung xiyj – xjyi (vgl. Fläche eines Dreiecks ). Bei gleichem Winkel, d.h. wenn die Dreiecksfläche gleich Null ist, werden die Punkte nach ihrem Abstand zum Nullpunkt sortiert. Es genügt hier, mit dem Manhattan-Abstand |x| + |y| zu rechnen.
Die Methode isLess der Klasse Point implementiert einen solchen Vergleich. Sie wird in der Sortierfunktion des Graham-Scan-Algorithmus benutzt.
Die folgende Klasse GrahamScan implementiert den Graham-Scan-Algorithmus. Der Aufruf erfolgt mit
Hierbei ist p ein Array von Punkten. Als Ergebnis der Berechnung werden die Punkte im Array so umgeordnet, dass die ersten h Punkte die Ecken des konvexen Hüllpolynoms in umlaufender Reihenfolge bilden.
Die weiteren Funktionen sind Hilfsfunktionen. Die Funktion exchange(i, j) vertauscht zwei Punkte im Array. Die Funktion makeRelTo(p0) rechnet alle Punkte des Arrays relativ zu p0 als Nullpunkt um. Die Funktion indexOfLowestPoint() sucht den Punkt mit kleinster y-Koordinate, oder bei mehreren Punkten mit kleinster y-Koordinate, von diesen den Punkt mit kleinster x-Koordinate. Als Ergebnis wird die Position des Punktes im Array zurückgegeben. Die Funktion isConvex(i) testet, ob die Punkte pi-1 pi pi+1 eine konvexe Ecke eines Polygonzuges darstellen. Für das Sortieren der Punkte wird Quicksort verwendet.
[CLRS 01] T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein: Introduction to Algorithms. 2. Auflage, The MIT Press (2001)
[Gra 72] R.L. Graham: An Efficient Algorithm for Determining the Convex Hull of a Finite Planar Set. Information Processing Letters 1, 132-133 (1972)
[PSh 85] F.P. Preparata, M.I. Shamos: Computational Geometry. Springer (1985)
[Web 1] http://www.cse.unsw.edu.au/~lambert/java/3d/hull.html
Weiter mit: [Jarvis-March-Algorithmus] oder [up]