// Non-adjacent edges are not allowed to intersect.
boolean crosses = false;
DataEdgeIterator it = getEdgeIterator(numVertices);
for (int a1 = 0; a1 < numVertices; a1++) {
int a2 = (a1 + 1) % numVertices;
EdgeCrosser crosser = new EdgeCrosser(vertex(a1), vertex(a2), vertex(0));
int previousIndex = -2;
for (it.getCandidates(vertex(a1), vertex(a2)); it.hasNext(); it.next()) {
int b1 = it.index();
int b2 = (b1 + 1) % numVertices;
// If either 'a' index equals either 'b' index, then these two edges
// share a vertex. If a1==b1 then it must be the case that a2==b2, e.g.
// the two edges are the same. In that case, we skip the test, since we
// don't want to test an edge against itself. If a1==b2 or b1==a2 then
// we have one edge ending at the start of the other, or in other words,
// the edges share a vertex -- and in S2 space, where edges are always
// great circle segments on a sphere, edges can only intersect at most
// once, so we don't need to do further checks in that case either.
if (a1 != b2 && a2 != b1 && a1 != b1) {
// WORKAROUND(shakusa, ericv): S2.robustCCW() currently
// requires arbitrary-precision arithmetic to be truly robust. That
// means it can give the wrong answers in cases where we are trying
// to determine edge intersections. The workaround is to ignore
// intersections between edge pairs where all four points are
// nearly colinear.
double abc = S2.angle(vertex(a1), vertex(a2), vertex(b1));
boolean abcNearlyLinear = S2.approxEquals(abc, 0D, MAX_INTERSECTION_ERROR) ||
S2.approxEquals(abc, S2.M_PI, MAX_INTERSECTION_ERROR);
double abd = S2.angle(vertex(a1), vertex(a2), vertex(b2));
boolean abdNearlyLinear = S2.approxEquals(abd, 0D, MAX_INTERSECTION_ERROR) ||
S2.approxEquals(abd, S2.M_PI, MAX_INTERSECTION_ERROR);
if (abcNearlyLinear && abdNearlyLinear) {
continue;
}
if (previousIndex != b1) {
crosser.restartAt(vertex(b1));
}
// Beware, this may return the loop is valid if there is a
// "vertex crossing".
// TODO(user): Fix that.
crosses = crosser.robustCrossing(vertex(b2)) > 0;
previousIndex = b2;
if (crosses ) {
log.info("Edges " + a1 + " and " + b1 + " cross");
log.info(String.format("Edge locations in degrees: " + "%s-%s and %s-%s",
new S2LatLng(vertex(a1)).toStringDegrees(),