package math.geom2d.conic;
import static java.lang.Math.max;
import static java.lang.Math.min;

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

import math.geom2d.*;
import math.geom2d.curve.*;
import math.geom2d.domain.SmoothOrientedCurve2D;
import math.geom2d.line.LinearShape2D;
import math.utils.EqualUtils;

/**
 * An arc of hyperbola, defined from the parent hyperbola branch, and two
 * positions on the parent curve.
 * 
 * @author dlegland
 */
public class HyperbolaBranchArc2D extends AbstractSmoothCurve2D
implements SmoothOrientedCurve2D, Cloneable {

    // ===================================================================
    // constructor

    public static HyperbolaBranchArc2D create(HyperbolaBranch2D branch, 
    		double t0, double t1) {
       return new HyperbolaBranchArc2D(branch, t0, t1);
    }

    
    // ===================================================================
    // class variables

    /** The supporting hyperbola branch */
    HyperbolaBranch2D branch = null;

	/**
	 * The lower bound if the parameterization for this arc.
	 */
	double t0 = 0;

	/**
	 * The upper bound if the parameterization for this arc.
	 */
	double t1 = 1;

    // ===================================================================
    // constructor

	/**
	 * Constructor from a branch and two bounds.
	 */
    public HyperbolaBranchArc2D(HyperbolaBranch2D branch, double t0, double t1) {
        this.branch = branch;
        this.t0 = t0;
        this.t1 = t1;
    }

    
    // ===================================================================
    // methods specific to the arc

    public HyperbolaBranch2D getHyperbolaBranch() {
        return branch;
    }

    // ===================================================================
    // methods inherited from SmoothCurve2D interface

    public double curvature(double t) {
        return branch.curvature(t);
    }

    public Vector2D tangent(double t) {
        return branch.tangent(t);
    }

    // ===================================================================
    // methods inherited from OrientedCurve2D interface

    public double signedDistance(Point2D point) {
        return this.signedDistance(point.x(), point.y());
    }

    public double signedDistance(double x, double y) {
        // TODO Auto-generated method stub
        return 0;
    }

    public double windingAngle(Point2D point) {
        // TODO Auto-generated method stub
        return 0;
    }

    public boolean isInside(Point2D pt) {
        // TODO Auto-generated method stub
        return false;
    }

    // ===================================================================
    // methods inherited from ContinuousCurve2D interface

    public java.awt.geom.GeneralPath appendPath(java.awt.geom.GeneralPath path) {
        return this.asPolyline(60).appendPath(path);
    }

    /** Returns false. */
    public boolean isClosed() {
        return false;
    }

    // ===================================================================
    // methods inherited from Curve2D interface

    public Collection intersections(LinearShape2D line) {
		Collection inters0 = this.branch.intersections(line);
		ArrayList inters = new ArrayList();
		for (Point2D point : inters0) {
			double pos = this.branch.project(point);
			if (pos > this.t0 && pos < this.t1)
				inters.add(point);
		}

        return inters;
    }

    /**
     * If t0 equals minus infinity, throws an UnboundedShapeException.
     */
   public Point2D point(double t) {
       if(Double.isInfinite(t))
           throw new UnboundedShape2DException(this);
        t = min(max(t, t0), t1);
        return branch.point(t);
    }

    public double position(Point2D point) {
        if (!this.branch.contains(point))
			return Double.NaN;
		double t = this.branch.position(point);
		if (t - t0 < -ACCURACY)
			return Double.NaN;
		if (t1 - t < ACCURACY)
			return Double.NaN;
		return t;
    }

    public double project(Point2D point) {
        double t = this.branch.project(point);
        return min(max(t, t0), t1);
    }

    public HyperbolaBranchArc2D reverse() {
        Hyperbola2D hyper = branch.hyperbola;
        Hyperbola2D hyper2 = new Hyperbola2D(hyper.xc, hyper.yc, hyper.a,
                hyper.b, hyper.theta, !hyper.direct);
        return new HyperbolaBranchArc2D(new HyperbolaBranch2D(hyper2,
                branch.positive), -t1, -t0);
    }

    /**
     * Returns a new HyperbolaBranchArc2D, with same parent hyperbola branch,
     * and with new parameterization bounds. The new bounds are constrained to
     * belong to the old bounds interval. If t1, which contains only instances of
     * HyperbolaBranchArc2D. If the shape is not clipped, the result is an
     * instance of CurveSet2D which contains 0 curves.
     */
    public CurveSet2D clip(Box2D box) {
        // Clip the curve
        CurveSet2D set = Curves2D.clipSmoothCurve(this, box);

        // Stores the result in appropriate structure
        CurveArray2D result = 
        	new CurveArray2D(set.size());

        // convert the result
        for (Curve2D curve : set.curves()) {
            if (curve instanceof HyperbolaBranchArc2D)
                result.add((HyperbolaBranchArc2D) curve);
        }
        return result;
    }

    public double distance(Point2D point) {
        Point2D p = point(project(point));
        return p.distance(point);
    }

    public double distance(double x, double y) {
        Point2D p = point(project(new Point2D(x, y)));
        return p.distance(x, y);
    }

    public boolean isBounded() {
		if (t0 == Double.NEGATIVE_INFINITY)
			return false;
		if (t1 == Double.POSITIVE_INFINITY)
			return false;
        return true;
    }

    public boolean isEmpty() {
        return false;
    }

    public HyperbolaBranchArc2D transform(AffineTransform2D trans) {
    	// transform the parent branch
        HyperbolaBranch2D branch2 = branch.transform(trans);

        // Compute position of end points on the transformed parabola
        double startPos = Double.isInfinite(t0) ? Double.NEGATIVE_INFINITY
                : branch2.project(this.firstPoint().transform(trans));
        double endPos = Double.isInfinite(t1) ? Double.POSITIVE_INFINITY
                : branch2.project(this.lastPoint().transform(trans));

        // Compute the new arc
		if (startPos > endPos) {
        	return new HyperbolaBranchArc2D(branch2.reverse(), 
        			endPos, startPos);
        } else {
        	return new HyperbolaBranchArc2D(branch2, startPos, endPos);
        }
    }

    public boolean contains(Point2D p) {
        return this.contains(p.x(), p.y());
    }

    public boolean contains(double x, double y) {
		if (!branch.contains(x, y))
			return false;
		double t = branch.position(new Point2D(x, y));
		if (t < t0)
			return false;
		if (t > t1)
			return false;
		return true;
	}

    public java.awt.geom.GeneralPath getGeneralPath() {
        if (!this.isBounded())
            throw new UnboundedShape2DException(this);
        return this.asPolyline(100).asGeneralPath();
    }

    
	// ===================================================================
	// 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 HyperbolaBranchArc2D))
            return false;
        HyperbolaBranchArc2D arc = (HyperbolaBranchArc2D) obj;
        
        if(!branch.almostEquals(arc.branch, eps)) return false;
		if (Math.abs(t0 - arc.t0) > eps)
			return false;
		if (Math.abs(t1 - arc.t1) > eps)
			return false;
     return true;
    }

    // ===================================================================
    // methods overriding object
  
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof HyperbolaBranchArc2D))
            return false;
        HyperbolaBranchArc2D that = (HyperbolaBranchArc2D) obj;
        
        if(!branch.equals(that.branch)) return false;
		if (!EqualUtils.areEqual(this.t0, that.t0)) 
			return false;
		if (!EqualUtils.areEqual(this.t1, that.t1)) 
			return false;
        return true;
    }

    @Override
    public HyperbolaBranchArc2D clone() {
        return new HyperbolaBranchArc2D(branch, t0, t1);
    }
}

 

Ads help maintain this website.