private boolean isConcave(Coordinate p0, Coordinate p1, Coordinate p2) { int orientation = Orientation.index(p0, p1, p2); boolean isConcave = (orientation == angleOrientation); return isConcave; } }
/** * Determines the orientation index of a {@link Coordinate} relative to this segment. * The orientation index is as defined in {@link Orientation#computeOrientation}. * * @param p the coordinate to compare * * @return 1 (LEFT) if <code>p</code> is to the left of this segment * @return -1 (RIGHT) if <code>p</code> is to the right of this segment * @return 0 (COLLINEAR) if <code>p</code> is collinear with this segment * * @see Orientation#computeOrientation(Coordinate, Coordinate, Coordinate) */ public int orientationIndex(Coordinate p) { return Orientation.index(p0, p1, p); }
/** * Returns an array of pts such that p0 - p[0] - [p1] is CW. * * @param p0 * @param p1 * @param p2 * @return */ private static Coordinate[] orientCorner(Coordinate p0, Coordinate p1, Coordinate p2) { Coordinate[] orient; // TODO: not sure if determining orientation is necessary? if (Orientation.CLOCKWISE == Orientation.index(p0, p1, p2)) { orient = new Coordinate[] {p1, p2 }; } else { orient = new Coordinate[] { p2, p1 }; } return orient; }
/** * * @param pt * @param cornerBase the two vertices defining the * @param corner the two vertices defining the arms of the corner, oriented CW * @return the quadrant the pt lies in */ private static int quadrant(Coordinate pt, Coordinate cornerBase, Coordinate[] corner) { if (Orientation.index(cornerBase, corner[0], pt) == Orientation.CLOCKWISE) { if (Orientation.index(cornerBase, corner[1], pt) == Orientation.COUNTERCLOCKWISE) { return 0; } else return 3; } else { if (Orientation.index(cornerBase, corner[1], pt) == Orientation.COUNTERCLOCKWISE) { return 1; } else return 2; } }
/** * Implements the total order relation: * <p> * a has a greater angle with the positive x-axis than b * <p> * Using the obvious algorithm of simply computing the angle is not robust, * since the angle calculation is obviously susceptible to roundoff. * A robust algorithm is: * - first compare the quadrant. If the quadrants * are different, it it trivial to determine which vector is "greater". * - if the vectors lie in the same quadrant, the computeOrientation function * can be used to decide the relative orientation of the vectors. */ public int compareDirection(EdgeEnd e) { if (dx == e.dx && dy == e.dy) return 0; // if the rays are in different quadrants, determining the ordering is trivial if (quadrant > e.quadrant) return 1; if (quadrant < e.quadrant) return -1; // vectors are in the same quadrant - check relative orientation of direction vectors // this is > e if it is CCW of e return Orientation.index(e.p0, e.p1, p1); }
/** * Returns 1 if this DirectedEdge has a greater angle with the * positive x-axis than b", 0 if the DirectedEdges are collinear, and -1 otherwise. * <p> * Using the obvious algorithm of simply computing the angle is not robust, * since the angle calculation is susceptible to roundoff. A robust algorithm * is: * <ul> * <li>first compare the quadrants. If the quadrants are different, it it * trivial to determine which vector is "greater". * <li>if the vectors lie in the same quadrant, the robust * {@link Orientation#computeOrientation(Coordinate, Coordinate, Coordinate)} * function can be used to decide the relative orientation of the vectors. * </ul> */ public int compareDirection(DirectedEdge e) { // if the rays are in different quadrants, determining the ordering is trivial if (quadrant > e.quadrant) return 1; if (quadrant < e.quadrant) return -1; // vectors are in the same quadrant - check relative orientation of direction vectors // this is > e if it is CCW of e return Orientation.index(e.p0, e.p1, p1); }
/** *@return whether the three coordinates are collinear and c2 lies between * c1 and c3 inclusive */ private boolean isBetween(Coordinate c1, Coordinate c2, Coordinate c3) { if (Orientation.index(c1, c2, c3) != 0) { return false; } if (c1.x != c3.x) { if (c1.x <= c2.x && c2.x <= c3.x) { return true; } if (c3.x <= c2.x && c2.x <= c1.x) { return true; } } if (c1.y != c3.y) { if (c1.y <= c2.y && c2.y <= c3.y) { return true; } if (c3.y <= c2.y && c2.y <= c1.y) { return true; } } return false; }
private static double distanceToSeg(Coordinate p, Coordinate p0, Coordinate p1) { distSeg.p0 = p0; distSeg.p1 = p1; double segDist = distSeg.distance(p); // robust calculation of zero distance if (Orientation.index(p0, p1, p) == Orientation.COLLINEAR) segDist = 0.0; return segDist; } }
private boolean isShallowConcavity(Coordinate p0, Coordinate p1, Coordinate p2, double distanceTol) { int orientation = Orientation.index(p0, p1, p2); boolean isAngleToSimplify = (orientation == angleOrientation); if (! isAngleToSimplify) return false; double dist = Distance.pointToSegment(p1, p0, p2); return dist < distanceTol; }
private static boolean isPointNearButNotOnSeg(Coordinate p, Coordinate p0, Coordinate p1, double distTol) { // don't rely on segment distance algorithm to correctly compute zero distance // on segment if (Orientation.index(p0, p1, p) == Orientation.COLLINEAR) return false; // compute actual distance distSeg.p0 = p0; distSeg.p1 = p1; double segDist = distSeg.distance(p); if (segDist > distTol) return false; return true; }
/** * Tests whether the orientations around a triangle of points * are all equal (as is expected if the orientation predicate is correct) * * @param pts an array of three points * @return true if all the orientations around the triangle are equal */ public static boolean isAllOrientationsEqual(Coordinate[] pts) { int[] orient = new int[3]; orient[0] = Orientation.index(pts[0], pts[1], pts[2]); orient[1] = Orientation.index(pts[1], pts[2], pts[0]); orient[2] = Orientation.index(pts[2], pts[0], pts[1]); return orient[0] == orient[1] && orient[0] == orient[2]; }
/** * Uses the Graham Scan algorithm to compute the convex hull vertices. * * @param c a list of points, with at least 3 entries * @return a Stack containing the ordered points of the convex hull ring */ private Stack grahamScan(Coordinate[] c) { Coordinate p; Stack ps = new Stack(); ps.push(c[0]); ps.push(c[1]); ps.push(c[2]); for (int i = 3; i < c.length; i++) { p = (Coordinate) ps.pop(); // check for empty stack to guard against robustness problems while ( ! ps.empty() && Orientation.index((Coordinate) ps.peek(), p, c[i]) > 0) { p = (Coordinate) ps.pop(); } ps.push(p); ps.push(c[i]); } ps.push(c[0]); return ps; }
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 ((Orientation.index(p1, p2, p) == 0) && (Orientation.index(p2, p1, p) == 0)) { isProper = true; if (p.equals(p1) || p.equals(p2)) { isProper = false; } result = POINT_INTERSECTION; return; } } result = NO_INTERSECTION; }
public static int orientationIndex(Geometry segment, Geometry ptGeom) { if (segment.getNumPoints() != 2 || ptGeom.getNumPoints() != 1) { throw new IllegalArgumentException("A must have two points and B must have one"); } Coordinate[] segPt = segment.getCoordinates(); Coordinate p = ptGeom.getCoordinate(); int index = Orientation.index(segPt[0], segPt[1], p); return index; }
/** * The coordinate pairs match if they define line segments lying in the same direction. * E.g. the segments are parallel and in the same quadrant * (as opposed to parallel and opposite!). */ private boolean matchInSameDirection(Coordinate p0, Coordinate p1, Coordinate ep0, Coordinate ep1) { if (! p0.equals(ep0)) return false; if (Orientation.index(p0, p1, ep1) == Orientation.COLLINEAR && Quadrant.quadrant(p0, p1) == Quadrant.quadrant(ep0, ep1) ) return true; return false; }
public void testOrientationIndexRobust() throws Exception { Coordinate p0 = new Coordinate(219.3649559090992, 140.84159161824724); Coordinate p1 = new Coordinate(168.9018919682399, -5.713787599646864); Coordinate p = new Coordinate(186.80814046338352, 46.28973405831556); int orient = Orientation.index(p0, p1, p); int orientInv = Orientation.index(p1, p0, p); assert(orient != orientInv); } /**
public void testIsCCW() { assertEquals(1, Orientation.index(new Coordinate(-123456789, -40), new Coordinate(0, 0), new Coordinate(381039468754763d, 123456789))); }
public void testIsCCW2() { assertEquals(0, Orientation.index(new Coordinate(10, 10), new Coordinate(20, 20), new Coordinate(0, 0))); }
public void testA() { Coordinate p1 = new Coordinate(-123456789, -40); Coordinate p2 = new Coordinate(381039468754763d, 123456789); Coordinate q = new Coordinate(0, 0); LineString l = new GeometryFactory().createLineString(new Coordinate[] {p1, p2}); Point p = new GeometryFactory().createPoint(q); assertEquals(false, l.intersects(p)); assertEquals(false, PointLocation.isOnLine(q, new Coordinate[] {p1, p2})); assertEquals(-1, Orientation.index(p1, p2, q)); }