/* * (non-Javadoc) * * @see math.geom2d.OrientedCurve2D#windingAngle(math.geom2d.Point2D) */ public double windingAngle(Point2D point) { Point2D p1 = point(0); Point2D p2 = point(abs(angleExtent)); // compute angle of point with extreme points double angle1 = Angle2D.horizontalAngle(point, p1); double angle2 = Angle2D.horizontalAngle(point, p2); // test on which 'side' of the arc the point lie boolean b1 = (new StraightLine2D(p1, p2)).isInside(point); boolean b2 = ellipse.isInside(point); if (angleExtent > 0) { if (b1 || b2) { // inside of ellipse arc if (angle2 > angle1) return angle2 - angle1; else return 2 * PI - angle1 + angle2; } else { // outside of ellipse arc if (angle2 > angle1) return angle2 - angle1 - 2 * PI; else return angle2 - angle1; } } else { if (!b1 || b2) { if (angle1 > angle2) return angle2 - angle1; else return angle2 - angle1 - 2 * PI; } else { if (angle1 > angle2) return angle2 - angle1 + 2 * PI; else return angle2 - angle1; } } }
/* * (non-Javadoc) * * @see math.geom2d.Curve2D#position(math.geom2d.Point2D) */ public double position(Point2D point) { double angle = Angle2D.horizontalAngle(ellipse.center(), point); if (this.containsAngle(angle)) if (angleExtent > 0) return Angle2D.formatAngle(angle - startAngle); else return Angle2D.formatAngle(startAngle - angle); // If the point is not contained in the arc, return NaN. return Double.NaN; }
/** Returns a new CircleArc2D. t0 and t1 are position on circle. */ public CircleArc2D subCurve(double t0, double t1) { double startAngle, extent; if (this.direct) { startAngle = t0; extent = Angle2D.formatAngle(t1 - t0); } else { extent = -Angle2D.formatAngle(t1 - t0); startAngle = Angle2D.formatAngle(-t0); } return new CircleArc2D(this, startAngle, extent); }
/** Returns a new EllipseArc2D. */ public EllipseArc2D subCurve(double t0, double t1) { // convert position to angle t0 = Angle2D.formatAngle(startAngle + t0); t1 = Angle2D.formatAngle(startAngle + t1); // check bounds of angles if (!Angle2D.containsAngle(startAngle, startAngle + angleExtent, t0, angleExtent > 0)) t0 = startAngle; if (!Angle2D.containsAngle(startAngle, startAngle + angleExtent, t1, angleExtent > 0)) t1 = angleExtent; // create new arc return new EllipseArc2D(ellipse, t0, t1, angleExtent > 0); }
public double project(Point2D point) { double angle = ellipse.project(point); // Case of an angle contained in the ellipse arc if (this.containsAngle(angle)) { if (angleExtent > 0) return Angle2D.formatAngle(angle - startAngle); else return Angle2D.formatAngle(startAngle - angle); } // return either 0 or T1, depending on which extremity is closer. double d1 = this.firstPoint().distance(point); double d2 = this.lastPoint().distance(point); return d1 < d2 ? 0 : abs(angleExtent); }
/** * Computes the projection position of the point on the circle, by computing angle with * horizonrtal */ public double project(Point2D point) { double xp = point.x() - this.xc; double yp = point.y() - this.yc; // compute angle return Angle2D.horizontalAngle(xp, yp); }
/** * Computes the radical axis of the two circles. * * @since 0.11.1 * @return the radical axis of the two circles. * @throws IllegalArgumentException if the two circles have same center */ public static StraightLine2D radicalAxis(Circle2D circle1, Circle2D circle2) { // extract center and radius of each circle double r1 = circle1.radius(); double r2 = circle2.radius(); Point2D p1 = circle1.center(); Point2D p2 = circle2.center(); // compute horizontal angle of joining line double angle = Angle2D.horizontalAngle(p1, p2); // distance between centers double dist = p1.distance(p2); if (dist < Shape2D.ACCURACY) { throw new IllegalArgumentException("Input circles must have distinct centers"); } // position of the radical axis on the joining line double d = (dist * dist + r1 * r1 - r2 * r2) * .5 / dist; // pre-compute trigonometric functions double cot = Math.cos(angle); double sit = Math.sin(angle); // compute parameters of the line double x0 = p1.x() + d * cot; double y0 = p1.y() + d * sit; double dx = -sit; double dy = cot; // update state of current line return new StraightLine2D(x0, y0, dx, dy); }
/** @deprecated replaced by circlesIntersections(Circle2D, Circle2D) (0.11.1) */ @Deprecated public static Collection<Point2D> getIntersections(Circle2D circle1, Circle2D circle2) { ArrayList<Point2D> intersections = new ArrayList<Point2D>(2); // extract center and radius of each circle Point2D center1 = circle1.center(); Point2D center2 = circle2.center(); double r1 = circle1.radius(); double r2 = circle2.radius(); double d = Point2D.distance(center1, center2); // case of no intersection if (d < abs(r1 - r2) || d > (r1 + r2)) return intersections; // Angle of line from center1 to center2 double angle = Angle2D.horizontalAngle(center1, center2); // position of intermediate point double d1 = d / 2 + (r1 * r1 - r2 * r2) / (2 * d); Point2D tmp = Point2D.createPolar(center1, d1, angle); // Add the 2 intersection points double h = sqrt(r1 * r1 - d1 * d1); intersections.add(Point2D.createPolar(tmp, h, angle + PI / 2)); intersections.add(Point2D.createPolar(tmp, h, angle - PI / 2)); return intersections; }
/* (non-Javadoc) * @see math.geom2d.GeometricObject2D#almostEquals(math.geom2d.GeometricObject2D, double) */ public boolean almostEquals(GeometricObject2D obj, double eps) { if (this == obj) return true; if (!(obj instanceof EllipseArc2D)) return false; EllipseArc2D arc = (EllipseArc2D) obj; // test whether supporting ellipses have same support if (abs(ellipse.xc - arc.ellipse.xc) > eps) return false; if (abs(ellipse.yc - arc.ellipse.yc) > eps) return false; if (abs(ellipse.r1 - arc.ellipse.r1) > eps) return false; if (abs(ellipse.r2 - arc.ellipse.r2) > eps) return false; if (abs(ellipse.theta - arc.ellipse.theta) > eps) return false; // test if angles are the same if (!Angle2D.equals(startAngle, arc.startAngle)) return false; if (!Angle2D.equals(angleExtent, arc.angleExtent)) return false; return true; }
public Box2D boundingBox() { // first get ending points Point2D p0 = firstPoint(); Point2D p1 = lastPoint(); // get coordinate of ending points double x0 = p0.x(); double y0 = p0.y(); double x1 = p1.x(); double y1 = p1.y(); // initialize min and max coords double xmin = min(x0, x1); double xmax = max(x0, x1); double ymin = min(y0, y1); double ymax = max(y0, y1); // precomputes some values Point2D center = ellipse.center(); double xc = center.x(); double yc = center.y(); double endAngle = startAngle + angleExtent; boolean direct = angleExtent >= 0; // check cases arc contains one maximum if (Angle2D.containsAngle(startAngle, endAngle, PI / 2 + ellipse.theta, direct)) ymax = max(ymax, yc + ellipse.r1); if (Angle2D.containsAngle(startAngle, endAngle, 3 * PI / 2 + ellipse.theta, direct)) ymin = min(ymin, yc - ellipse.r1); if (Angle2D.containsAngle(startAngle, endAngle, ellipse.theta, direct)) xmax = max(xmax, xc + ellipse.r2); if (Angle2D.containsAngle(startAngle, endAngle, PI + ellipse.theta, direct)) xmin = min(xmin, xc - ellipse.r2); // return a bounding with computed limits return new Box2D(xmin, xmax, ymin, ymax); }
/** Specify parameters of supporting ellipse, bounding angles and flag for direct ellipse. */ public EllipseArc2D( double xc, double yc, double a, double b, double theta, double start, double end, boolean direct) { this.ellipse = new Ellipse2D(xc, yc, a, b, theta); this.startAngle = start; this.angleExtent = Angle2D.formatAngle(end - start); if (!direct) this.angleExtent = this.angleExtent - PI * 2; }
/** * Computes the intersections points between two circles or circular shapes. * * @param circle1 an instance of circle or circle arc * @param circle2 an instance of circle or circle arc * @return a collection of 0, 1 or 2 intersection points */ public static Collection<Point2D> circlesIntersections(Circle2D circle1, Circle2D circle2) { // extract center and radius of each circle Point2D center1 = circle1.center(); Point2D center2 = circle2.center(); double r1 = circle1.radius(); double r2 = circle2.radius(); double d = Point2D.distance(center1, center2); // case of no intersection if (d < abs(r1 - r2) || d > (r1 + r2)) return new ArrayList<Point2D>(0); // Angle of line from center1 to center2 double angle = Angle2D.horizontalAngle(center1, center2); if (d == abs(r1 - r2) || d == (r1 + r2)) { Collection<Point2D> r = new ArrayList<>(1); r.add(Point2D.createPolar(center1, r1, angle)); return r; } // position of intermediate point double d1 = d / 2 + (r1 * r1 - r2 * r2) / (2 * d); Point2D tmp = Point2D.createPolar(center1, d1, angle); // distance between intermediate point and each intersection double h = sqrt(r1 * r1 - d1 * d1); // create empty array ArrayList<Point2D> intersections = new ArrayList<Point2D>(2); // Add the 2 intersection points Point2D p1 = Point2D.createPolar(tmp, h, angle + PI / 2); intersections.add(p1); Point2D p2 = Point2D.createPolar(tmp, h, angle - PI / 2); intersections.add(p2); return intersections; }
public double position(Point2D point) { double angle = Angle2D.horizontalAngle(xc, yc, point.x(), point.y()); if (direct) return Angle2D.formatAngle(angle - theta); else return Angle2D.formatAngle(theta - angle); }
/** * Returns the ellipse arc which refers to the reversed parent ellipse, with same start angle, and * with opposite angle extent. */ public EllipseArc2D reverse() { double newStart = Angle2D.formatAngle(startAngle + angleExtent); return new EllipseArc2D(ellipse, newStart, -angleExtent); }
/** Returns the angle associated with the given position */ public double getAngle(double position) { if (position < 0) position = 0; if (position > abs(angleExtent)) position = abs(angleExtent); if (angleExtent < 0) position = -position; return Angle2D.formatAngle(startAngle + position); }
public boolean containsAngle(double angle) { return Angle2D.containsAngle(startAngle, startAngle + angleExtent, angle, angleExtent > 0); }