/** Geometry2D.pde basic parts of a 2D computational geometry library (none of these classes should be considered "complete") Dave Bollinger http://www.davebollinger.com */ public class Point2D { float x, y; public Point2D() { this(0f,0f); } public Point2D(float x, float y) { this.x = x; this.y = y; } public Point2D(Point2D p) { this(p.x, p.y); } public boolean equals(Point2D p) { return ((x==p.x) && (y==p.y)); } public void draw() { point(x, y); } } public class Vector2D extends Point2D { public Vector2D() { super(0f,0f); } public Vector2D(float x, float y) { super(x,y); } public Vector2D(Vector2D v) { super(v.x, v.y); } public boolean equals(Vector2D v) { return ((x==v.x) && (y==v.y)); } public float mag() { return sqrt(x*x+y*y); } public float magsq() { return x*x+y*y; } public Vector2D normalize() { float m = mag(); if (m > 0f) { x /= m; y /= m; } return this; } public Vector2D normalized() { return new Vector2D(this).normalize(); } public Vector2D add(Vector2D v) { return new Vector2D(x+v.x, y+v.y); } public Vector2D sub(Vector2D v) { return new Vector2D(x-v.x, y-v.y); } public Vector2D scale(float q) { return new Vector2D(x*q, y*q); } // mul/div are defined on Vector2D's to avoid having to have multiple scalar versions of scale() public Vector2D mul(Vector2D v) { return new Vector2D(x+v.x, y*v.y); } public Vector2D div(Vector2D v) { if ((v.x==0f) || (v.y==0f)) // uh, er, wtf? return this; return new Vector2D(x/v.x, y/v.y); } public Vector2D neg() { return new Vector2D(-x, -y); } public Vector2D lerp(Vector2D v, float t) { //return this.add(v.sub(this).scale(t)); return new Vector2D(x+(v.x-x)*t, y+(v.y-y)*t); } public Vector2D perp() { return new Vector2D(-y, x); } public Vector2D purp() { return new Vector2D(y, -x); } public float angle() { return atan2(y,x); } public float dot(Vector2D v) { return x*v.x + y*v.y; } public float kross(Vector2D v) { // aka perpdot, etc return x*v.y - y*v.x; } public void draw() { point(x,y); // or, more properly: line(0,0,x,y); } public void draw(float atx, float aty) { line(atx, aty, atx+x, aty+y); } public void draw(Vector2D atv) { draw(atv.x, atv.y); } } public class Line2D { Vector2D a, b; public Line2D() { this(0f,0f,0f,0f); } public Line2D(float ax, float ay, float bx, float by) { a = new Vector2D(ax,ay); b = new Vector2D(bx,by); } public Line2D(Vector2D a, Vector2D b) { this(a.x, a.y, b.x, b.y); } public Line2D(Line2D l) { this(l.a, l.b); } public boolean equals(Line2D l) { return (a.equals(l.a) && b.equals(l.b)); } public float len() { return b.sub(a).mag(); } public float lensq() { return b.sub(a).magsq(); } public float angle() { return b.sub(a).angle(); } public Vector2D midpoint() { return a.lerp(b, 0.5); } public void draw() { line(a.x, a.y, b.x, b.y); } } public class Triangle2D { Vector2D a, b, c; // and perhaps optionally maintain edges: // Line2D ab, bc, ca; public Triangle2D() { this(0f,0f,0f,0f,0f,0f); } public Triangle2D(float ax, float ay, float bx, float by, float cx, float cy) { a = new Vector2D(ax, ay); b = new Vector2D(bx, by); c = new Vector2D(cx, cy); } public Triangle2D(Vector2D a, Vector2D b, Vector2D c) { this(a.x, a.y, b.x, b.y, c.x, c.y); } public Triangle2D(Triangle2D t) { this(t.a, t.b, t.c); } public boolean equals(Triangle2D t) { return (a.equals(t.a) && b.equals(t.b) && c.equals(t.c)); } public void draw() { triangle(a.x, a.y, b.x, b.y, c.x, c.y); } private boolean overlaps(Triangle2D t, Vector2D axis) { float adota, adotb, adotc; adota = axis.dot(a); adotb = axis.dot(b); adotc = axis.dot(c); float minThis = min(min(adota, adotb), adotc); float maxThis = max(max(adota, adotb), adotc); adota = axis.dot(t.a); adotb = axis.dot(t.b); adotc = axis.dot(t.c); float minThat = min(min(adota, adotb), adotc); float maxThat = max(max(adota, adotb), adotc); return ((minThat <= maxThis) && (minThis <= maxThat)); } public boolean overlaps(Triangle2D t) { Vector2D edge, norm; Vector2D axis; axis = b.sub(a).perp(); // test is any of this tri's axes separate that tri's vertices if (!overlaps(t, b.sub(a).perp())) return false; if (!overlaps(t, c.sub(b).perp())) return false; if (!overlaps(t, a.sub(c).perp())) return false; // test is any of that tri's axes separate this tri's vertices if (!overlaps(t, t.b.sub(t.a).perp())) return false; if (!overlaps(t, t.c.sub(t.b).perp())) return false; if (!overlaps(t, t.a.sub(t.c).perp())) return false; // no separating axis, so return true; } }