1
2 package hep.wired.heprep.util;
3
4 import java.awt.geom.*;
5 import java.io.*;
6
7 import org.freehep.graphicsio.QuadToCubicPathConstructor;
8
9 /***
10 * Constructs a path while keeping track of the nearest point on that path to an arbitrary
11 * given point.
12 *
13 * @author Mark Donszelmann
14 * @version $Id: NearestPointPathConstructor.java 289 2004-06-22 22:59:36Z duns $
15 */
16 public class NearestPointPathConstructor extends QuadToCubicPathConstructor {
17
18 private Point2D arbitraryPoint;
19 private Point2D nearestPoint = new Point2D.Double();
20 private Point2D nearestPointOnPath = new Point2D.Double();
21 private double distanceSq = Double.MAX_VALUE;
22
23 private transient Point2D p1 = new Point2D.Double();
24 private transient Point2D p2 = new Point2D.Double();
25 private transient CubicCurve2D c = new CubicCurve2D.Double();
26
27 /***
28 * Creates a path constructor with given arbitrary point
29 */
30 public NearestPointPathConstructor(Point2D arbitraryPoint) {
31 this.arbitraryPoint = arbitraryPoint;
32 }
33
34 /***
35 * Adds a line to the path, called from addPath.
36 */
37 public void line(double x, double y) throws IOException {
38 p1.setLocation(currentX, currentY);
39 p2.setLocation(x, y);
40 check(NearestPoint.onLine(p1, p2, arbitraryPoint, nearestPoint));
41 super.line(x, y);
42 }
43
44 /***
45 * Adds a cubic bezier to the path, called from addPath.
46 */
47 public void cubic(double x1, double y1, double x2, double y2, double x3, double y3) throws IOException {
48 c.setCurve(currentX, currentY, x1, y1, x2, y2, x3, y3);
49 check(NearestPoint.onCurve(c, arbitraryPoint, nearestPoint));
50 super.cubic(x1, y1, x2, y2, x3, y3);
51 }
52
53 /***
54 * Closes the current path, called from addPath.
55 */
56 public void closePath(double x0, double y0) throws IOException {
57 p1.setLocation(currentX, currentY);
58 p2.setLocation(x0, y0);
59 check(NearestPoint.onLine(p1, p2, arbitraryPoint, nearestPoint));
60 super.closePath(x0, y0);
61 }
62
63 /***
64 * Returns nearest point on path, nearest to the given arbitrary point, or null if path is empty.
65 */
66 public Point2D getNearestPoint() {
67 return distanceSq == Double.MAX_VALUE ? null : nearestPointOnPath;
68 }
69
70 /***
71 * Returns squared distance from the arbitrary point to the nearest point on path.
72 * If path is empty, -1 is returned.
73 */
74 public double distanceSq() {
75 return distanceSq == Double.MAX_VALUE ? -1 : distanceSq;
76 }
77
78 private void check(double dsq) {
79 if (dsq < distanceSq) {
80 distanceSq = dsq;
81 nearestPointOnPath.setLocation(nearestPoint);
82 pointFound(new Point2D.Double(nearestPoint.getX(), nearestPoint.getY()), distanceSq, true);
83 } else if (dsq == distanceSq) {
84 pointFound(new Point2D.Double(nearestPoint.getX(), nearestPoint.getY()), distanceSq, false);
85 }
86 }
87
88 /***
89 * Called when a closer or equal point is found, so that the subclass
90 * can use this to track some other information, such as keeping a reference
91 * to the closest object(s).
92 */
93 protected void pointFound(Point2D nearestPoint, double distanceSq, boolean closer) {
94 }
95 }