Ejemplo n.º 1
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;
 }
Ejemplo n.º 2
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;
   }
 }
 private void tryDist(Coordinate p, Coordinate p0, Coordinate p1) {
   double dist = CGAlgorithms.distancePointLine(p, p0, p1);
   if (dist < minDist) {
     minDist = dist;
     intPt = p;
   }
 }
Ejemplo n.º 4
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;
 }
Ejemplo n.º 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;
  }
Ejemplo n.º 6
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;
  }
Ejemplo n.º 7
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);
 }
Ejemplo n.º 8
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);
 }
Ejemplo n.º 9
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);
 }
Ejemplo n.º 10
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);
 }
Ejemplo n.º 11
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;
  }
Ejemplo n.º 12
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());
 }