Пример #1
0
  /**
   * Determine closest point on hyperbolic arm to a point pt
   *
   * @param pt : point
   * @return t value for closest point; not necessarily within clipped range
   */
  public double closestPointTo(FPoint2 pt) {

    final boolean db = false;

    pt = toCurveSpace(pt, null);

    double U = B + 1;
    double V = -pt.y;
    double W = B * pt.x;

    Polyn p =
        new Polyn( //
            B * U * U, //
            2 * B * U * V, //
            B * V * V + A * U * U - W * W, //
            2 * A * U * V, //
            A * V * V //
            );

    if (db) Streams.out.println("closestPointTo, pt=" + pt + "\n" + p);
    double ret = 0;

    try {
      DArray r = new DArray();

      if (Math.abs(p.c(0)) < 1e-5) r.addDouble(0);
      else p.solve(r);

      if (r.isEmpty()) {
        throw new FPError("can't find closest point, poly=\n" + p);
      }

      double bestDist = 0;

      for (int i = 0; i < r.size(); i++) {
        double t = r.getDouble(i);
        FPoint2 apt = calcPoint(t);
        double dist = apt.distance(pt);
        if (i == 0 || dist < bestDist) {
          bestDist = dist;
          ret = t;
        }
      }
    } catch (FPError e) {
      Tools.warn("caught FPError");
      //      Streams.out.println("caught:\n" + e);
      ret = (this.minParameter() + this.maxParameter()) * .5;
    }

    return ret;
  }
Пример #2
0
  /**
   * Construct a hyperbola
   *
   * @param f1 FPoint2 : first focus
   * @param f2 FPoint2 : second focus
   * @param interceptDistance : closest distance of point on arm to f1
   */
  public Hyperbola(FPoint2 f1, FPoint2 f2, double interceptDistance) {
    double fDist = f2.distance(f1);
    if (!(interceptDistance >= 0 && interceptDistance <= fDist))
      throw new FPError(
          "Hyperbola construction: icept="
              + Tools.f(interceptDistance)
              + " of max "
              + Tools.f(fDist)
              + "\n f1="
              + f1
              + " f2="
              + f2);

    double ratio = 0;
    if (fDist > 0) {
      ratio = interceptDistance / fDist;
    }
    FPoint2 pt = FPoint2.interpolate(f1, f2, ratio);
    construct(f1, f2, pt);
  }
Пример #3
0
  /**
   * Test program for Hyperbola class
   *
   * @param args String[]
   */
  public static void main(String[] args) {

    final double[] pts = { //
      100, 0, -100, 0, 75, 20,

      //  120, 30, -100, -10, 70, 50,
    };

    for (int i = 0; i < pts.length; i += 6) {
      try {
        Hyperbola h =
            new Hyperbola(
                new FPoint2(pts[i + 0], pts[i + 1]),
                new FPoint2(pts[i + 2], pts[i + 3]),
                new FPoint2(pts[i + 4], pts[i + 5]));
        System.out.println("Constructed:\n" + h);

        for (double t = -50; t <= 50; t += 10) {

          FPoint2 pt = h.calcPoint(t);

          FPoint2 pt2 = new FPoint2(pt.x, pt.y + 5);

          double tClosest = h.closestPointTo(pt2);

          System.out.println("t=" + Tools.f(t) + " pt=" + pt + " closest=" + tClosest);

          if (t == -20) {
            for (double t2 = tClosest - .1; t2 <= tClosest + .1; t2 += .01) {
              FPoint2 pt3 = h.calcPoint(t2);
              Streams.out.println("t2=" + t2 + " dist=" + pt3.distance(pt2));
            }
          }
        }

      } catch (TBError e) {
        System.out.println(e.toString());
      }
    }
  }
Пример #4
0
  /**
   * Constructor
   *
   * @param f1 FPoint2
   * @param f2 FPoint2
   * @param pt FPoint2, or null for bisector
   */
  private void construct(FPoint2 f1, FPoint2 f2, FPoint2 pt) {

    //    userData[LEFT] = new DArray();
    //    userData[RIGHT]  =new DArray();

    final boolean db = false;
    if (db) {
      System.out.println("Hyperbola constructor\n f1=" + f1 + "\n f2=" + f2 + "\n pt=" + pt);
    }
    boolean bisector = (pt == null);
    initializeVisibleSegments();

    // if point on arm is closer to f2 than f1, swap f1 & f2.

    if (!bisector && FPoint2.distanceSquared(f1, pt) > FPoint2.distanceSquared(f2, pt)) {
      flipped = true;
    }

    this.foci[RIGHT] = new FPoint2(f1);
    this.foci[LEFT] = new FPoint2(f2);
    if (!bisector) {
      this.pt = new FPoint2(pt);
    }

    double fociDist = FPoint2.distance(f1, f2);
    if (fociDist == 0) {
      throw new FPError("Hyperbola foci are same point");
    }

    c = fociDist * .5;

    // calculate the translation of the hyperbola away from
    // standard position.

    FPoint2 rFocus = getFocus(0), lFocus = getFocus(1);

    origin = new FPoint2(.5 * (rFocus.x + lFocus.x), .5 * (rFocus.y + lFocus.y));

    // calculate the angle of rotation of the hyperbola away
    // from the standard position.

    double theta = Math.atan2(rFocus.y - lFocus.y, rFocus.x - lFocus.x);

    Matrix fromCenterInW = Matrix.getTranslate(origin, true);
    Matrix rotToE = Matrix.getRotate(-theta);

    toE2 = rotToE;
    Matrix.mult(toE2, fromCenterInW, toE2);
    // calculate inverse

    toW2 = toE2.invert(null);

    //      Matrix toCenterInW = Matrix.translationMatrix(origin, false);
    //      Matrix rotToW = Matrix.getRotate2D(theta);
    //
    //      toW2 = toCenterInW;
    //      Matrix.mult(toW2, rotToW, toW2);
    //      Tools.warn("just invert matrix here");
    //

    if (bisector) {
      valid = true;
    } else {
      // get the arm point in hyperbola space.
      FPoint2 workPt = toE2.apply(pt, null);

      double xs = workPt.x * workPt.x;
      double cs = c * c;

      Polyn q = new Polyn(1, -(cs + xs + workPt.y * workPt.y), cs * xs);
      if (db) {
        System.out.println("a2 quadratic:\n" + q);
      }
      final DArray qsoln = new DArray();
      q.solve(qsoln);
      if (db) {
        Streams.out.println(qsoln);
      }
      double val = q.c(1) * -.5;
      int ql = qsoln.size();
      if (ql >= 1) {
        val = qsoln.getDouble(0);
      }

      // choose the root that is less than c*c.

      if (ql == 2) {
        if (val > qsoln.getDouble(1)) {
          val = qsoln.getDouble(1);
          if (db) {
            System.out.println(" two roots, choosing smaller.");
          }
        }
      }
      if (db) {
        System.out.println(" root chosen=" + val);
      }

      a = Polyn.sqrt(val);
      A = a * a;
      B = A / (c * c - A);
    }
    valid = true;
    if (db) {
      System.out.println(" ==> " + this);
    }
  }