/**
   * Clip out a section of the arm, using internal parameter values
   *
   * @param c0 : start of section to clip out
   * @param c1 : end of section to clip out; if < c0, c0 & c1 are swapped
   */
  private void clip0(double c0, double c1) {
    final boolean db = false;

    if (c0 > c1) {
      double t = c0;
      c0 = c1;
      c1 = t;
    }

    // array to store new clip elements in
    DArray nc = new DArray();

    if (db) {
      System.out.println("clip " + Tools.f(c0) + "..." + Tools.f(c1));
    }

    for (int i = 0; i < visSeg.size(); i += 2) {

      double t0 = visSeg.getDouble(i), t1 = visSeg.getDouble(i + 1);
      if (db) {

        System.out.println(" seg " + i + " " + Tools.f(t0) + "..." + Tools.f(t1));
      }

      // if this seg is outside clip region, leave intact (add it)
      if (t0 >= c1 || t1 <= c0) {
        nc.addDouble(t0);
        nc.addDouble(t1);
        continue;
      }

      if (t0 >= c0 && t1 <= c1) {
        if (db) {
          System.out.println("  clipping entire segment");
        }
        // remove entire segment, by skipping it
        continue;
      }

      // add unclipped portion
      if (t0 < c0) {
        nc.addDouble(t0);
        nc.addDouble(c0);
      }
      if (t1 > c1) {
        nc.addDouble(c1);
        nc.addDouble(t1);
      }
    }
    visSeg = nc;
    if (db) {
      System.out.println(" after clipping:" + visSeg);
    }
  }
  /**
   * 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;
  }