/** * Ensure Ring of Coordinates are in a counter Orientationwise order. * * <p>If the Coordinate need to be reversed a copy will be returned. * * @param factory Factory to used to reverse CoordinateSequence * @param ring Ring of Coordinates * @return coords in a CCW order */ public static CoordinateSequence counterClockWise( CoordinateSequenceFactory factory, CoordinateSequence ring) { if (Orientation.isCCW(ring.toCoordinateArray())) { return ring; } return Coordinates.reverse(factory, ring); }
/** * Ensure Ring of Coordinates are in a Orientationwise order. * * <p>If the Coordinate need to be reversed a copy will be returned. * * @param factory Factory used to reverse CoordinateSequence * @param ring Ring of Coordinates * @return coords in a CW order */ private static CoordinateSequence clockWise( CoordinateSequenceFactory factory, CoordinateSequence ring) { if (!Orientation.isCCW(ring.toCoordinateArray())) { return ring; } return Coordinates.reverse(factory, ring); }
private boolean isHole(Coordinate[] pts) { return Orientation.isCCW(pts); }
if (Orientation.isCCW(ring.getCoordinates())) { // it is an Interior Hole rings.add(ring); i++;
public static boolean isCCW(Geometry g) { Coordinate[] ptsRing = OrientationFunctions.getRing(g); if (ptsRing == null) return false; return Orientation.isCCW(ptsRing); }
/** * Compute a LinearRing from the point list previously collected. * Test if the ring is a hole (i.e. if it is CCW) and set the hole flag * accordingly. */ public void computeRing() { if (ring != null) return; // don't compute more than once Coordinate[] coord = new Coordinate[pts.size()]; for (int i = 0; i < pts.size(); i++) { coord[i] = (Coordinate) pts.get(i); } ring = geometryFactory.createLinearRing(coord); isHole = Orientation.isCCW(ring.getCoordinates()); //Debug.println( (isHole ? "hole - " : "shell - ") + WKTWriter.toLineString(new CoordinateArraySequence(ring.getCoordinates()))); } abstract public DirectedEdge getNext(DirectedEdge de);
private void addHole(Coordinate[] pts) { boolean isPositiveArea = Orientation.isCCW(pts); for (int i = 0; i < pts.length - 1; i++) { addTriangle(areaBasePt, pts[i], pts[i+1], isPositiveArea); } addLineSegments(pts); } private void addTriangle(Coordinate p0, Coordinate p1, Coordinate p2, boolean isPositiveArea)
/** * Computes whether this ring is a hole. * Due to the way the edges in the polygonization graph are linked, * a ring is a hole if it is oriented counter-clockwise. */ public void computeHole() { LinearRing ring = getRing(); isHole = Orientation.isCCW(ring.getCoordinates()); }
private void addShell(Coordinate[] pts) { if (pts.length > 0) setAreaBasePoint(pts[0]); boolean isPositiveArea = ! Orientation.isCCW(pts); for (int i = 0; i < pts.length - 1; i++) { addTriangle(areaBasePt, pts[i], pts[i+1], isPositiveArea); } addLineSegments(pts); }
/** * Adds an offset curve for a polygon ring. * The side and left and right topological location arguments * assume that the ring is oriented CW. * If the ring is in the opposite orientation, * the left and right locations must be interchanged and the side flipped. * * @param coord the coordinates of the ring (must not contain repeated points) * @param offsetDistance the distance at which to create the buffer * @param side the side of the ring on which to construct the buffer line * @param cwLeftLoc the location on the L side of the ring (if it is CW) * @param cwRightLoc the location on the R side of the ring (if it is CW) */ private void addPolygonRing(Coordinate[] coord, double offsetDistance, int side, int cwLeftLoc, int cwRightLoc) { // don't bother adding ring if it is "flat" and will disappear in the output if (offsetDistance == 0.0 && coord.length < LinearRing.MINIMUM_VALID_SIZE) return; int leftLoc = cwLeftLoc; int rightLoc = cwRightLoc; if (coord.length >= LinearRing.MINIMUM_VALID_SIZE && Orientation.isCCW(coord)) { leftLoc = cwRightLoc; rightLoc = cwLeftLoc; side = Position.opposite(side); } Coordinate[] curve = curveBuilder.getRingCurve(coord, side, offsetDistance); addCurve(curve, leftLoc, rightLoc); }
List<Integer> commands(Polygon polygon) { List<Integer> commands = new ArrayList<Integer>(); // According to the vector tile specification, the exterior ring of a polygon // must be in clockwise order, while the interior ring in counter-clockwise order. // In the tile coordinate system, Y axis is positive down. // // However, in geographic coordinate system, Y axis is positive up. // Therefore, we must reverse the coordinates. // So, the code below will make sure that exterior ring is in counter-clockwise order // and interior ring in clockwise order. LineString exteriorRing = polygon.getExteriorRing(); if (!Orientation.isCCW(exteriorRing.getCoordinates())) { exteriorRing = (LineString) exteriorRing.reverse(); } commands.addAll(commands(exteriorRing.getCoordinates(), true)); for (int i = 0; i < polygon.getNumInteriorRing(); i++) { LineString interiorRing = polygon.getInteriorRingN(i); if (Orientation.isCCW(interiorRing.getCoordinates())) { interiorRing = (LineString) interiorRing.reverse(); } commands.addAll(commands(interiorRing.getCoordinates(), true)); } return commands; }
public void testCCW() throws Exception { Coordinate[] pts = getCoordinates("POLYGON ((60 180, 140 240, 140 240, 140 240, 200 180, 120 120, 60 180))"); assertEquals(false, Orientation.isCCW(pts)); CoordinateSequence seq = getCoordinateSequence("POLYGON ((60 180, 140 240, 140 240, 140 240, 200 180, 120 120, 60 180))"); assertEquals(false, Orientation.isCCW(seq)); Coordinate[] pts2 = getCoordinates("POLYGON ((60 180, 140 120, 100 180, 140 240, 60 180))"); assertEquals(true, Orientation.isCCW(pts2)); CoordinateSequence seq2 = getCoordinateSequence("POLYGON ((60 180, 140 120, 100 180, 140 240, 60 180))"); assertEquals(true, Orientation.isCCW(seq2)); // same pts list with duplicate top point - check that isCCW still works Coordinate[] pts2x = getCoordinates( "POLYGON ((60 180, 140 120, 100 180, 140 240, 140 240, 60 180))"); assertEquals(true, Orientation.isCCW(pts2x) ); CoordinateSequence seq2x = getCoordinateSequence("POLYGON ((60 180, 140 120, 100 180, 140 240, 140 240, 60 180))"); assertEquals(true, Orientation.isCCW(seq2x) ); }
private String componentType(GeometryLocation loc) { String compType = ""; if (loc.getComponent() instanceof LinearRing) { boolean isCCW = Orientation.isCCW(loc.getComponent().getCoordinates()); compType = "Ring" + (isCCW ? "-CCW" : "-CW ") + " "; } else if (loc.getComponent() instanceof LineString) { compType = "Line "; } else if (loc.getComponent() instanceof Point) { compType = "Point "; } return compType; }
private void normalize(LinearRing ring, boolean clockwise) { if (ring.isEmpty()) { return; } CoordinateSequence seq = ring.getCoordinateSequence(); int minCoordinateIndex = CoordinateSequences.minCoordinateIndex(seq, 0, seq.size()-2); CoordinateSequences.scroll(seq, minCoordinateIndex, true); if (Orientation.isCCW(seq) == clockwise) CoordinateSequences.reverse(seq); }
private void addResultVertices(Geometry geom0, Geometry geom1) { /** * Compute rays originating at vertices inside the resultant * (i.e. A vertices inside B, and B vertices inside A) */ IndexedPointInAreaLocator locator = new IndexedPointInAreaLocator(geom1); CoordinateSequence seq = getVertices(geom0); boolean isCW = ! Orientation.isCCW(seq); for (int i = 0; i < seq.size()-1; i++) { Coordinate vPrev = i == 0 ? seq.getCoordinate(seq.size()-2) : seq.getCoordinate(i-1); Coordinate v = seq.getCoordinate(i); Coordinate vNext = seq.getCoordinate(i+1); if (Location.INTERIOR == locator.locate(v)) { area += EdgeRay.areaTerm(v, vPrev, ! isCW); area += EdgeRay.areaTerm(v, vNext, isCW); } } }
if (Orientation.isCCW(triPts)) { orientation = -orientation;
public double getArea() { Polygon poly = (Polygon) geom; CoordinateSequence seq = poly.getExteriorRing().getCoordinateSequence(); boolean isCW = ! Orientation.isCCW(seq); // TODO: for now assume poly is CW // scan every segment double area = 0; for (int i = 1; i < seq.size(); i++) { int i0 = i - 1; int i1 = i; /* area += EdgeRay.areaTermBoth(seq.getX(i0), seq.getY(i0), seq.getX(i1), seq.getY(i1)); */ area += EdgeRay.areaTerm(seq.getX(i0), seq.getY(i0), seq.getX(i1), seq.getY(i1), isCW); area += EdgeRay.areaTerm(seq.getX(i1), seq.getY(i1), seq.getX(i0), seq.getY(i0), ! isCW); } return area; } }
@Test public void testCCW(){ //empty user data test final LinearRing ring = GF.createLinearRing(new Coordinate[]{ new Coordinate(50, 27), new Coordinate(25, 15), new Coordinate(10, 10), new Coordinate(28, 30), new Coordinate(50, 27) }); final Polygon poly = GF.createPolygon(ring, null); final Geometry returnedGeom = JTS.ensureCounterClockWise(poly); assertTrue(Orientation.isCCW(returnedGeom.getCoordinates())); }
@Test public void testCW(){ //empty user data test final LinearRing ring = GF.createLinearRing(new Coordinate[]{ new Coordinate(50, 27), new Coordinate(28, 30), new Coordinate(10, 10), new Coordinate(25, 15), new Coordinate(50, 27) }); final Polygon poly = GF.createPolygon(ring, null); final Geometry returnedGeom = JTS.ensureClockWise(poly); assertFalse(Orientation.isCCW(returnedGeom.getCoordinates())); }