Esempio n. 1
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;
   }
 }
Esempio n. 2
0
 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;
 }
Esempio n. 3
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;
  }
Esempio n. 4
0
  /**
   * 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;
  }
Esempio n. 5
0
  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;
  }
Esempio n. 6
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());
 }