Android examples for java.lang:Math Geometry
Compute the intersection between two line segments, or two lines of infinite length.
/******************************************************************************* * Copyright (c) 2011 MadRobot.//from w w w. ja v a 2 s . com * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Elton Kent - initial API and implementation ******************************************************************************/ //package com.java2s; import android.graphics.PointF; public class Main { /** * Compute the intersection between two line segments, or two lines * of infinite length. * * @param x0 * X coordinate first end point first line segment. * @param y0 * Y coordinate first end point first line segment. * @param x1 * X coordinate second end point first line segment. * @param y1 * Y coordinate second end point first line segment. * @param x2 * X coordinate first end point second line segment. * @param y2 * Y coordinate first end point second line segment. * @param x3 * X coordinate second end point second line segment. * @param y3 * Y coordinate second end point second line segment. * @param intersection * [2] Preallocated by caller to double[2] * @return -1 if lines are parallel (x,y unset), * -2 if lines are parallel and overlapping (x, y center) * 0 if intesrection outside segments (x,y set) * +1 if segments intersect (x,y set) */ public static int findLineSegmentIntersection(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float[] intersection) { // TODO: Make limit depend on input domain final float LIMIT = 1e-5f; final float INFINITY = 1e10f; float x, y; // // Convert the lines to the form y = ax + b // // Slope of the two lines float a0 = equals(x0, x1, LIMIT) ? INFINITY : (y0 - y1) / (x0 - x1); float a1 = equals(x2, x3, LIMIT) ? INFINITY : (y2 - y3) / (x2 - x3); float b0 = y0 - a0 * x0; float b1 = y2 - a1 * x2; // Check if lines are parallel if (equals(a0, a1)) { if (!equals(b0, b1)) { return -1; // Parallell non-overlapping } else { if (equals(x0, x1)) { if ((Math.min(y0, y1) < Math.max(y2, y3)) || (Math.max(y0, y1) > Math.min(y2, y3))) { float twoMiddle = y0 + y1 + y2 + y3 - min(y0, y1, y2, y3) - max(y0, y1, y2, y3); y = (twoMiddle) / 2.0f; x = (y - b0) / a0; } else { return -1; // Parallell non-overlapping } } else { if ((Math.min(x0, x1) < Math.max(x2, x3)) || (Math.max(x0, x1) > Math.min(x2, x3))) { float twoMiddle = x0 + x1 + x2 + x3 - min(x0, x1, x2, x3) - max(x0, x1, x2, x3); x = (twoMiddle) / 2.0f; y = a0 * x + b0; } else { return -1; } } intersection[0] = x; intersection[1] = y; return -2; } } // Find correct intersection point if (equals(a0, INFINITY)) { x = x0; y = a1 * x + b1; } else if (equals(a1, INFINITY)) { x = x2; y = a0 * x + b0; } else { x = -(b0 - b1) / (a0 - a1); y = a0 * x + b0; } intersection[0] = x; intersection[1] = y; // Then check if intersection is within line segments float distanceFrom1; if (equals(x0, x1)) { if (y0 < y1) { distanceFrom1 = y < y0 ? length(new PointF(x, y), new PointF(x0, y0)) : y > y1 ? length(new PointF(x, y), new PointF(x1, y1)) : 0.0f; } else { distanceFrom1 = y < y1 ? length(new PointF(x, y), new PointF(x1, y1)) : y > y0 ? length(new PointF(x, y), new PointF(x0, y0)) : 0.0f; } } else { if (x0 < x1) { distanceFrom1 = x < x0 ? length(new PointF(x, y), new PointF(x0, y0)) : x > x1 ? length(new PointF(x, y), new PointF(x1, y1)) : 0.0f; } else { distanceFrom1 = x < x1 ? length(new PointF(x, y), new PointF(x1, y1)) : x > x0 ? length(new PointF(x, y), new PointF(x0, y0)) : 0.0f; } } float distanceFrom2; if (equals(x2, x3)) { if (y2 < y3) { distanceFrom2 = y < y2 ? length(new PointF(x, y), new PointF(x2, y2)) : y > y3 ? length(new PointF(x, y), new PointF(x3, y3)) : 0.0f; } else { distanceFrom2 = y < y3 ? length(new PointF(x, y), new PointF(x3, y3)) : y > y2 ? length(new PointF(x, y), new PointF(x2, y2)) : 0.0f; } } else { if (x2 < x3) { distanceFrom2 = x < x2 ? length(new PointF(x, y), new PointF(x2, y2)) : x > x3 ? length(new PointF(x, y), new PointF(x3, y3)) : 0.0f; } else { distanceFrom2 = x < x3 ? length(new PointF(x, y), new PointF(x3, y3)) : x > x2 ? length(new PointF(x, y), new PointF(x2, y2)) : 0.0f; } } return equals(distanceFrom1, 0.0f) && equals(distanceFrom2, 0.0f) ? 1 : 0; } /** * Check if two double precision numbers are "equal", i.e. close enough * to a prespecified limit. * * @param a * First number to check * @param b * Second number to check * @return True if the twho numbers are "equal", false otherwise */ private static boolean equals(float a, float b) { return equals(a, b, 1.0e-5f); } /** * Check if two double precision numbers are "equal", i.e. close enough * to a given limit. * * @param a * First number to check * @param b * Second number to check * @param limit * The definition of "equal". * @return True if the twho numbers are "equal", false otherwise */ private static boolean equals(float a, float b, float limit) { return Math.abs(a - b) < limit; } /** * Return smallest of four numbers. * * @param a * First number to find smallest among. * @param b * Second number to find smallest among. * @param c * Third number to find smallest among. * @param d * Fourth number to find smallest among. * @return Smallest of a, b, c and d. */ private static float min(float a, float b, float c, float d) { return Math.min(Math.min(a, b), Math.min(c, d)); } /** * Return largest of four numbers. * * @param a * First number to find largest among. * @param b * Second number to find largest among. * @param c * Third number to find largest among. * @param d * Fourth number to find largest among. * @return Largest of a, b, c and d. */ private static float max(float a, float b, float c, float d) { return Math.max(Math.max(a, b), Math.max(c, d)); } public static float length(float ax, float ay) { return (float) Math.sqrt(ax * ax + ay * ay); } public static float length(float ax, float ay, float bx, float by) { PointF v = createVector(ax, ay, bx, by); return length(v); } /** * Return the length of a vector. * * @param v * Vector Point * @return Length of vector. */ public static float length(PointF v) { return length(v.x, v.y); } /** * Compute distance between two points. * * @param p0 * starting point * @param p1 * ending point * * @return Distance between points. */ public static float length(PointF p0, PointF p1) { PointF v = createVector(p0, p1); return length(v); } public static PointF createVector(float ax, float ay, float bx, float by) { PointF point = new PointF(); point.x = bx - ax; point.y = by - ay; return point; } /** * Construct the vector specified by two points. * * @param lineStart * The coordinate of the line starting point * @param lineEnd * The coordinate of the line ending point * * @return The Vector point */ public static PointF createVector(PointF lineStart, PointF lineEnd) { return createVector(lineStart.x, lineStart.y, lineEnd.x, lineEnd.y); } }