package org.iplantc.phyloviewer.shared.scene; import org.iplantc.phyloviewer.shared.math.Box2D; import org.iplantc.phyloviewer.shared.math.Vector2; import org.iplantc.phyloviewer.shared.render.IGraphics; import org.iplantc.phyloviewer.shared.render.style.IStyle; public class Polygon extends Drawable { Vector2 vertices[]; public Polygon(Vector2 vertices[]) { this.vertices = vertices; Box2D box = new Box2D(); for(Vector2 v : vertices) { box.expandBy(v); } this.setBoundingBox(box); } /** * Create a triangle from the 3 vertices. * * @param v0 * @param v1 * @param v2 * @return */ public static Polygon createTriangle(Vector2 v0, Vector2 v1, Vector2 v2) { Vector2 vertices[] = new Vector2[3]; vertices[0] = v0; vertices[1] = v1; vertices[2] = v2; Polygon triangle = new Polygon(vertices); return triangle; } @Override public void draw(IGraphics graphics, IStyle style) { if(graphics != null && vertices != null) { if(style != null) { graphics.setStyle(style.getGlyphStyle()); } graphics.drawPolygon(vertices); } } @Override public boolean intersect(Vector2 position, double distanceSquared) { if(vertices == null) { return false; } // Specialize for a triangle. // Should we have a shape classes in addition to just polygon (ie Triangle)? if(vertices.length == 3) { // Compute the barycentric coordinates to determine if the point is inside the triangle. Vector2 t0 = vertices[1].subtract(vertices[0]); Vector2 t1 = vertices[2].subtract(vertices[0]); Vector2 t2 = position.subtract(vertices[0]); // Compute dot products. double dot00 = t0.dot(t0); double dot01 = t0.dot(t1); double dot11 = t1.dot(t1); double dot20 = t2.dot(t0); double dot21 = t2.dot(t1); // Compute barycentric coordinates using ratio of the triangle areas. // This is twice the area of the triangle, but since we are using ratios, this is ok. double triangleArea = (dot00 * dot11 - dot01 * dot01); double invDenom = 1.0 / triangleArea; double u = (dot11 * dot20 - dot01 * dot21) * invDenom; double v = (dot00 * dot21 - dot01 * dot20) * invDenom; // The point is inside the triangle if barycentric coordinates u,v,w are all between 0 and 1. return (u >= 0) && (v >= 0) && ((u + v) <= 1); } return false; } @Override public int getDrawableType() { return TYPE_POLYGON; } }