/** * Given two edges AB and CD where at least two vertices are identical (i.e. * robustCrossing(a,b,c,d) == 0), this function defines whether the two edges * "cross" in a such a way that point-in-polygon containment tests can be * implemented by counting the number of edge crossings. The basic rule is * that a "crossing" occurs if AB is encountered after CD during a CCW sweep * around the shared vertex starting from a fixed reference point. * * Note that according to this rule, if AB crosses CD then in general CD does * not cross AB. However, this leads to the correct result when counting * polygon edge crossings. For example, suppose that A,B,C are three * consecutive vertices of a CCW polygon. If we now consider the edge * crossings of a segment BP as P sweeps around B, the crossing number changes * parity exactly when BP crosses BA or BC. * * Useful properties of VertexCrossing (VC): * * (1) VC(a,a,c,d) == VC(a,b,c,c) == false (2) VC(a,b,a,b) == VC(a,b,b,a) == * true (3) VC(a,b,c,d) == VC(a,b,d,c) == VC(b,a,c,d) == VC(b,a,d,c) (3) If * exactly one of a,b Equals one of c,d, then exactly one of VC(a,b,c,d) and * VC(c,d,a,b) is true * * It is an error to call this method with 4 distinct vertices. */ public static bool VertexCrossing(S2Point a, S2Point b, S2Point c, S2Point d) { // If A == B or C == D there is no intersection. We need to check this // case first in case 3 or more input points are identical. if (a.Equals(b) || c.Equals(d)) { return(false); } // If any other pair of vertices is equal, there is a crossing if and only // if orderedCCW() indicates that the edge AB is further CCW around the // shared vertex than the edge CD. if (a.Equals(d)) { return(S2.OrderedCcw(S2.Ortho(a), c, b, a)); } if (b.Equals(c)) { return(S2.OrderedCcw(S2.Ortho(b), d, a, b)); } if (a.Equals(c)) { return(S2.OrderedCcw(S2.Ortho(a), d, b, a)); } if (b.Equals(d)) { return(S2.OrderedCcw(S2.Ortho(b), c, a, b)); } // assert (false); return(false); }
private void InitOrigin() { // The bounding box does not need to be correct before calling this // function, but it must at least contain vertex(1) since we need to // do a Contains() test on this point below. Preconditions.CheckState(_bound.Contains(Vertex(1))); // To ensure that every point is contained in exactly one face of a // subdivision of the sphere, all containment tests are done by counting the // edge crossings starting at a fixed point on the sphere (S2::Origin()). // We need to know whether this point is inside or outside of the loop. // We do this by first guessing that it is outside, and then seeing whether // we get the correct containment result for vertex 1. If the result is // incorrect, the origin must be inside the loop. // // A loop with consecutive vertices A,B,C contains vertex B if and only if // the fixed vector R = S2::Ortho(B) is on the left side of the wedge ABC. // The test below is written so that B is inside if C=R but not if A=R. _originInside = false; // Initialize before calling Contains(). var v1Inside = S2.OrderedCcw(S2.Ortho(Vertex(1)), Vertex(0), Vertex(2), Vertex(1)); if (v1Inside != Contains(Vertex(1))) { _originInside = true; } }