Example #1
0
        /**
         * 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);
        }
Example #2
0
        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;
            }
        }