Find the square of the distance between the point and a point on the curve (u). - Java java.lang

Java examples for java.lang:Math Geometry Distance

Description

Find the square of the distance between the point and a point on the curve (u).

Demo Code

/*//from w w  w.  j  a v a2  s  . 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.
 *
 */
//package com.java2s;
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));

    }
}

Related Tutorials