Here you can find the source of curvedLineHit(Point point, Point startPoint, Point endPoint, Point controlPoint1, Point controlPoint2, float padding)
Parameter | Description |
---|---|
point | the Point on the line |
startPoint | the Start Point |
endPoint | the End Point |
controlPoint1 | the First Control Point |
controlPoint2 | the Second Control Point |
padding | the area surrounding the curve |
public static boolean curvedLineHit(Point point, Point startPoint, Point endPoint, Point controlPoint1, Point controlPoint2, float padding)
//package com.java2s; /*//from www.j a v a 2s .c o m * Twirl Editor - Petri-Net Editor * * Copyright (C) 2009 Neil Brittliff * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ import java.awt.Point; public class Main { /** * Find the square of the distance between the point and a point on the * curve (u). use newtons method to approach the minumum u. * * @param point * the Point on the line * @param startPoint * the Start Point * @param endPoint * the End Point * @param controlPoint1 * the First Control Point * @param controlPoint2 * the Second Control Point * @param padding * the area surrounding the curve * * @return TRUE point is on the curve, FALSE otherwise * */ public static boolean curvedLineHit(Point point, Point startPoint, Point endPoint, Point controlPoint1, Point controlPoint2, float padding) { Point a[] = new Point[4]; // our regular coefficients double c[] = new double[7]; // a cubic squared gives us 7 coefficients double u; double tolerance = padding + 1 / 2; double delta; double minDelta; int i; tolerance *= tolerance; parameterizeCurve(a, startPoint, endPoint, controlPoint1, controlPoint2); delta = a[0].x - point.x; c[0] = delta * delta; delta = a[0].y - point.y; c[0] += delta * delta; c[1] = 2 * ((a[0].x - point.x) * a[1].x + (a[0].y - point.y) * a[1].y); c[2] = a[1].x * a[1].x + a[1].y * a[1].y + 2 * (a[2].x * (a[0].x - point.x) + a[2].y * (a[0].y - point.y)); c[3] = 2 * (a[1].x * a[2].x + (a[0].x - point.x) * a[3].x + a[1].y * a[2].y + (a[0].y - point.y) * a[3].y); c[4] = a[2].x * a[2].x + a[2].y * a[2].y + 2 * (a[1].x * a[3].x + a[1].y * a[3].y); c[5] = 2.0 * (a[2].x * a[3].x + a[2].y * a[3].y); c[6] = a[3].x * a[3].x + a[3].y * a[3].y; // Estimate a starting U if (endPoint.x < startPoint.x) { u = point.x - endPoint.x; } else { u = point.x - startPoint.x; delta = endPoint.x - startPoint.x; } delta = Math.abs(startPoint.x - point.x) + Math.abs(endPoint.x - point.x); delta += Math.abs(startPoint.y - point.y) + Math.abs(endPoint.y - point.y); if (endPoint.y < startPoint.y) { u += point.y - endPoint.y; delta += startPoint.y - endPoint.y; } else { u += point.y - startPoint.y; delta += endPoint.y - startPoint.y; } u /= delta; u = (u < 0) ? 0 : (u > 1) ? 1 : u; // Iterate while adjust U with our error function // NOTE: Sadly, Newton's method becomes unstable as we approach the // solution. Also, the farther away from the curve, the wider the // oscillation will be. // To get around this, we're keeping track of our best result, adding a // few more iterations, and damping our approach. minDelta = 100000; for (i = 0; i < 12; i++) { delta = (((((c[6] * u + c[5]) * u + c[4]) * u + c[3]) * u + c[2]) * u + c[1]) * u + c[0]; if (delta < minDelta) { minDelta = delta; } if (i == 11 && minDelta <= tolerance) { return true; } else { double slope = (((((6 * c[6] * u + 5 * c[5]) * u + 4 * c[4]) * u + 3 * c[3]) * u + 2 * c[2]) * u + c[1]); double deltaU = delta / slope; if ((u == 0 && delta > 0) || (u == 1 && delta < 0)) { return minDelta <= tolerance; } u -= 0.75 * deltaU; // Used to be just deltaU, but we're damping // it a bit u = u < 0.0 ? 0.0 : u > 1.0 ? 1.0 : u; } } return false; } /** * Given a curveto's endpoints and control points, compute the coefficients * to trace out the curve as p(t) = c[0] + c[1]*t + c[2]*t^2 + c[3]*t^3 * * @param coefficients * the Coefficients * @param startPoint * the Start Point * @param endPoint * the End Point * @param controlPoint1 * the First Control Point * @param controlPoint2 * the Second Control Point * @param padding * the area surrounding the curve * */ static void parameterizeCurve(Point[] coefficients, Point startPoint, Point endPoint, Point controlPoint1, Point controlPoint2) { Point tangent2 = new Point(); tangent2.x = (int) (3.0 * (endPoint.x - controlPoint2.x)); tangent2.y = (int) (3.0 * (endPoint.y - controlPoint2.y)); coefficients[0] = startPoint; coefficients[1] = new Point((int) (3.0 * (controlPoint1.x - startPoint.x)), (int) (3.0 * (controlPoint1.y - startPoint.y))); // tangent coefficients[2] = new Point( (int) (3.0 * (endPoint.x - startPoint.x) - 2.0 * coefficients[1].x - tangent2.x), (int) (3.0 * (endPoint.y - startPoint.y) - 2.0 * coefficients[1].y - tangent2.y)); coefficients[3] = new Point((int) (2.0 * (startPoint.x - endPoint.x) + coefficients[1].x + tangent2.x), (int) (2.0 * (startPoint.y - endPoint.y) + coefficients[1].y + tangent2.y)); } }