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;
+ }
+
+}
|