import java.awt.Polygon; public class DPolygon { /* This class represents a convex polygon (x,y) in double format. More importantly, it includes wonderful convenient simple functions for manipulating polygons. */ public DPoint[] vertices; // the vertices of the polygon public DPoint center; // an approximate center for rotating around & collision detection public double radius; // the approximate distance from the furthest vertex to the center public DPolygon() // allocate memory for a new DPolygon { vertices = new DPoint[0]; center = new DPoint(0.0, 0.0); radius = 0.0; } public DPolygon(DPolygon poly) // make a copy of an existing DPolygon { vertices = new DPoint[poly.vertices.length]; for (int i = 0; i < vertices.length; i++) vertices[i] = new DPoint(poly.vertices[i]); center = new DPoint(poly.center); radius = poly.radius; } public DPolygon(double[] x, double[] y, double r, DPoint c) // create a new DPolygon { vertices = new DPoint[x.length]; for (int i = 0; i < x.length; i++) vertices[i] = new DPoint(x[i],y[i]); center = new DPoint(c); radius = r; } public void translate(double dx, double dy) // move the DPolygon one step { for (int i = 0; i < vertices.length; i++) { vertices[i].x += dx; vertices[i].y += dy; } center.translate(dx,dy); } public void rotate(double angle) // rotate the polygon ccw around the its center { rotate(center,angle); } public void rotate(DPoint origin, double angle) // rotate the polygon ccw about a point { for (int i = 0; i < vertices.length; i++) vertices[i].rotate(origin,angle); } // rotate public boolean inCollision(DPoint point) { // returns true if our DPolygon contains point, else false // quick check on distance if (center.distanceFrom(point) > radius) return false; boolean isLeftOfAll = true; // if point is left of all lines so far boolean isLeftOfLine; // if point is left of a line segment int i, j; // indices of consecutive counter-clockwise vertices double ix, iy, jx, jy; for (i = 0; i < vertices.length; i++) // check each edge { j = (i + 1) % vertices.length; ix = vertices[i].x; iy = vertices[i].y; jx = vertices[j].x; jy = vertices[j].y; if (ix == jx) // special case: vertical isLeftOfAll = isLeftOfAll && (iy > jy ? point.x <= ix : point.x >= ix); else // not vertical, we can use slope { // (y - k) - slope * (x - h) is positive if (x,y) is left of the line isLeftOfLine = (point.y - iy) - ((iy-jy)/(ix-jx)) * (point.x - ix) > 0.0; isLeftOfAll = isLeftOfAll && (ix > jx ? isLeftOfLine : !isLeftOfLine); } } return isLeftOfAll; } // inCollision(DPoint) public boolean inCollision(DPolygon poly) { // returns true if there is a collision with poly // This happens when any sides overlap or one is inside the other. // quick check on distance if (center.distanceFrom(poly.center) > radius + poly.radius) return false; // check if any sides overlap int i, j, m, n; for (i = 0; i < this.vertices.length; i++) // check each edge (this) { j = (i + 1) % this.vertices.length; for (m = 0; m < poly.vertices.length; m++) // check each edge (poly) { n = (m + 1) % poly.vertices.length; DPoint pt = DPoint.intersection(this.vertices[i], this.vertices[j], poly.vertices[m], poly.vertices[n]); if (pt != null && pt.isBetween(this.vertices[i], this.vertices[j]) && pt.isBetween(poly.vertices[m], poly.vertices[n]) ) return true; } } // check if one is completely inside the other return this.inCollision(poly.vertices[0]) || poly.inCollision(this.vertices[0]); } // inCollision(DPolygon) public Polygon toPolygon() // convert our double polygon to an integer polygon { int length = vertices.length; int[] x = new int[length], y = new int[length]; for (int i = 0; i < length; i++) { x[i] = new Double(vertices[i].x).intValue(); y[i] = new Double(vertices[i].y).intValue(); } return new Polygon(x,y,length); } }