public boolean intersects(S2Loop b) {
    // a->Intersects(b) if and only if !a->Complement()->Contains(b).
    // This code is similar to Contains(), but is optimized for the case
    // where both loops enclose less than half of the sphere.

    if (!bound.intersects(b.getRectBound())) {
      return false;
    }

    // Normalize the arguments so that B has a smaller longitude span than A.
    // This makes intersection tests much more efficient in the case where
    // longitude pruning is used (see CheckEdgeCrossings).
    if (b.getRectBound().lng().getLength() > bound.lng().getLength()) {
      return b.intersects(this);
    }

    // Unless there are shared vertices, we need to check whether A contains a
    // vertex of B. Since shared vertices are rare, it is more efficient to do
    // this test up front as a quick acceptance test.
    if (contains(b.vertex(0)) && findVertex(b.vertex(0)) < 0) {
      return true;
    }

    // Now check whether there are any edge crossings, and also check the loop
    // relationship at any shared vertices.
    if (checkEdgeCrossings(b, new S2EdgeUtil.WedgeIntersects()) < 0) {
      return true;
    }

    // We know that A does not contain a vertex of B, and that there are no edge
    // crossings. Therefore the only way that A can intersect B is if B
    // entirely contains A. We can check this by testing whether B contains an
    // arbitrary non-shared vertex of A. Note that this check is cheap because
    // of the bounding box precondition and the fact that we normalized the
    // arguments so that A's longitude span is at least as long as B's.
    if (b.getRectBound().contains(bound)) {
      if (b.contains(vertex(0)) && b.findVertex(vertex(0)) < 0) {
        return true;
      }
    }

    return false;
  }