Explorar o código

fix convexHull()

bstouls %!s(int64=9) %!d(string=hai) anos
pai
achega
88cedaea5b
Modificáronse 1 ficheiros con 25 adicións e 21 borrados
  1. 25 21
      h2d/col/Polygon.hx

+ 25 - 21
h2d/col/Polygon.hx

@@ -48,33 +48,37 @@ abstract Polygon(Array<Point>) from Array<Point> to Array<Point> {
 		return b;
 	}
 
+	//sources : https://fr.wikipedia.org/wiki/Parcours_de_Graham
+	//step by step demonstration : http://www.algomation.com/algorithm/graham-scan-convex-hull
 	public function convexHull() {
 		var len = points.length;
-		if( len < 3 )
-			throw "convexHull() needs at least 3 points";
+		if( points.length < 3 )
+			return points;
+
+		//find lowest y points
+		var pts = points.copy();
+		var p0 = pts[0];
+		for( p in pts ) {
+			if( p.y < p0.y || (p.y == p0.y && p.x < p0.x) )
+				p0 = p;
+		}
 
-		var first = 0;
-		var firstX = points[first].x;
-		for( i in 1...points.length ) {
-			var px = points[i].x;
-			if( px < firstX ) {
-				first = i;
-				firstX = px;
+		//sort by polar angle from/to P
+		for(p in pts)
+			if(p.x == p0.x && p.y == p0.y)
+				pts.remove(p);
+		pts.sort(function(p1, p2) return side(p0, p1, p2) > 0 ? -1 : 1);
+
+		//set hull
+		var hull = [ p0, pts[0], pts[1] ];
+		for (i in 2...pts.length) {
+			var pi = pts[i];
+			while (side(hull[hull.length - 2], hull[hull.length - 1], pi) <= 0) {
+				hull.pop();
 			}
+			hull.push(pi);
 		}
 
-		var hull = [];
-		var curr = first;
-		var next = 0;
-		do {
-			hull.push(points[curr]);
-			next = (curr + 1) % len;
-			for( i in 0...len ) {
-			   if( side(points[i], points[curr], points[next]) < 0 )
-				   next = i;
-			}
-			curr = next;
-		} while( curr != first );
 		return hull;
 	}