IntersectionFinderXY class
TODO optimize: reduce Vector3 creation (each operation) by using instance cache (or by using x,y instead of vector) May be future inspiration : http://www.realtimerendering.com/intersections.html http://www.kevlindev.com/gui/math/intersection/index.htm http://cse.csusb.edu/tong/courses/cs621/notes/intersect.php http://www.gamasutra.com/view/feature/3383/simpleintersectiontestsforgames.php
class IntersectionFinderXY implements IntersectionFinder {
//with double approximation, use zeroEpsilon for test
static const zeroEpsilon = 0.0001;
// cache to avoid re-alloc
var _v0 = new Vector3.zero();
var _v1 = new Vector3.zero();
var _v2 = new Vector3.zero();
var _mm0 = new MinMax();
var _mm1 = new MinMax();
// double length2(Vector3 p0, Vector3 p1) {
// var x = p1.x - p0.x;
// var y = p1.y - p0.y;
// return x*x + y*y;
// }
/// implementation from http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
/// based on Andre LeMothe's ["Tricks of the Windows Game Programming Gurus"](http://rads.stackoverflow.com/amzn/click/0672323699).
bool segment_segment(Vector3 sa1, Vector3 sa2, Vector3 sb1, Vector3 sb2, Vector4 acol) {
var sa_x, sa_y, sb_x, sb_y;
sa_x = sa2.x - sa1.x; sa_y = sa2.y - sa1.y;
sb_x = sb2.x - sb1.x; sb_y = sb2.y - sb1.y;
var u = (sa_x * sb_y - sb_x * sa_y);
// u == 0 if segment are parallele, with double approximation, use 0.0001
//if (u < zeroEpsilon && u > -zeroEpsilon ) return false;
if (u == 0) return false;
var s = ( sa_x * (sa1.y - sb1.y) - sa_y * (sa1.x - sb1.x)) / u;
var t = ( sb_x * (sa1.y - sb1.y) - sb_y * (sa1.x - sb1.x)) / u;
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
acol.x = sa1.x + (t * sa_x);
acol.y = sa1.y + (t * sa_y);
//acol.z = sa1.z;
acol.w = t;
return true;
}
return false;
}
bool segment_sphere(Vector3 s1, Vector3 s2, Vector3 c, double r){
var s1c = _v0;
s1c.setFrom(c).sub(s1);
var s = _v1;
s.setFrom(s2).sub(s1);
var sl2 = s.length2;
var sp;
if (sl2 == 0.0) {
sp = s1;
} else {
double u = (s1c.x * s.x + s1c.y *s.y) / sl2; // s1c.dot(s)
sp = (u < 0.0)? s1 : (u > 1.0) ? s2 : s.scale(u).add(s1);
}
var cs = _v2;
cs.setFrom(c).sub(sp);
double l2 = cs.length2;
if (l2 > r * r)
return false;
// double l = math.sqrt(l2);
// var t = (r - l) / l;
// var coll = cs.scale(t).add(c);
// ccol.setValues(coll.x, coll.y, coll.z, t);
return true;
}
bool sphere_sphere(Vector3 ca, double ra, Vector3 cb, double rb) {
var threshold = ra + rb;
// Get the Cathetus
var dx = (ca.x - cb.x);
var dy = (ca.y - cb.y);
// Calculate the distance
var dis2 = dx * dx + dy * dy;
// Returns whether the distance between the two particles is smaller then the sum of both radi
return (threshold * threshold >= dis2);
}
bool aabb_aabb( Aabb3 b1, Aabb3 b2 ) {
return ( b1.min.x <= b2.max.x) && ( b1.min.y <= b2.max.y )
&& ( b1.max.x >= b2.min.x ) && ( b1.max.y >= b2.min.y);
}
// use SAT check intersection (first againts the longer poly (nb of edge))
// [a] and [b] should be clockwise concave polygone
bool poly_poly(List<Vector3> a, List<Vector3> b) {
var separated = false;
separated = _poly_poly0(a, b);
separated = separated || _poly_poly0(b, a);
return !separated;
}
bool _poly_poly0(List<Vector3> a, List<Vector3> b) {
var axis = _v0;
MinMax amm = _mm0;
MinMax bmm = _mm1;
var separated = false;
for (var i = 0; (!separated) && (i < a.length); i++) {
// axis is the left normal of the side
axis.setFrom(a[(i+1) % a.length]).sub(a[i]);
var t = axis.x;
axis.x = - axis.y;
axis.y = t;
extractMinMaxProjection(a, axis, amm);
extractMinMaxProjection(b, axis, bmm);
separated = isSeparated(amm.min, amm.max, bmm.min, bmm.max);
}
return separated;
}
}
Implements
Static Properties
const zeroEpsilon #
static const zeroEpsilon = 0.0001
Methods
bool aabb_aabb(Aabb3 b1, Aabb3 b2) #
bool aabb_aabb( Aabb3 b1, Aabb3 b2 ) {
return ( b1.min.x <= b2.max.x) && ( b1.min.y <= b2.max.y )
&& ( b1.max.x >= b2.min.x ) && ( b1.max.y >= b2.min.y);
}
bool poly_poly(List<Vector3> a, List<Vector3> b) #
bool poly_poly(List<Vector3> a, List<Vector3> b) {
var separated = false;
separated = _poly_poly0(a, b);
separated = separated || _poly_poly0(b, a);
return !separated;
}
bool segment_segment(Vector3 sa1, Vector3 sa2, Vector3 sb1, Vector3 sb2, Vector4 acol) #
implementation from http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect based on Andre LeMothe's "Tricks of the Windows Game Programming Gurus".
bool segment_segment(Vector3 sa1, Vector3 sa2, Vector3 sb1, Vector3 sb2, Vector4 acol) {
var sa_x, sa_y, sb_x, sb_y;
sa_x = sa2.x - sa1.x; sa_y = sa2.y - sa1.y;
sb_x = sb2.x - sb1.x; sb_y = sb2.y - sb1.y;
var u = (sa_x * sb_y - sb_x * sa_y);
// u == 0 if segment are parallele, with double approximation, use 0.0001
//if (u < zeroEpsilon && u > -zeroEpsilon ) return false;
if (u == 0) return false;
var s = ( sa_x * (sa1.y - sb1.y) - sa_y * (sa1.x - sb1.x)) / u;
var t = ( sb_x * (sa1.y - sb1.y) - sb_y * (sa1.x - sb1.x)) / u;
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
acol.x = sa1.x + (t * sa_x);
acol.y = sa1.y + (t * sa_y);
//acol.z = sa1.z;
acol.w = t;
return true;
}
return false;
}
bool segment_sphere(Vector3 s1, Vector3 s2, Vector3 c, double r) #
bool segment_sphere(Vector3 s1, Vector3 s2, Vector3 c, double r){
var s1c = _v0;
s1c.setFrom(c).sub(s1);
var s = _v1;
s.setFrom(s2).sub(s1);
var sl2 = s.length2;
var sp;
if (sl2 == 0.0) {
sp = s1;
} else {
double u = (s1c.x * s.x + s1c.y *s.y) / sl2; // s1c.dot(s)
sp = (u < 0.0)? s1 : (u > 1.0) ? s2 : s.scale(u).add(s1);
}
var cs = _v2;
cs.setFrom(c).sub(sp);
double l2 = cs.length2;
if (l2 > r * r)
return false;
// double l = math.sqrt(l2);
// var t = (r - l) / l;
// var coll = cs.scale(t).add(c);
// ccol.setValues(coll.x, coll.y, coll.z, t);
return true;
}
bool sphere_sphere(Vector3 ca, double ra, Vector3 cb, double rb) #
bool sphere_sphere(Vector3 ca, double ra, Vector3 cb, double rb) {
var threshold = ra + rb;
// Get the Cathetus
var dx = (ca.x - cb.x);
var dy = (ca.y - cb.y);
// Calculate the distance
var dis2 = dx * dx + dy * dy;
// Returns whether the distance between the two particles is smaller then the sum of both radi
return (threshold * threshold >= dis2);
}