private void findRightmostEdgeAtVertex() { /** * The rightmost point is an interior vertex, so it has a segment on either side of it. If these * segments are both above or below the rightmost point, we need to determine their relative * orientation to decide which is rightmost. */ Coordinate[] pts = minDe.getEdge().getCoordinates(); Assert.isTrue( minIndex > 0 && minIndex < pts.length, "rightmost point expected to be interior vertex of edge"); Coordinate pPrev = pts[minIndex - 1]; Coordinate pNext = pts[minIndex + 1]; int orientation = CGAlgorithms.computeOrientation(minCoord, pNext, pPrev); boolean usePrev = false; // both segments are below min point if (pPrev.y < minCoord.y && pNext.y < minCoord.y && orientation == CGAlgorithms.COUNTERCLOCKWISE) { usePrev = true; } else if (pPrev.y > minCoord.y && pNext.y > minCoord.y && orientation == CGAlgorithms.CLOCKWISE) { usePrev = true; } // if both segments are on the same side, do nothing - either is safe // to select as a rightmost segment if (usePrev) { minIndex = minIndex - 1; } }
public void computeIntersection(Coordinate p, Coordinate p1, Coordinate p2) { isProper = false; // do between check first, since it is faster than the orientation test if (Envelope.intersects(p1, p2, p)) { if ((CGAlgorithms.orientationIndex(p1, p2, p) == 0) && (CGAlgorithms.orientationIndex(p2, p1, p) == 0)) { isProper = true; if (p.equals(p1) || p.equals(p2)) { isProper = false; } result = POINT_INTERSECTION; return; } } result = NO_INTERSECTION; }
/** * Find the innermost enclosing shell EdgeRing containing the argument EdgeRing, if any. The * innermost enclosing ring is the <i>smallest</i> enclosing ring. The algorithm used depends on * the fact that: <br> * ring A contains ring B iff envelope(ring A) contains envelope(ring B) <br> * This routine is only safe to use if the chosen point of the hole is known to be properly * contained in a shell (which is guaranteed to be the case if the hole does not touch its shell) * * @return containing EdgeRing, if there is one or null if no containing EdgeRing is found */ public static EdgeRing findEdgeRingContaining(EdgeRing testEr, List shellList) { LinearRing testRing = testEr.getRing(); Envelope testEnv = testRing.getEnvelopeInternal(); Coordinate testPt = testRing.getCoordinateN(0); EdgeRing minShell = null; Envelope minShellEnv = null; for (Iterator it = shellList.iterator(); it.hasNext(); ) { EdgeRing tryShell = (EdgeRing) it.next(); LinearRing tryShellRing = tryShell.getRing(); Envelope tryShellEnv = tryShellRing.getEnvelopeInternal(); // the hole envelope cannot equal the shell envelope // (also guards against testing rings against themselves) if (tryShellEnv.equals(testEnv)) continue; // hole must be contained in shell if (!tryShellEnv.contains(testEnv)) continue; testPt = CoordinateArrays.ptNotInList(testRing.getCoordinates(), tryShellRing.getCoordinates()); boolean isContained = false; if (CGAlgorithms.isPointInRing(testPt, tryShellRing.getCoordinates())) isContained = true; // check if this new containing ring is smaller than the current minimum ring if (isContained) { if (minShell == null || minShellEnv.contains(tryShellEnv)) { minShell = tryShell; minShellEnv = minShell.getRing().getEnvelopeInternal(); } } } return minShell; }
/** * Finds the endpoint of the segments P and Q which is closest to the other segment. This is a * reasonable surrogate for the true intersection points in ill-conditioned cases (e.g. where two * segments are nearly coincident, or where the endpoint of one segment lies almost on the other * segment). * * <p>This replaces the older CentralEndpoint heuristic, which chose the wrong endpoint in some * cases where the segments had very distinct slopes and one endpoint lay almost on the other * segment. * * @param p1 an endpoint of segment P * @param p2 an endpoint of segment P * @param q1 an endpoint of segment Q * @param q2 an endpoint of segment Q * @return the nearest endpoint to the other segment */ private static Coordinate nearestEndpoint( Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { Coordinate nearestPt = p1; double minDist = CGAlgorithms.distancePointLine(p1, q1, q2); double dist = CGAlgorithms.distancePointLine(p2, q1, q2); if (dist < minDist) { minDist = dist; nearestPt = p2; } dist = CGAlgorithms.distancePointLine(q1, p1, p2); if (dist < minDist) { minDist = dist; nearestPt = q1; } dist = CGAlgorithms.distancePointLine(q2, p1, p2); if (dist < minDist) { minDist = dist; nearestPt = q2; } return nearestPt; }
protected int computeIntersect(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { isProper = false; // first try a fast test to see if the envelopes of the lines intersect if (!Envelope.intersects(p1, p2, q1, q2)) return NO_INTERSECTION; // for each endpoint, compute which side of the other segment it lies // if both endpoints lie on the same side of the other segment, // the segments do not intersect int Pq1 = CGAlgorithms.orientationIndex(p1, p2, q1); int Pq2 = CGAlgorithms.orientationIndex(p1, p2, q2); if ((Pq1 > 0 && Pq2 > 0) || (Pq1 < 0 && Pq2 < 0)) { return NO_INTERSECTION; } int Qp1 = CGAlgorithms.orientationIndex(q1, q2, p1); int Qp2 = CGAlgorithms.orientationIndex(q1, q2, p2); if ((Qp1 > 0 && Qp2 > 0) || (Qp1 < 0 && Qp2 < 0)) { return NO_INTERSECTION; } boolean collinear = Pq1 == 0 && Pq2 == 0 && Qp1 == 0 && Qp2 == 0; if (collinear) { return computeCollinearIntersection(p1, p2, q1, q2); } /** * At this point we know that there is a single intersection point (since the lines are not * collinear). */ /** * Check if the intersection is an endpoint. If it is, copy the endpoint as the intersection * point. Copying the point rather than computing it ensures the point has the exact value, * which is important for robustness. It is sufficient to simply check for an endpoint which is * on the other line, since at this point we know that the inputLines must intersect. */ if (Pq1 == 0 || Pq2 == 0 || Qp1 == 0 || Qp2 == 0) { isProper = false; /** * Check for two equal endpoints. This is done explicitly rather than by the orientation tests * below in order to improve robustness. * * <p>[An example where the orientation tests fail to be consistent is the following (where * the true intersection is at the shared endpoint POINT (19.850257749638203 * 46.29709338043669) * * <p>LINESTRING ( 19.850257749638203 46.29709338043669, 20.31970698357233 46.76654261437082 ) * and LINESTRING ( -48.51001596420236 -22.063180333403878, 19.850257749638203 * 46.29709338043669 ) * * <p>which used to produce the INCORRECT result: (20.31970698357233, 46.76654261437082, NaN) */ if (p1.equals2D(q1) || p1.equals2D(q2)) { intPt[0] = p1; } else if (p2.equals2D(q1) || p2.equals2D(q2)) { intPt[0] = p2; } /** Now check to see if any endpoint lies on the interior of the other segment. */ else if (Pq1 == 0) { intPt[0] = new Coordinate(q1); } else if (Pq2 == 0) { intPt[0] = new Coordinate(q2); } else if (Qp1 == 0) { intPt[0] = new Coordinate(p1); } else if (Qp2 == 0) { intPt[0] = new Coordinate(p2); } } else { isProper = true; intPt[0] = intersection(p1, p2, q1, q2); } return POINT_INTERSECTION; }
/** * Tests whether this ring is a hole. Due to the way the edges in the polyongization graph are * linked, a ring is a hole if it is oriented counter-clockwise. * * @return <code>true</code> if this ring is a hole */ public boolean isHole() { LinearRing ring = getRing(); return CGAlgorithms.isCCW(ring.getCoordinates()); }