Print

Print


Author: [log in to unmask]
Date: Wed Oct 19 13:10:51 2016
New Revision: 4516

Log:
Circle fitting utilities

Added:
    java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/
    java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/CircleFit.java
    java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/TwoPointRadiusCircleFitter.java

Added: java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/CircleFit.java
 =============================================================================
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/CircleFit.java	(added)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/CircleFit.java	Wed Oct 19 13:10:51 2016
@@ -0,0 +1,85 @@
+package org.hps.recon.tracking.circlefit;
+
+/**
+ * A class which encapsulates the result of a circle fit.
+ *
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class CircleFit
+{
+
+    private double _x0;
+    private double _y0;
+    private double _r;
+
+    /**
+     * Creates a new instance of CircleFit
+     *
+     * @param x0 the x coordinate of the center of the circle
+     * @param y0 the y coordinate of the center of the circle
+     * @param r the radius of the circle
+     */
+    public CircleFit(double x0, double y0, double r)
+    {
+        _x0 = x0;
+        _y0 = y0;
+        _r = r;
+    }
+
+    /**
+     * The x coordinate of the center of the circle.
+     *
+     * @return the x coordinate of the center of the circle
+     */
+    public double x0()
+    {
+        return _x0;
+    }
+
+    /**
+     * The y coordinate of the center of the circle
+     *
+     * @return
+     */
+    public double y0()
+    {
+        return _y0;
+    }
+
+    /**
+     * The radius of the circle
+     *
+     * @return the radius of the circle
+     */
+    public double radius()
+    {
+        return _r;
+    }
+
+    /**
+     * Return the slope of the tangent (dy/dx) at a point on this circle (does
+     * not check if point is on circle)
+     *
+     * @param p double array assumed to be (x, y)
+     * @return the slope of the tangent to this circle at the point p
+     */
+    public double tangentAtPoint(double[] p)
+    {
+        double tangent;
+        tangent = -(p[0] - _x0) / (p[1] - _y0);
+        return tangent;
+    }
+
+    /**
+     * String representation of this object
+     *
+     * @return String representation of this object
+     */
+    public String toString()
+    {
+        return "CircleFit: x0= " + _x0 + " y0= " + _y0 + " r= " + _r;
+    }
+
+}

Added: java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/TwoPointRadiusCircleFitter.java
 =============================================================================
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/TwoPointRadiusCircleFitter.java	(added)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/circlefit/TwoPointRadiusCircleFitter.java	Wed Oct 19 13:10:51 2016
@@ -0,0 +1,71 @@
+package org.hps.recon.tracking.circlefit;
+
+import static java.lang.Math.hypot;
+import static java.lang.Math.pow;
+import static java.lang.Math.sqrt;
+
+/**
+ * Fits a circle to two points and a radius
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class TwoPointRadiusCircleFitter
+{
+
+    private static boolean _debug = false;
+
+    static double distance(double[] p1, double[] p2)
+    {
+        return hypot((p1[0] - p2[0]), p1[1] - p2[1]);
+    }
+
+    /**
+     * Returns two circles which can be fit to two points and a radius
+     * @param p1 A point on the cricle 
+     * @param p2 Another point on the circle
+     * @param radius The radius of the circle
+     * @return The two circles which can be fit, or null 
+     */
+    public static CircleFit[] findCircles(double[] p1, double[] p2, double radius)
+    {
+        CircleFit[] results = null;
+        double separation = distance(p1, p2);
+        double mirrorDistance;
+
+        if (separation == 0.0) {
+            if (radius == 0.0) {
+                if (_debug) {
+                    System.out.printf("\nNo circles can be drawn through (%.4f,%.4f)", p1[0], p1[1]);
+                }
+            } else {
+                if (_debug) {
+                    System.out.printf("\nInfinitely many circles can be drawn through (%.4f,%.4f)", p1[0], p1[1]);
+                }
+            }
+        } else if (separation == 2 * radius) {
+            results = new CircleFit[1];
+            results[0] = new CircleFit((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2, radius);
+            if (_debug) {
+                System.out.printf("\nGiven points are opposite ends of a diameter of the circle with center (%.4f,%.4f) and radius %.4f", (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2, radius);
+            }
+        } else if (separation > 2 * radius) {
+            if (_debug) {
+                System.out.printf("\nGiven points are farther away from each other than a diameter of a circle with radius %.4f", radius);
+            }
+        } else {
+            mirrorDistance = sqrt(pow(radius, 2) - pow(separation / 2, 2));
+            results = new CircleFit[2];
+            results[0] = new CircleFit((p1[0] + p2[0]) / 2 + mirrorDistance * (p1[1] - p2[1]) / separation, (p1[1] + p2[1]) / 2 + mirrorDistance * (p2[0] - p1[0]) / separation, radius);
+            results[1] = new CircleFit((p1[0] + p2[0]) / 2 - mirrorDistance * (p1[1] - p2[1]) / separation, (p1[1] + p2[1]) / 2 - mirrorDistance * (p2[0] - p1[0]) / separation, radius);
+            if (_debug) {
+                System.out.printf("\nTwo circles are possible.");
+            }
+            if (_debug) {
+                System.out.printf("\nCircle C1 with center (%.4f,%.4f), radius %.4f and Circle C2 with center (%.4f,%.4f), radius %.4f", (p1[0] + p2[0]) / 2 + mirrorDistance * (p1[1] - p2[1]) / separation, (p1[1] + p2[1]) / 2 + mirrorDistance * (p2[0] - p1[0]) / separation, radius, (p1[0] + p2[0]) / 2 - mirrorDistance * (p1[1] - p2[1]) / separation, (p1[1] + p2[1]) / 2 - mirrorDistance * (p2[0] - p1[0]) / separation, radius);
+            }
+        }
+        return results;
+    }
+
+}