예제 #1
0
  /**
   * make sure outer ring is CCW and holes are CW
   *
   * @param p polygon to check
   */
  Polygon makeGoodSHAPEPolygon(Polygon p) {
    LinearRing outer;
    LinearRing[] holes = new LinearRing[p.getNumInteriorRing()];
    Coordinate[] coords;

    coords = p.getExteriorRing().getCoordinates();

    if (cga.isCCW(coords)) {
      outer = reverseRing((LinearRing) p.getExteriorRing());
    } else {
      outer = (LinearRing) p.getExteriorRing();
    }

    for (int t = 0; t < p.getNumInteriorRing(); t++) {
      coords = p.getInteriorRingN(t).getCoordinates();

      if (!(cga.isCCW(coords))) {
        holes[t] = reverseRing((LinearRing) p.getInteriorRingN(t));
      } else {
        holes[t] = (LinearRing) p.getInteriorRingN(t);
      }
    }

    return new Polygon(outer, holes, new PrecisionModel(), 0);
  }
예제 #2
0
  private void validate(final Geometry geom, final List<ValidationResult> validationErrors) {

    if (geom.isEmpty()) {
      return;
    }

    if (geom instanceof GeometryCollection) {
      final GeometryCollection gc = (GeometryCollection) geom;
      for (int numGeom = 0; numGeom < gc.getNumGeometries(); numGeom++) {
        validate(gc.getGeometryN(numGeom), validationErrors);
      }
    }

    final ValidationResult result = new ValidationResult();
    result.setWkt(geom.toText());
    final List<String> messages = new ArrayList<String>();

    if (!geom.isValid()) {
      messages.add("Error en topología básica");
    }

    if (!geom.isSimple()) {
      messages.add("No es una geometría simple");
    }

    if (repeatedPointTester.hasRepeatedPoint(geom)) {
      messages.add("Se encuentran vértices repetidos");
    }

    if (geom instanceof Polygon) {
      final Polygon polygon = (Polygon) geom;
      if (CGAlgorithms.isCCW(polygon.getExteriorRing().getCoordinates())) {
        messages.add("Error en orientación del polígono");
      } else {

        for (int numRing = 0; numRing < polygon.getNumInteriorRing(); numRing++) {
          if (!CGAlgorithms.isCCW(polygon.getInteriorRingN(numRing).getCoordinates())) {
            messages.add("Error en orientación del polígono en anillos interiores");
            break;
          }
        }
      }

      if (!validateMinPolygonArea(geom)) {
        messages.add("Error en validación mínima de area de un polígono");
      }
    }

    if (!validateMinSegmentLength(geom)) {
      messages.add("Error en validación mínima de longitud de segmento");
    }

    if (!messages.isEmpty()) {
      result.setMessages(messages);
      validationErrors.add(result);
    }
  }
예제 #3
0
 /**
  * Determines the orientation of a LineSegment relative to this segment. The concept of
  * orientation is specified as follows: Given two line segments A and L,
  *
  * <ul
  * <li>
  *   A is to the left of a segment L if A lies wholly in the closed half-plane lying to the left
  *   of L
  *   <li>A is to the right of a segment L if A lies wholly in the closed half-plane lying to the
  *       right of L
  *   <li>otherwise, A has indeterminate orientation relative to L. This happens if A is collinear
  *       with L or if A crosses the line determined by L.
  * </ul>
  *
  * @param seg the LineSegment to compare
  * @return 1 if <code>seg</code> is to the left of this segment
  * @return -1 if <code>seg</code> is to the right of this segment
  * @return 0 if <code>seg</code> is collinear to or crosses this segment
  */
 public int orientationIndex(LineSegment seg) {
   int orient0 = CGAlgorithms.orientationIndex(p0, p1, seg.p0);
   int orient1 = CGAlgorithms.orientationIndex(p0, p1, seg.p1);
   // this handles the case where the points are L or collinear
   if (orient0 >= 0 && orient1 >= 0) return Math.max(orient0, orient1);
   // this handles the case where the points are R or collinear
   if (orient0 <= 0 && orient1 <= 0) return Math.max(orient0, orient1);
   // points lie on opposite sides ==> indeterminate orientation
   return 0;
 }
예제 #4
0
 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;
   }
 }
예제 #5
0
  /**
   * 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;
  }
예제 #6
0
  /**
   * Sets the orientation of an array of coordinates.
   *
   * @param coord the coordinates to inspect
   * @param desiredOrientation CGAlgorithms.CLOCKWISE or CGAlgorithms.COUNTERCLOCKWISE
   * @return a new array with entries in reverse order, if the orientation is incorrect; otherwise,
   *     the original array
   */
  public static Coordinate[] ensureOrientation(Coordinate[] coord, int desiredOrientation) {
    if (coord.length == 0) {
      return coord;
    }

    int orientation = cga.isCCW(coord) ? CGAlgorithms.COUNTERCLOCKWISE : CGAlgorithms.CLOCKWISE;

    if (orientation != desiredOrientation) {
      Coordinate[] reverse = (Coordinate[]) coord.clone();
      CoordinateArrays.reverse(reverse);

      return reverse;
    }

    return coord;
  }
예제 #7
0
  private void addBufferCoordinates() {
    if (m_segment0 == null || m_segment1 == null || m_buffer0 == null || m_buffer1 == null) return;

    final int orientation =
        CGAlgorithms.computeOrientation(m_segment0.p0, m_segment0.p1, m_segment1.p1);
    final boolean outsideTurn =
        (orientation == CGAlgorithms.CLOCKWISE && m_side == Position.LEFT)
            || (orientation == CGAlgorithms.COUNTERCLOCKWISE && m_side == Position.RIGHT);

    // REMARK: we add only points at the current buffer vertex (i.e. the common point of the two
    // segments);
    // the very first and very last vertex must be added separately
    // last crd of last segment is added separately

    final boolean addStartPoint = true;

    if (orientation == 0) {
      addCollinear(addStartPoint);
    } else if (outsideTurn) {
      addOutsideTurn(orientation, addStartPoint);
    } else {
      addInsideTurn();
    }
  }
예제 #8
0
  /**
   * Check if it's CW.
   *
   * @param linearRing
   * @return true if the ring has a clock wise orientation
   */
  private boolean isCW(final LinearRing linearRing) {

    Coordinate[] ringCoord = linearRing.getCoordinates();

    return !CGAlgorithms.isCCW(ringCoord);
  }
예제 #9
0
 private static boolean isClockwiseRectangle(Geometry geo) {
   return geo != null && geo.isRectangle() && !CGAlgorithms.isCCW(geo.getCoordinates());
 }
예제 #10
0
 /**
  * Computes the perpendicular distance between the (infinite) line defined by this line segment
  * and a point.
  *
  * @return the perpendicular distance between the defined line and the given point
  */
 public double distancePerpendicular(Coordinate p) {
   return CGAlgorithms.distancePointLinePerpendicular(p, p0, p1);
 }
예제 #11
0
 /**
  * Computes the distance between this line segment and a given point.
  *
  * @return the distance from this segment to the given point
  */
 public double distance(Coordinate p) {
   return CGAlgorithms.distancePointLine(p, p0, p1);
 }
예제 #12
0
 /**
  * Computes the distance between this line segment and another segment.
  *
  * @return the distance to the other segment
  */
 public double distance(LineSegment ls) {
   return CGAlgorithms.distanceLineLine(p0, p1, ls.p0, ls.p1);
 }
예제 #13
0
 /**
  * Determines the orientation index of a {@link Coordinate} relative to this segment. The
  * orientation index is as defined in {@link CGAlgorithms#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 CGAlgorithms#computeOrientation(Coordinate, Coordinate, Coordinate)
  */
 public int orientationIndex(Coordinate p) {
   return CGAlgorithms.orientationIndex(p0, p1, p);
 }
예제 #14
0
 public static boolean edgesIntersect(final Edge e1, final Edge e2) {
   return CGAlgorithms.distanceLineLine(e1.start, e1.end, e2.start, e2.end) <= 0.0;
 }
예제 #15
0
 /**
  * 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());
 }