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 Line extends Drawable { Vector2 vertices[]; public Line(Vector2 vertices[]) { this.vertices = vertices; Box2D box = new Box2D(); for(Vector2 v : vertices) { box.expandBy(v); } this.setBoundingBox(box); } public Line(Vector2 vertices[], Box2D box) { this.vertices = vertices; this.setBoundingBox(box); } @Override public void draw(IGraphics graphics, IStyle style) { if(vertices != null && graphics != null) { if(style != null) { graphics.setStyle(style.getBranchStyle()); } graphics.drawLineStrip(vertices); } } @Override public boolean intersect(Vector2 position, double distanceSquared) { if(vertices == null || vertices.length < 2) { return false; } for(int i = 1;i < vertices.length;++i) { Vector2 start = vertices[i - 1]; Vector2 end = vertices[i]; double dSquared = distanceSquared(start, end, position); if(isPointInSegment(start, end, position) && dSquared < distanceSquared) { return true; } } return false; } public static boolean isPointInSegment(Vector2 start, Vector2 end, Vector2 position) { Vector2 w = position.subtract(start); Vector2 v = end.subtract(start); double t = w.dot(v) / v.dot(v); return t >= 0 && t <= 1; } public static double distanceSquared(Vector2 start, Vector2 end, Vector2 position) { // Turn the line segment into point, vector form of line. Vector2 p = start.clone(); Vector2 v = end.subtract(start); v.normalize(); Vector2 w = position.subtract(p); double vsq = v.dot(v); double wsq = w.dot(w); double proj = w.dot(v); return wsq - proj * proj / vsq; } @Override public int getDrawableType() { return TYPE_LINE; } }