Compute the distance between two segments. - Java java.lang

Java examples for java.lang:Math Trigonometric Function

Description

Compute the distance between two segments.

Demo Code

/* // w  ww. j av a2 s  .co  m
 * $Id$
 * 
 * Copyright (C) 2010-2011 Janus Core Developers
 * Copyright (C) 2012 St?phane GALLAND
 * 
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

public class Main{
    /** Compute the distance between two segments.
     *
     * @param p position of the point.
     * @param s1 position of the first point of the segment.
     * @param s2 position of the second point of the segment.
     * @return the distance beetween the segments.
     */
    public static final float distanceSegmentToSegment(Point2f s1,
            Point2f s2, Point2f s3, Point2f s4) {
        float f = getSegmentSegmentIntersectionFactor(s1, s2, s3, s4);
        if (!Float.isNaN(f)) {
            return 0f;
        }
        float d1 = distancePointToSegment(s1, s3, s4);
        float d2 = distancePointToSegment(s2, s3, s4);
        float d3 = distancePointToSegment(s3, s1, s2);
        float d4 = distancePointToSegment(s4, s1, s2);
        return MathUtil.min(d1, d2, d3, d4);
    }
    /**
     * Replies one position factor for the intersection point between two lines.
     * <p>
     * Let line equations for L1 and L2:<br>
     * <code>L1: P1 + factor1 * (P2-P1)</code><br>
     * <code>L2: P3 + factor2 * (P4-P3)</code><br>
     * If lines are intersecting, then<br>
     * <code>P1 + factor1 * (P2-P1) = P3 + factor2 * (P4-P3)</code>
     * <p>
     * This function computes and replies <code>factor1</code>.
     * 
     * @param p1
     *            is the coordinates of the first point of the first segment.
     * @param p2
     *            is the coordinates of the second point of the first segment.
     * @param p3
     *            is the coordinates of the first point of the second segment.
     * @param p4
     *            is the coordinates of the second point of the second segment.
     * @return <code>factor1</code> or {@link Float#NaN} if no intersection.
     */
    public static float getSegmentSegmentIntersectionFactor(Point2f p1,
            Point2f p2, Point2f p3, Point2f p4) {
        Vector2f v1 = p2.operator_minus(p1);
        Vector2f v2 = p4.operator_minus(p3);

        // determinant is zero when parallel = det(L1,L2)
        float det = determinant(v1, v2);
        if (det == 0f)
            return Float.NaN;

        // Given line equations:
        // Pa = P1 + ua (P2-P1), and
        // Pb = P3 + ub (P4-P3)
        // and
        // V = (P1-P3)
        // then
        // ua = det(L2,V) / det(L1,L2)
        // ub = det(L1,V) / det(L1,L2)
        Vector2f v3 = p1.operator_minus(p3);
        float u = determinant(v1, v3) / det;
        if (u < 0. || u > 1.)
            return Float.NaN;
        u = determinant(v2, v3) / det;
        return (u < 0. || u > 1.) ? Float.NaN : u;
    }
    /** Compute the distance between a point and a segment.
     *
     * @param p position of the point.
     * @param s1 position of the first point of the segment.
     * @param s2 position of the second point of the segment.
     * @return the distance beetween the point and the segment.
     */
    public static final float distancePointToSegment(Point2f p, Point2f s1,
            Point2f s2) {
        float r_denomenator = (s2.getX() - s1.getX())
                * (s2.getX() - s1.getX()) + (s2.getY() - s1.getY())
                * (s2.getY() - s1.getY());
        if (r_denomenator == 0f)
            return p.distance(s1);
        float r_numerator = (p.getX() - s1.getX())
                * (s2.getX() - s1.getX()) + (p.getY() - s1.getY())
                * (s2.getY() - s1.getY());
        float ratio = r_numerator / r_denomenator;

        if (ratio <= 0.) {
            return (float) Math.sqrt((p.getX() - s1.getX())
                    * (p.getX() - s1.getX()) + (p.getY() - s1.getY())
                    * (p.getY() - s1.getY()));
        }

        if (ratio >= 1f) {
            return (float) Math.sqrt((p.getX() - s2.getX())
                    * (p.getX() - s2.getX()) + (p.getY() - s2.getY())
                    * (p.getY() - s2.getY()));
        }

        float s = ((s1.getY() - p.getY()) * (s2.getX() - s1.getX()) - (s1
                .getX() - p.getX()) * (s2.getY() - s1.getY()))
                / r_denomenator;
        return (float) (Math.abs(s) * Math.sqrt(r_denomenator));
    }
    /** Replies the min value in the given values.
     *
     * @return the min value.
     */
    public static float min(float... values) {
        float min = values[0];
        for (int i = 1; i < values.length; ++i) {
            if (min > values[i]) {
                min = values[i];
            }
        }
        return min;
    }
    private static float determinant(Tuple2f<?> a, Tuple2f<?> b) {
        return a.getX() * b.getY() - b.getX() * a.getY();
    }
}

Related Tutorials