View Javadoc

1   // Copyright 2004, FreeHEP.
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  }