Browse files

Make sure all regions are traversed in counterclockwise order

  • Loading branch information...
1 parent 565db42 commit 40a20798e86f29f6118db42e2d397a6b8ec5530a @nodename committed Nov 29, 2009
Showing with 87 additions and 1 deletion.
  1. +8 −1 src/com/nodename/Delaunay/Site.as
  2. +49 −0 src/com/nodename/geom/Polygon.as
  3. +30 −0 src/com/nodename/geom/Winding.as
View
9 src/com/nodename/Delaunay/Site.as
@@ -1,5 +1,8 @@
package com.nodename.Delaunay
{
+ import com.nodename.geom.Polygon;
+ import com.nodename.geom.Winding;
+
import flash.geom.Point;
import flash.geom.Rectangle;
@@ -199,6 +202,10 @@ package com.nodename.Delaunay
{
reorderEdges();
_region = clipToBounds(clippingBounds);
+ if ((new Polygon(_region)).winding() == Winding.CLOCKWISE)
+ {
+ _region = _region.reverse();
+ }
}
return _region;
}
@@ -245,6 +252,7 @@ package com.nodename.Delaunay
}
// close up the polygon by adding another corner point of the bounds if needed:
connect(points, i, bounds, true);
+
return points;
}
@@ -267,7 +275,6 @@ package com.nodename.Delaunay
// (NOTE this will not be correct if the region should take up more than
// half of the bounds rect, for then we will have gone the wrong way
// around the bounds and included the smaller part rather than the larger)
- // TODO check the clockwise/counterclockwise orientation of the polygon
var rightCheck:int = BoundsCheck.check(rightPoint, bounds);
var newCheck:int = BoundsCheck.check(newPoint, bounds);
var px:Number, py:Number;
View
49 src/com/nodename/geom/Polygon.as
@@ -0,0 +1,49 @@
+package com.nodename.geom
+{
+ import flash.geom.Point;
+
+ public final class Polygon
+ {
+ private var _vertices:Vector.<Point>;
+
+ public function Polygon(vertices:Vector.<Point>)
+ {
+ _vertices = vertices;
+ }
+
+ public function area():Number
+ {
+ return Math.abs(signedDoubleArea() * 0.5);
+ }
+
+ public function winding():Winding
+ {
+ var signedDoubleArea:Number = signedDoubleArea();
+ if (signedDoubleArea < 0)
+ {
+ return Winding.CLOCKWISE;
+ }
+ if (signedDoubleArea > 0)
+ {
+ return Winding.COUNTERCLOCKWISE;
+ }
+ return Winding.NONE;
+ }
+
+ private function signedDoubleArea():Number
+ {
+ var index:uint, nextIndex:uint;
+ var n:uint = _vertices.length;
+ var point:Point, next:Point;
+ var signedDoubleArea:Number = 0;
+ for (index = 0; index < n; ++index)
+ {
+ nextIndex = (index + 1) % n;
+ point = _vertices[index] as Point;
+ next = _vertices[nextIndex] as Point;
+ signedDoubleArea += point.x * next.y - next.x * point.y;
+ }
+ return signedDoubleArea;
+ }
+ }
+}
View
30 src/com/nodename/geom/Winding.as
@@ -0,0 +1,30 @@
+package com.nodename.geom
+{
+ import flash.errors.IllegalOperationError;
+
+ public final class Winding
+ {
+ public static const CLOCKWISE:Winding = new Winding(PrivateConstructorEnforcer, "clockwise");
+ public static const COUNTERCLOCKWISE:Winding = new Winding(PrivateConstructorEnforcer, "counterclockwise");
+ public static const NONE:Winding = new Winding(PrivateConstructorEnforcer, "none");
+
+ private var _name:String;
+
+ public function Winding(lock:Class, name:String)
+ {
+ super();
+ if (lock != PrivateConstructorEnforcer)
+ {
+ throw new IllegalOperationError("Invalid constructor access");
+ }
+ _name = name;
+ }
+
+ public function toString():String
+ {
+ return _name;
+ }
+ }
+}
+
+class PrivateConstructorEnforcer {}

0 comments on commit 40a2079

Please sign in to comment.