/* file : LineArc2D.java
 * 
 * Project : geometry
 *
 * ===========================================
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library. if not, write to :
 * The Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 * 
 *
 */

package math.geom2d.line;

import java.util.ArrayList;
import java.util.Collection;

import math.geom2d.*;
import math.geom2d.domain.SmoothOrientedCurve2D;
import math.utils.EqualUtils;

/**
 * LineArc2D is a generic class to represent edges, straight lines, and rays.
 * It is defined like other linear shapes: origin point, and direction vector.
 * Moreover, two internal variables t0 and t1 define the limit of the object
 * (with t0
 * 
  • t0=0 and t1=1: this is an edge.
  • *
  • t0=-inf and t1=inf: this is a straight line.
  • *
  • t0=0 and t1=inf: this is a ray.
  • *
  • t0=-inf and 0: this is an inverted ray.
  • * * @author dlegland */ public class LineArc2D extends AbstractLine2D implements SmoothOrientedCurve2D, Cloneable { // =================================================================== // Static constructor /** * Static factory for creating a new LineArc2D * @since 0.8.1 */ public static LineArc2D create(Point2D p1, Point2D p2, double t0, double t1) { return new LineArc2D(p1, p2, t0, t1); } // =================================================================== // class variables /** Lower bound of this arc parameterization */ protected double t0 = 0; /** Upper bound of this arc parameterization */ protected double t1 = 1; // =================================================================== // Constructors /** * @param point1 the point located at t=0 * @param point2 the point located at t=1 * @param t0 the lower bound of line arc parameterization * @param t1 the upper bound of line arc parameterization */ public LineArc2D(Point2D point1, Point2D point2, double t0, double t1) { this(point1.x(), point1.y(), point2.x()-point1.x(), point2.y()-point1.y(), t0, t1); } /** * Construct a line arc contained in the same straight line as first * argument, with bounds of arc given by t0 and t1 * * @param line an object defining the supporting line * @param t0 the lower bound of line arc parameterization * @param t1 the upper bound of line arc parameterization */ public LineArc2D(LinearShape2D line, double t0, double t1) { super(line.origin(), line.direction()); this.t0 = t0; this.t1 = t1; } /** * Construct a line arc by the parameters of the supporting line and two * positions on the line. * * @param x1 the x-coordinate of the first point * @param y1 the y-coordinate of the first point * @param dx the x-coordinate of the direction vector * @param dy the y-coordinate of the direction vector * @param t0 the starting position of the arc * @param t1 the ending position of the arc */ public LineArc2D(double x1, double y1, double dx, double dy, double t0, double t1) { super(x1, y1, dx, dy); this.t0 = t0; this.t1 = t1; } // =================================================================== // methods specific to LineArc2D /** * Returns the length of the line arc. */ @Override public double length() { if (this.isBounded()) return firstPoint().distance(lastPoint()); else return Double.POSITIVE_INFINITY; } public double getX1() { if (t0 != Double.NEGATIVE_INFINITY) return x0 + t0 * dx; else return Double.NEGATIVE_INFINITY; } public double getY1() { if (t0 != Double.NEGATIVE_INFINITY) return y0 + t0 * dy; else return Double.NEGATIVE_INFINITY; } public double getX2() { if (t1 != Double.POSITIVE_INFINITY) return x0 + t1 * dx; else return Double.POSITIVE_INFINITY; } public double getY2() { if (t1 != Double.POSITIVE_INFINITY) return y0 + t1 * dy; else return Double.POSITIVE_INFINITY; } // =================================================================== // methods implementing the CirculinearCurve2D interface /* (non-Javadoc) * @see math.geom2d.circulinear.CirculinearCurve2D#parallel(double) */ public LineArc2D parallel(double d) { double d2 = d / Math.hypot(dx, dy); return new LineArc2D(x0 + dy * d2, y0 - dx * d2, dx, dy, t0, t1); } // =================================================================== // methods of Curve2D interface /** * Returns the parameter of the first point of the line arc, * arbitrarily set to 0. */ public double t0() { return t0; } /** * @deprecated replaced by t0() (since 0.11.1). */ @Deprecated public double getT0() { return t0(); } /** * Returns the parameter of the last point of the line arc, * arbitrarily set to 1. */ public double t1() { return t1; } /** * @deprecated replaced by t1() (since 0.11.1). */ @Deprecated public double getT1() { return t1(); } public Point2D point(double t) { if (t < t0) t = t0; if (t > t1) t = t1; if (Double.isInfinite(t)) throw new UnboundedShape2DException(this); else return new Point2D(x0 + dx * t, y0 + dy * t); } /** * Returns the first point of the edge. In the case of a line, or a ray * starting from -infinity, throws an UnboundedShape2DException. * * @return the last point of the arc */ @Override public Point2D firstPoint() { if (!Double.isInfinite(t0)) return new Point2D(x0 + t0 * dx, y0 + t0 * dy); else throw new UnboundedShape2DException(this); } /** * Returns the last point of the edge. In the case of a line, or a ray * ending at infinity, throws an UnboundedShape2DException. * * @return the last point of the arc */ @Override public Point2D lastPoint() { if (!Double.isInfinite(t1)) return new Point2D(x0 + t1 * dx, y0 + t1 * dy); else throw new UnboundedShape2DException(this); } @Override public Collection singularPoints() { ArrayList list = new ArrayList(2); if (t0 != Double.NEGATIVE_INFINITY) list.add(this.firstPoint()); if (t1 != Double.POSITIVE_INFINITY) list.add(this.lastPoint()); return list; } @Override public boolean isSingular(double pos) { if (Math.abs(pos-t0) continuousCurves() { return wrapCurve(this); } /** * Returns the line arc which have the same trace, but has the inverse * parameterization. */ public LineArc2D reverse() { return new LineArc2D(x0, y0, -dx, -dy, -t1, -t0); } /** * Returns a new LineArc2D, which is the portion of this LineArc2D delimited * by parameters t0 and t1. */ @Override public LineArc2D subCurve(double t0, double t1) { t0 = Math.max(t0, this.t0()); t1 = Math.min(t1, this.t1()); return new LineArc2D(this, t0, t1); } // =================================================================== // methods of Shape2D interface /** * Returns true if both t0 and t1 are different from infinity. */ public boolean isBounded() { return t0 != Double.NEGATIVE_INFINITY && t1 != Double.POSITIVE_INFINITY; } /** * Returns the bounding box of this line arc. */ public Box2D boundingBox() { return new Box2D(x0 + t0 * dx, x0 + t1 * dx, y0 + t0 * dy, y0 + t1 * dy); } // =================================================================== // methods of Shape interface @Override public boolean contains(Point2D pt) { return contains(pt.x(), pt.y()); } public boolean contains(double xp, double yp) { if (!super.supportContains(xp, yp)) return false; // compute position on the line double t = positionOnLine(xp, yp); if (t - t0 < -ACCURACY) return false; if (t - t1 > ACCURACY) return false; return true; } public java.awt.geom.GeneralPath getGeneralPath() { if (!this.isBounded()) throw new UnboundedShape2DException(this); java.awt.geom.GeneralPath path = new java.awt.geom.GeneralPath(); path.moveTo((float) (x0 + t0 * dx), (float) (y0 + t0 * dy)); path.lineTo((float) (x0 + t1 * dx), (float) (y0 + t1 * dy)); return path; } /** * Appends a line to the current path. If t0 or t1 is infinite, throws a new * UnboundedShape2DException. * * @param path the path to modify * @return the modified path */ public java.awt.geom.GeneralPath appendPath(java.awt.geom.GeneralPath path) { if (!this.isBounded()) throw new UnboundedShape2DException(this); if (t0==Double.NEGATIVE_INFINITY) return path; if (t1==Double.POSITIVE_INFINITY) return path; path.lineTo((float) getX1(), (float) getY1()); path.lineTo((float) getX2(), (float) getY2()); return path; } @Override public LineArc2D transform(AffineTransform2D trans) { double[] tab = trans.coefficients(); double x1 = x0 * tab[0] + y0 * tab[1] + tab[2]; double y1 = x0 * tab[3] + y0 * tab[4] + tab[5]; return new LineArc2D(x1, y1, dx * tab[0] + dy * tab[1], dx * tab[3] + dy * tab[4], t0, t1); } @Override public String toString() { return new String("LineArc2D(" + x0 + "," + y0 + "," + dx + "," + dy + "," + t0 + "," + t1 +")"); } // =================================================================== // methods implementing the GeometricObject2D interface /* (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 LineArc2D)) return false; LineArc2D that = (LineArc2D) obj; // Compare each field if (!almostEquals(this.x0, that.x0, eps)) return false; if (!almostEquals(this.y0, that.y0, eps)) return false; if (!almostEquals(this.dx, that.dx, eps)) return false; if (!almostEquals(this.dy, that.dy, eps)) return false; if (!almostEquals(this.t0, that.t0, eps)) return false; if (!almostEquals(this.t1, that.t1, eps)) return false; return true; } /** * Compares two double values with a given accuracy, with correct result * for infinite values. Undefined results for NaNs. */ private static boolean almostEquals(double d1, double d2, double eps) { if (d1 == Double.POSITIVE_INFINITY && d2 == Double.POSITIVE_INFINITY) return true; if (d1 == Double.NEGATIVE_INFINITY && d2 == Double.NEGATIVE_INFINITY) return true; return Math.abs(d1 - d2) < eps; } // =================================================================== // methods of Object interface @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof LineArc2D)) return false; LineArc2D that = (LineArc2D) obj; // Compare each field if (!EqualUtils.areEqual(this.x0, that.x0)) return false; if (!EqualUtils.areEqual(this.y0, that.y0)) return false; if (!EqualUtils.areEqual(this.dx, that.dx)) return false; if (!EqualUtils.areEqual(this.dy, that.dy)) return false; if (!EqualUtils.areEqual(this.t0, that.t0)) return false; if (!EqualUtils.areEqual(this.t1, that.t1)) return false; return true; } /** * @deprecated use copy constructor instead (0.11.2) */ @Deprecated @Override public LineArc2D clone() { return new LineArc2D(x0, y0, dx, dy, t0, t1); } }

    Ads help maintain this website.