فهرست منبع

updated h2d.col.Ray api to match h3d one, updated Polygon.rayIntersection as well

Nicolas Cannasse 5 سال پیش
والد
کامیت
584e3e1148
3فایلهای تغییر یافته به همراه72 افزوده شده و 50 حذف شده
  1. 31 33
      h2d/col/Polygon.hx
  2. 40 16
      h2d/col/Ray.hx
  3. 1 1
      h2d/col/Segment.hx

+ 31 - 33
h2d/col/Polygon.hx

@@ -238,8 +238,8 @@ abstract Polygon(Array<Point>) from Array<Point> to Array<Point> {
 		return minDistSq == 1e10 ? 0. : minDistSq;
 	}
 
-	public function rayIntersection( r : h2d.col.Ray, ?pt : Point ) {
-		var dmin = 1E9;
+	public function rayIntersection( r : h2d.col.Ray, bestMatch : Bool ) : Float {
+		var dmin = -1.;
 		var p0 = points[points.length - 1];
 
 		for(p in points) {
@@ -248,64 +248,62 @@ abstract Polygon(Array<Point>) from Array<Point> to Array<Point> {
 				continue;
 			}
 
-			var u = ( r.dx * (p0.y - r.y) - r.dy * (p0.x - r.x) ) / ( r.dy * (p.x - p0.x) - r.dx * (p.y - p0.y) );
+			var u = ( r.lx * (p0.y - r.py) - r.ly * (p0.x - r.px) ) / ( r.ly * (p.x - p0.x) - r.lx * (p.y - p0.y) );
 			var x = p0.x + u * (p.x - p0.x);
 			var y = p0.y + u * (p.y - p0.y);
-			var d = Math.distanceSq(x - r.x, y - r.y);
+			var d = Math.distanceSq(x - r.px, y - r.py);
 
-			if(d < dmin) {
-				if( pt == null ) pt = new Point();
-				pt.x = x;
-				pt.y = y;
+			if(d < dmin || dmin < 0) {
 				dmin = d;
+				if( !bestMatch ) return dmin;
 			}
 			p0 = p;
 		}
 
-		return pt;
+		return dmin;
 	}
-	
-	// find orientation of ordered triplet (p, q, r). 
-	// 0 --> p, q and r are colinear 
-	// 1 --> Clockwise 
-	// 2 --> Counterclockwise 
-	inline function orientation(p : h2d.col.Point, q : h2d.col.Point, r : h2d.col.Point) { 
-		var v = side(p, q, r);	
-		if (v == 0)	return 0;  		// colinear 
-		return v > 0 ? 1 : -1; 	// clock or counterclock wise 
+
+	// find orientation of ordered triplet (p, q, r).
+	// 0 --> p, q and r are colinear
+	// 1 --> Clockwise
+	// 2 --> Counterclockwise
+	inline function orientation(p : h2d.col.Point, q : h2d.col.Point, r : h2d.col.Point) {
+		var v = side(p, q, r);
+		if (v == 0)	return 0;  		// colinear
+		return v > 0 ? 1 : -1; 	// clock or counterclock wise
 	}
 
 	/**
 		p, q, r : must be colinear points!
-		checks if 'r' lies on segment 'pq' 
+		checks if 'r' lies on segment 'pq'
 	**/
-	inline function onSegment(p : h2d.col.Point, q : h2d.col.Point, r : h2d.col.Point) { 
+	inline function onSegment(p : h2d.col.Point, q : h2d.col.Point, r : h2d.col.Point) {
 		if(r.x > Math.max(p.x, q.x)) return false;
 		if(r.x < Math.min(p.x, q.x)) return false;
 		if(r.y > Math.max(p.y, q.y)) return false;
 		if(r.y < Math.min(p.y, q.y)) return false;
 		return true;
-	} 
+	}
 
 	/**
-		check if segment 'p1q1' and 'p2q2' intersect. 
+		check if segment 'p1q1' and 'p2q2' intersect.
 	**/
-	function intersect(p1 : h2d.col.Point, q1 : h2d.col.Point, p2 : h2d.col.Point, q2 : h2d.col.Point) { 
-		var s1 = orientation(p1, q1, p2); 
-		var s2 = orientation(p1, q1, q2); 
-		var s3 = orientation(p2, q2, p1); 
-		var s4 = orientation(p2, q2, q1); 
-		
-		if (s1 != s2 && s3 != s4) return true; 
+	function intersect(p1 : h2d.col.Point, q1 : h2d.col.Point, p2 : h2d.col.Point, q2 : h2d.col.Point) {
+		var s1 = orientation(p1, q1, p2);
+		var s2 = orientation(p1, q1, q2);
+		var s3 = orientation(p2, q2, p1);
+		var s4 = orientation(p2, q2, q1);
+
+		if (s1 != s2 && s3 != s4) return true;
 
 		if((s1 == 0 && onSegment(p1, q1, p2))
 		|| (s2 == 0 && onSegment(p1, q1, q2))
 		|| (s3 == 0 && onSegment(p2, q2, p1))
 		|| (s4 == 0 && onSegment(p2, q2, q1)))
-			return true; 
-	
+			return true;
+
 		return false;
-	} 
+	}
 
 	/**
 		check if polygon self-insterset
@@ -319,7 +317,7 @@ abstract Polygon(Array<Point>) from Array<Point> to Array<Point> {
 			for(j in i+2...points.length) {
 				var p2 = points[j];
 				var q2 = points[(j+1) % points.length];
-				if(q2 != p1 && intersect(p1, q1, p2, q2)) 
+				if(q2 != p1 && intersect(p1, q1, p2, q2))
 					return true;
 			}
 		}

+ 40 - 16
h2d/col/Ray.hx

@@ -3,32 +3,56 @@ import hxd.Math;
 
 class Ray {
 
-	public var x : Float;
-	public var y : Float;
-	public var dx : Float;
-	public var dy : Float;
+	public var px : Float;
+	public var py : Float;
+	public var lx : Float;
+	public var ly : Float;
 
-	public inline function new( p1 : Point, p2 : Point ) {
-		setPoints(p1, p2);
-	}
-
-	public inline function setPoints( p1 : Point, p2 : Point ) {
-		x = p1.x;
-		y = p1.y;
-		dx = p2.x - x;
-		dy = p2.y - y;
+	public inline function new() {
 	}
 
 	public inline function side( p : Point ) {
-		return dx * (p.y - y) - dy * (p.x - x);
+		return lx * (p.y - py) - ly * (p.x - px);
 	}
 
+	public inline function getPoint( distance : Float ) {
+		return new Point(px + distance * lx, py + distance * ly);
+	}
 
 	public inline function getPos() {
-		return new Point(x, y);
+		return new Point(px, py);
 	}
 
 	public inline function getDir() {
-		return new Point(dx, dy);
+		return new Point(lx, ly);
+	}
+
+	function normalize() {
+		var l = lx * lx + ly * ly;
+		if( l == 1. ) return;
+		if( l < Math.EPSILON ) l = 0 else l = Math.invSqrt(l);
+		lx *= l;
+		ly *= l;
 	}
+
+	public static inline function fromPoints( p1 : Point, p2 : Point ) {
+		var r = new Ray();
+		r.px = p1.x;
+		r.py = p1.y;
+		r.lx = p2.x - p1.x;
+		r.ly = p2.y - p1.y;
+		r.normalize();
+		return r;
+	}
+
+	public static inline function fromValues( x, y, dx, dy ) {
+		var r = new Ray();
+		r.px = x;
+		r.py = y;
+		r.lx = dx;
+		r.ly = dy;
+		r.normalize();
+		return r;
+	}
+
 }

+ 1 - 1
h2d/col/Segment.hx

@@ -67,7 +67,7 @@ class Segment {
 		if( r.side(new Point(x, y)) * r.side(new Point(x + dx, y + dy)) > 0 )
 			return null;
 
-		var u = ( r.dx * (y - r.y) - r.dy * (x - r.x) ) / ( r.dy * dx - r.dx * dy );
+		var u = ( r.lx * (y - r.py) - r.ly * (x - r.px) ) / ( r.ly * dx - r.lx * dy );
 		if( u < 0 || u > 1 ) return null;
 
 		if( pt == null ) pt = new Point();