intersects method

bool intersects(
  1. Coordinate p0,
  2. Coordinate p1
)

Tests whether the query rectangle intersects a given line segment.

@param p0 the first endpoint of the segment @param p1 the second endpoint of the segment @return true if the rectangle intersects the segment

Implementation

bool intersects(Coordinate p0, Coordinate p1) {
  // TODO: confirm that checking envelopes first is faster

  /**
   * If the segment envelope is disjoint from the
   * rectangle envelope, there is no intersection
   */
  Envelope segEnv = new Envelope.fromCoordinates(p0, p1);
  if (!rectEnv.intersectsEnvelope(segEnv)) return false;

  /**
   * If either segment endpoint lies in the rectangle,
   * there is an intersection.
   */
  if (rectEnv.intersectsCoordinate(p0)) return true;
  if (rectEnv.intersectsCoordinate(p1)) return true;

  /**
   * Normalize segment.
   * This makes p0 less than p1,
   * so that the segment runs to the right,
   * or vertically upwards.
   */
  if (p0.compareTo(p1) > 0) {
    Coordinate tmp = p0;
    p0 = p1;
    p1 = tmp;
  }
  /**
   * Compute angle of segment.
   * Since the segment is normalized to run left to right,
   * it is sufficient to simply test the Y ordinate.
   * "Upwards" means relative to the left end of the segment.
   */
  bool isSegUpwards = false;
  if (p1.y > p0.y) isSegUpwards = true;

  /**
   * Since we now know that neither segment endpoint
   * lies in the rectangle, there are two possible
   * situations:
   * 1) the segment is disjoint to the rectangle
   * 2) the segment crosses the rectangle completely.
   *
   * In the case of a crossing, the segment must intersect
   * a diagonal of the rectangle.
   *
   * To distinguish these two cases, it is sufficient
   * to test intersection with
   * a single diagonal of the rectangle,
   * namely the one with slope "opposite" to the slope
   * of the segment.
   * (Note that if the segment is axis-parallel,
   * it must intersect both diagonals, so this is
   * still sufficient.)
   */
  if (isSegUpwards) {
    li.computeIntersection(p0, p1, diagDown0, diagDown1);
  } else {
    li.computeIntersection(p0, p1, diagUp0, diagUp1);
  }
  if (li.hasIntersection()) return true;
  return false;
}