public void testContains()
        {
            assertTrue(candyCane.Contains(S2LatLng.FromDegrees(5, 71).ToPoint()));
            for (var i = 0; i < 4; ++i)
            {
                assertTrue(northHemi.Contains(new S2Point(0, 0, 1)));
                assertTrue(!northHemi.Contains(new S2Point(0, 0, -1)));
                assertTrue(!southHemi.Contains(new S2Point(0, 0, 1)));
                assertTrue(southHemi.Contains(new S2Point(0, 0, -1)));
                assertTrue(!westHemi.Contains(new S2Point(0, 1, 0)));
                assertTrue(westHemi.Contains(new S2Point(0, -1, 0)));
                assertTrue(eastHemi.Contains(new S2Point(0, 1, 0)));
                assertTrue(!eastHemi.Contains(new S2Point(0, -1, 0)));
                northHemi = rotate(northHemi);
                southHemi = rotate(southHemi);
                eastHemi  = rotate(eastHemi);
                westHemi  = rotate(westHemi);
            }

            // This code checks each cell vertex is contained by exactly one of
            // the adjacent cells.
            for (var level = 0; level < 3; ++level)
            {
                var            loops        = new List <S2Loop>();
                var            loopVertices = new List <S2Point>();
                ISet <S2Point> points       = new HashSet <S2Point>();
                for (var id = S2CellId.Begin(level); !id.Equals(S2CellId.End(level)); id = id.Next)
                {
                    var cell = new S2Cell(id);
                    points.Add(cell.Center);
                    for (var k = 0; k < 4; ++k)
                    {
                        loopVertices.Add(cell.GetVertex(k));
                        points.Add(cell.GetVertex(k));
                    }
                    loops.Add(new S2Loop(loopVertices));
                    loopVertices.Clear();
                }
                foreach (var point in points)
                {
                    var count = 0;
                    for (var j = 0; j < loops.Count; ++j)
                    {
                        if (loops[j].Contains(point))
                        {
                            ++count;
                        }
                    }
                    assertEquals(count, 1);
                }
            }
        }
 private void assertRelation(
     S2Loop a, S2Loop b, int containsOrCrosses, bool intersects, bool nestable)
 {
     assertEquals(a.Contains(b), containsOrCrosses == 1);
     assertEquals(a.Intersects(b), intersects);
     if (nestable)
     {
         assertEquals(a.ContainsNested(b), a.Contains(b));
     }
     if (containsOrCrosses >= -1)
     {
         assertEquals(a.ContainsOrCrosses(b), containsOrCrosses);
     }
 }
    private static void CompareS2LoopToShape(S2Loop loop, S2Shape shape)
    {
        MutableS2ShapeIndex index = new();

        index.Add(shape);
        S2Cap cap   = loop.GetCapBound();
        var   query = index.MakeS2ContainsPointQuery();

        for (int iter = 0; iter < 100; ++iter)
        {
            S2Point point = S2Testing.SamplePoint(cap);
            Assert.Equal(loop.Contains(point),
                         query.ShapeContains(index.Shape(0), point));
        }
    }
 private void dumpCrossings(S2Loop loop)
 {
     Console.WriteLine("Ortho(v1): " + S2.Ortho(loop.Vertex(1)));
     Console.WriteLine("Contains(kOrigin): {0}\n", loop.Contains(S2.Origin));
     for (var i = 1; i <= loop.NumVertices; ++i)
     {
         var a = S2.Ortho(loop.Vertex(i));
         var b = loop.Vertex(i - 1);
         var c = loop.Vertex(i + 1);
         var o = loop.Vertex(i);
         Console.WriteLine("Vertex {0}: [%.17g, %.17g, %.17g], "
                           + "%d%dR=%d, %d%d%d=%d, R%d%d=%d, inside: %b\n",
                           i,
                           loop.Vertex(i).X,
                           loop.Vertex(i).Y,
                           loop.Vertex(i).Z,
                           i - 1,
                           i,
                           S2.RobustCcw(b, o, a),
                           i + 1,
                           i,
                           i - 1,
                           S2.RobustCcw(c, o, b),
                           i,
                           i + 1,
                           S2.RobustCcw(a, o, c),
                           S2.OrderedCcw(a, b, c, o));
     }
     for (var i = 0; i < loop.NumVertices + 2; ++i)
     {
         var orig = S2.Origin;
         S2Point dest;
         if (i < loop.NumVertices)
         {
             dest = loop.Vertex(i);
             Console.WriteLine("Origin->{0} crosses:", i);
         }
         else
         {
             dest = new S2Point(0, 0, 1);
             if (i == loop.NumVertices + 1)
             {
                 orig = loop.Vertex(1);
             }
             Console.WriteLine("Case {0}:", i);
         }
         for (var j = 0; j < loop.NumVertices; ++j)
         {
             Console.WriteLine(
                 " " + S2EdgeUtil.EdgeOrVertexCrossing(orig, dest, loop.Vertex(j), loop.Vertex(j + 1)));
         }
         Console.WriteLine();
     }
     for (var i = 0; i <= 2; i += 2)
     {
         Console.WriteLine("Origin->v1 crossing v{0}->v1: ", i);
         var a = S2.Ortho(loop.Vertex(1));
         var b = loop.Vertex(i);
         var c = S2.Origin;
         var o = loop.Vertex(1);
         Console.WriteLine("{0}1R={1}, M1{2}={3}, R1M={4}, crosses: {5}\n",
                           i,
                           S2.RobustCcw(b, o, a),
                           i,
                           S2.RobustCcw(c, o, b),
                           S2.RobustCcw(a, o, c),
                           S2EdgeUtil.EdgeOrVertexCrossing(c, o, b, a));
     }
 }
 private void assertRelation(
     S2Loop a, S2Loop b, int containsOrCrosses, bool intersects, bool nestable)
 {
     assertEquals(a.Contains(b), containsOrCrosses == 1);
     assertEquals(a.Intersects(b), intersects);
     if (nestable)
     {
         assertEquals(a.ContainsNested(b), a.Contains(b));
     }
     if (containsOrCrosses >= -1)
     {
         assertEquals(a.ContainsOrCrosses(b), containsOrCrosses);
     }
 }
 private void dumpCrossings(S2Loop loop)
 {
     Console.WriteLine("Ortho(v1): " + S2.Ortho(loop.Vertex(1)));
     Console.WriteLine("Contains(kOrigin): {0}\n", loop.Contains(S2.Origin));
     for (var i = 1; i <= loop.NumVertices; ++i)
     {
         var a = S2.Ortho(loop.Vertex(i));
         var b = loop.Vertex(i - 1);
         var c = loop.Vertex(i + 1);
         var o = loop.Vertex(i);
         Console.WriteLine("Vertex {0}: [%.17g, %.17g, %.17g], "
                           + "%d%dR=%d, %d%d%d=%d, R%d%d=%d, inside: %b\n",
                           i,
                           loop.Vertex(i).X,
                           loop.Vertex(i).Y,
                           loop.Vertex(i).Z,
                           i - 1,
                           i,
                           S2.RobustCcw(b, o, a),
                           i + 1,
                           i,
                           i - 1,
                           S2.RobustCcw(c, o, b),
                           i,
                           i + 1,
                           S2.RobustCcw(a, o, c),
                           S2.OrderedCcw(a, b, c, o));
     }
     for (var i = 0; i < loop.NumVertices + 2; ++i)
     {
         var     orig = S2.Origin;
         S2Point dest;
         if (i < loop.NumVertices)
         {
             dest = loop.Vertex(i);
             Console.WriteLine("Origin->{0} crosses:", i);
         }
         else
         {
             dest = new S2Point(0, 0, 1);
             if (i == loop.NumVertices + 1)
             {
                 orig = loop.Vertex(1);
             }
             Console.WriteLine("Case {0}:", i);
         }
         for (var j = 0; j < loop.NumVertices; ++j)
         {
             Console.WriteLine(
                 " " + S2EdgeUtil.EdgeOrVertexCrossing(orig, dest, loop.Vertex(j), loop.Vertex(j + 1)));
         }
         Console.WriteLine();
     }
     for (var i = 0; i <= 2; i += 2)
     {
         Console.WriteLine("Origin->v1 crossing v{0}->v1: ", i);
         var a = S2.Ortho(loop.Vertex(1));
         var b = loop.Vertex(i);
         var c = S2.Origin;
         var o = loop.Vertex(1);
         Console.WriteLine("{0}1R={1}, M1{2}={3}, R1M={4}, crosses: {5}\n",
                           i,
                           S2.RobustCcw(b, o, a),
                           i,
                           S2.RobustCcw(c, o, b),
                           S2.RobustCcw(a, o, c),
                           S2EdgeUtil.EdgeOrVertexCrossing(c, o, b, a));
     }
 }