/** * This function handles the "slow path" of robustCrossing(). */ private int RobustCrossingInternal(S2Point d) { // ACB and BDA have the appropriate orientations, so now we check the // triangles CBD and DAC. var cCrossD = S2Point.CrossProd(c, d); var cbd = -S2.RobustCcw(c, d, b, cCrossD); if (cbd != acb) { return(-1); } var dac = S2.RobustCcw(c, d, a, cCrossD); return((dac == acb) ? 1 : -1); }
/** * Like SimpleCrossing, except that points that lie exactly on a line are * arbitrarily classified as being on one side or the other (according to the * rules of S2.robustCCW). It returns +1 if there is a crossing, -1 if there * is no crossing, and 0 if any two vertices from different edges are the * same. Returns 0 or -1 if either edge is degenerate. Properties of * robustCrossing: * * (1) robustCrossing(b,a,c,d) == robustCrossing(a,b,c,d) (2) * robustCrossing(c,d,a,b) == robustCrossing(a,b,c,d) (3) * robustCrossing(a,b,c,d) == 0 if a==c, a==d, b==c, b==d (3) * robustCrossing(a,b,c,d) <= 0 if a==b or c==d * * Note that if you want to check an edge against a *chain* of other edges, * it is much more efficient to use an EdgeCrosser (above). */ public static int RobustCrossing(S2Point a, S2Point b, S2Point c, S2Point d) { // For there to be a crossing, the triangles ACB, CBD, BDA, DAC must // all have the same orientation (clockwise or counterclockwise). // // First we compute the orientation of ACB and BDA. We permute the // arguments to robustCCW so that we can reuse the cross-product of A and B. // Recall that when the arguments to robustCCW are permuted, the sign of the // result changes according to the sign of the permutation. Thus ACB and // ABC are oppositely oriented, while BDA and ABD are the same. var aCrossB = S2Point.CrossProd(a, b); var acb = -S2.RobustCcw(a, b, c, aCrossB); var bda = S2.RobustCcw(a, b, d, aCrossB); // If any two vertices are the same, the result is degenerate. if ((bda & acb) == 0) { return(0); } // If ABC and BDA have opposite orientations (the most common case), // there is no crossing. if (bda != acb) { return(-1); } // Otherwise we compute the orientations of CBD and DAC, and check whether // their orientations are compatible with the other two triangles. var cCrossD = S2Point.CrossProd(c, d); var cbd = -S2.RobustCcw(c, d, b, cCrossD); if (cbd != acb) { return(-1); } var dac = S2.RobustCcw(c, d, a, cCrossD); return((dac == acb) ? 1 : -1); }
/** * This method is equivalent to calling the S2EdgeUtil.robustCrossing() * function (defined below) on the edges AB and CD. It returns +1 if there * is a crossing, -1 if there is no crossing, and 0 if two points from * different edges are the same. Returns 0 or -1 if either edge is * degenerate. As a side effect, it saves vertex D to be used as the next * vertex C. */ public int RobustCrossing(S2Point d) { // For there to be an edge crossing, the triangles ACB, CBD, BDA, DAC must // all be oriented the same way (CW or CCW). We keep the orientation // of ACB as part of our state. When each new point D arrives, we // compute the orientation of BDA and check whether it matches ACB. // This checks whether the points C and D are on opposite sides of the // great circle through AB. // Recall that robustCCW is invariant with respect to rotating its // arguments, i.e. ABC has the same orientation as BDA. var bda = S2.RobustCcw(a, b, d, aCrossB); int result; if (bda == -acb && bda != 0) { // Most common case -- triangles have opposite orientations. result = -1; } else if ((bda & acb) == 0) { // At least one value is zero -- two vertices are identical. result = 0; } else { // assert (bda == acb && bda != 0); result = RobustCrossingInternal(d); // Slow path. } // Now save the current vertex D as the next vertex C, and also save the // orientation of the new triangle ACB (which is opposite to the current // triangle BDA). c = d; acb = -bda; return(result); }
/** * Call this function when your chain 'jumps' to a new place. */ public void RestartAt(S2Point c) { this.c = c; acb = -S2.RobustCcw(a, b, c, aCrossB); }