/** * Project the value given along the line segment, where 0 represents A and 1 represents B. * Tolerance is used to snap points to A or B if close enough. If u < 0 return A and if u > 1 * return B and the point is beyond the tolerance, return null * * @param u * @param tolerance tolerance for snapping to end points * @param target target vector * @throws IllegalArgumentException if u was infinite or NaN * @throws NullPointerException if tolerance or target was null */ public void projectClosest(double u, Tolerance tolerance, VectBuilder target) throws NullPointerException, IllegalArgumentException { double x = (u * (bx - ax)) + ax; double y = (u * (by - ay)) + ay; if ((u < 0) || tolerance.match(x, y, ax, ay)) { getA(target); } else if ((u > 1) || tolerance.match(x, y, bx, by)) { getB(target); } else { target.set(x, y); } }
static void intersectionLineCircleInternal( double ax, double ay, double bx, double by, double cx, double cy, double radius, Tolerance tolerance, VectBuilder working, VectList intersections) { projectOnToLineInternal( ax, ay, bx, by, cx, cy, tolerance, working); // get the closest point on the line to the circle center double dx = working.getX(); double dy = working.getY(); double distToLineSq = Vect.distSq(cx, cy, dx, dy); double radiusSq = radius * radius; switch (tolerance.check(distToLineSq - radiusSq)) { case 1: // dist to line is greater than radius - line does not intersect circle return; case 0: // dist to line matches radius - line touches circle intersections.add(dx, dy); return; default: // dist to line is less than radius - line crosses circle double mx = bx - ax; double my = by - ay; double segmentLen = Math.sqrt(mx * mx + my * my); double projectDist; if (tolerance.check(distToLineSq) == 0) { // line crosses circle center projectDist = radius; dx = cx; dy = cy; } else { projectDist = Math.sqrt(radiusSq - distToLineSq); } double mul = projectDist / segmentLen; mx *= mul; my *= mul; intersections.add(dx - mx, dy - my); intersections.add(dx + mx, dy + my); } }
static boolean project( double ax, double ay, double bx, double by, double u, Tolerance tolerance, VectBuilder target) { double x = (u * (bx - ax)) + ax; double y = (u * (by - ay)) + ay; if (tolerance.match(x, y, ax, ay)) { target.set(ax, ay); return true; } else if (tolerance.match(x, y, bx, by)) { target.set(bx, by); return true; } else { target.set(x, y); return ((u > 0) && (u < 1)); } }
/** * Determine if segments intersect. Segments which do not intersect, but are within the tolerance * given from each other are considered to intersect unless they are parallel * * @param line * @param tolerance * @return true if segments intersect, false otherwise * @throws NullPointerException if line or tolerance was null */ public boolean intersectsSeg(Line line, Tolerance tolerance) throws NullPointerException { double jax = line.ax; double jay = line.ay; double jbx = line.bx; double jby = line.by; double denom = getDenom(ax, ay, bx, by, jax, jay, jbx, jby); if (denom == 0.0) { // Lines are parallel. return false; } double ui = ((jbx - jax) * (ay - jay) - (jby - jay) * (ax - jax)) / denom; // projected distance along i and j double uj = ((bx - ax) * (ay - jay) - (by - ay) * (ax - jax)) / denom; if ((ui >= 0) && (ui <= 1) && (uj >= 0) && (uj <= 1)) { return true; } double x = (ui * (bx - ax)) + ax; double y = (ui * (by - ay)) + ay; if (ui < 0) { if (!tolerance.match(x, y, ax, ay)) { return false; } } else if (ui > 1) { if (!tolerance.match(x, y, bx, by)) { return false; } } if (uj < 0) { if (!tolerance.match(x, y, jax, jay)) { return false; } } else if (uj > 1) { if (!tolerance.match(x, y, jbx, jby)) { return false; } } return true; }
/** * Determine if the point given lies to the left, right, or on the line given. * * @param ax * @param ay * @param bx * @param by * @param x * @param y * @param accuracy * @return 1 if left of line, -1 if right of line, 0 if on line. */ public static int counterClockwise( double ax, double ay, double bx, double by, double x, double y, Tolerance accuracy) { bx -= ax; by -= ay; x -= ax; y -= ay; double ccw = x * by - y * bx; if (ccw == 0.0) { // Point is colinear - classify based on whether b is further away from a than // point ccw = ((x * x) + (y * y)) - ((bx * bx) + (by * by)); ccw = Math.max(ccw, 0); } return accuracy.check(ccw); }
static boolean intersectionSegInternal( double ax, double ay, double bx, double by, double jax, double jay, double jbx, double jby, Tolerance tolerance, VectBuilder target) throws NullPointerException { if (Vect.compare(ax, ay, bx, by) > 0) { double tmp = ax; ax = bx; bx = tmp; tmp = ay; ay = by; by = tmp; } if (Vect.compare(jax, jay, jbx, jby) > 0) { double tmp = jax; jax = jbx; jbx = tmp; tmp = jay; jay = jby; jby = tmp; } if (compare(ax, ay, bx, by, jax, jay, jbx, jby) > 0) { double tmp = ax; ax = jax; jax = tmp; tmp = ay; ay = jay; jay = tmp; tmp = bx; bx = jbx; jbx = tmp; tmp = by; by = jby; jby = tmp; } double denom = getDenom(ax, ay, bx, by, jax, jay, jbx, jby); if (denom == 0.0) { // Lines are parallel. return false; } double ui = ((jbx - jax) * (ay - jay) - (jby - jay) * (ax - jax)) / denom; // projected distance along i and j double uj = ((bx - ax) * (ay - jay) - (by - ay) * (ax - jax)) / denom; double x, y; if (ax == bx) { x = ax; } else if (jax == jbx) { x = jax; } else { x = (ui * (bx - ax)) + ax; } if (ay == by) { y = ay; } else if (jay == jby) { y = jay; } else { y = (ui * (by - ay)) + ay; } boolean ia = tolerance.match(x, y, ax, ay); boolean ib = tolerance.match(x, y, bx, by); boolean i = ia || ib || ((ui >= 0) && (ui <= 1)); boolean ja = tolerance.match(x, y, jax, jay); boolean jb = tolerance.match(x, y, jbx, jby); boolean j = ja || jb || ((uj >= 0) && (uj <= 1)); if (i && j) { if (ia) { target.set(ax, ay); } else if (ib) { target.set(bx, by); } else if (ja) { target.set(jax, jay); } else if (jb) { target.set(jbx, jby); } else { target.set(x, y); } return true; } return false; }
/** * Determine if this line is parallell to that given, with differences in slope within the * tolerance * * @param line * @param tolerance * @return * @throws NullPointerException if line or tolerance was null */ public boolean isParallel(Line line, Tolerance tolerance) throws NullPointerException { double denom = getDenom(ax, ay, bx, by, line.ax, line.ay, line.bx, line.by); return tolerance.match(denom, 0); }
/** * Get the side of the line on which vect lies. Positive values imply that it lies on the left of * the line. Negative values imply it lies on the right of the line. 0 implies it lies on the line * * @param vect * @param tolerance * @return * @throws IllegalStateException if invalid */ public int sign(Vect vect, Tolerance tolerance) throws NullPointerException { return tolerance.check(sign(vect)); }
/** * Determine if the distance between the end points is greater than the tolerance given * * @param tolerance * @return true if distance is greater, false otherwise */ public boolean isValid(Tolerance tolerance) { return (!tolerance.match(ax, ay, bx, by)); }