package org.iplantc.phyloviewer.shared.math; import com.google.gwt.user.client.rpc.IsSerializable; public class AnnularSector implements IsSerializable { private PolarVector2 min; private PolarVector2 max; public AnnularSector() { this.min = new PolarVector2(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); this.max = new PolarVector2(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); } public AnnularSector(PolarVector2 min, PolarVector2 max) { if (min == max) { max = new PolarVector2(min); } this.min = min; this.max = max; } public AnnularSector(PolarVector2 initPoint) { this(initPoint, new PolarVector2(initPoint)); } public PolarVector2 getMin() { return min; } public void setMin(PolarVector2 min) { this.min = min; } public PolarVector2 getMax() { return max; } public void setMax(PolarVector2 max) { this.max = max; } public void expandBy(AnnularSector other) { if (!other.isValid()) { return; } double minRadius = Math.min(other.getMin().getRadius(), this.getMin().getRadius()); double maxRadius = Math.max(other.getMax().getRadius(), this.getMax().getRadius()); double minAngle = Math.min(other.getMin().getAngle(), this.getMin().getAngle()); double maxAngle = Math.max(other.getMax().getAngle(), this.getMax().getAngle()); min.setRadius(minRadius); min.setAngle(minAngle); max.setRadius(maxRadius); max.setAngle(maxAngle); } public void expandBy(Vector2 v) { PolarVector2 pv = new PolarVector2(v); this.expandBy(pv); } public void expandBy(PolarVector2 pv) { if (!pv.isValid()) { return; } min.setAngle(Math.min(min.getAngle(), pv.getAngle())); max.setAngle(Math.max(max.getAngle(), pv.getAngle())); min.setRadius(Math.min(min.getRadius(), pv.getRadius())); max.setRadius(Math.max(max.getRadius(), pv.getRadius())); } public boolean contains(Vector2 position) { PolarVector2 pv = new PolarVector2(position); return this.contains(pv); } public boolean contains(PolarVector2 pv) { return pv.isValid() && this.containsRadius(pv.getRadius()) && this.containsAngle(pv.getAngle()); } public boolean intersects(AnnularSector other) { return Math.max ( min.getRadius(), other.getMin().getRadius() ) <= Math.min ( max.getRadius(), other.getMax().getRadius() ) && Math.max ( min.getAngle(), other.getMin().getAngle() ) <= Math.min ( max.getAngle(), other.getMax().getAngle() ); } public Box2D cartesianBounds() { Vector2 min = this.getMin().toCartesian(); Vector2 otherInsideCorner = new PolarVector2(this.getMin().getRadius(), this.getMax().getAngle()).toCartesian(); Box2D bounds = getOuterArcBounds(); bounds.expandBy(min); bounds.expandBy(otherInsideCorner); return bounds; } public boolean isValid() { return min.isValid() && max.isValid() && max.getRadius() >= min.getRadius() && max.getAngle() >= min.getAngle(); } /** * Should be tight cartesian bounds of the outside arc of this AnnularSector */ public Box2D getOuterArcBounds() { double[] anglesToCheck = {0.0, Math.PI/2, Math.PI, 3 * Math.PI/2, 2 * Math.PI, this.min.getAngle(), this.max.getAngle()}; double outerRadius = this.getMax().getRadius(); Box2D bounds = new Box2D(); for (double angle : anglesToCheck) { if (this.containsAngle(angle)) { bounds.expandBy(new PolarVector2(outerRadius, angle).toCartesian()); } } return bounds; } private boolean containsAngle(double angle) { return angle >= min.getAngle() && angle <= max.getAngle(); } private boolean containsRadius(double radius) { return radius >= min.getRadius() && radius <= max.getRadius(); } @Override public String toString() { return "[" + this.min + ", " + this.max + "]"; } }