/** * 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; }
public void render(Color c, int stroke, int markType) { final boolean db = false; // Get array of visible segments. If no such array exists, // use default. DArray vseg = visSeg; boolean dashed = false; // if (step == 0) { double step = renderStep(); // } // vp V = TestBed.view(); if (db) Streams.out.println(" step=" + step); // plot each visible segment for (int seg = 0; seg < vseg.size(); seg += 2) { double t0 = vseg.getDouble(seg + 0), t1 = vseg.getDouble(seg + 1); t0 = MyMath.clamp(t0, -500.0, 500.0); t1 = MyMath.clamp(t1, -500.0, 500.0); // render() expects external parameters. double s0 = toExt(t0), s1 = toExt(t1); if (s0 > s1) { double tmp = s0; s0 = s1; s1 = tmp; } FPoint2 p0 = calcPoint(s0), p1 = calcPoint(s1); if (db) Streams.out.println(" p0=" + p0 + ", p1=" + p1); if (isLine() && !dashed) { V.drawLine(p0, p1); } else { /* if (Math.abs(s0) >= 500 ||Math.abs(s1) >= 500) System.out.println("Rendering "+t0+" to "+t1+" step "+step); */ if (dashed) V.pushStroke(Globals.STRK_RUBBERBAND); { // int count = 0; boolean first = true; for (double t = t0; ; t += step) { // , count++) { boolean last = (t >= t1); if (last) { t = t1; } calcPointInternal(t, p1); if (!p1.isValid()) { if (last) { break; } continue; } if (db) { System.out.println(" calcPt " + Tools.f(toExt(t)) + " = " + p1.x + "," + p1.y); } if (!first) { V.drawLine(p0, p1); if (false) { Tools.warn("highlighting int"); V.mark(p0); } } if (last) { break; } p0.setLocation(p1); first = false; } } if (dashed) V.popStroke(); } } }