コード例 #1
0
        private bool loopsEqual(S2Loop a, S2Loop b, double maxError)
        {
            // Return true if two loops have the same cyclic vertex sequence.

            if (a.NumVertices != b.NumVertices)
            {
                return(false);
            }
            for (var offset = 0; offset < a.NumVertices; ++offset)
            {
                if (S2.ApproxEquals(a.Vertex(offset), b.Vertex(0), maxError))
                {
                    var success = true;
                    for (var i = 0; i < a.NumVertices; ++i)
                    {
                        if (!S2.ApproxEquals(a.Vertex(i + offset), b.Vertex(i), maxError))
                        {
                            success = false;
                            break;
                        }
                    }
                    if (success)
                    {
                        return(true);
                    }
                    // Otherwise continue looping. There may be more than one candidate
                    // starting offset since vertices are only matched approximately.
                }
            }
            return(false);
        }
コード例 #2
0
        private void assertPointApproximatelyEquals(
            S2Loop s2Loop, int vertexIndex, double lat, double lng, double error)
        {
            var latLng = new S2LatLng(s2Loop.Vertex(vertexIndex));

            assertDoubleNear(latLng.LatDegrees, lat, error);
            assertDoubleNear(latLng.LngDegrees, lng, error);
        }
コード例 #3
0
        public void testRoundingError()
        {
            var a = new S2Point(-0.9190364081111774, 0.17231932652084575, 0.35451111445694833);
            var b = new S2Point(-0.92130667053206, 0.17274500072476123, 0.3483578383756171);
            var c = new S2Point(-0.9257244057938284, 0.17357332608634282, 0.3360158106235289);
            var d = new S2Point(-0.9278712595449962, 0.17397586116468677, 0.32982923679138537);

            assertTrue(S2Loop.IsValidLoop(new List <S2Point>(new[] { a, b, c, d })));
        }
コード例 #4
0
 private S2Loop rotate(S2Loop loop)
 {
     var vertices = new List<S2Point>();
     for (var i = 1; i <= loop.NumVertices; ++i)
     {
         vertices.Add(loop.Vertex(i));
     }
     return new S2Loop(vertices);
 }
コード例 #5
0
    public void Test_S2ConvexHullQuery_EmptyLoop()
    {
        S2ConvexHullQuery query = new();
        S2Loop            empty = (S2Loop.kEmpty);

        query.AddLoop(empty);
        var result = (query.GetConvexHull());

        Assert.True(result.IsEmpty());
    }
コード例 #6
0
        private S2Loop rotate(S2Loop loop)
        {
            var vertices = new List <S2Point>();

            for (var i = 1; i <= loop.NumVertices; ++i)
            {
                vertices.Add(loop.Vertex(i));
            }
            return(new S2Loop(vertices));
        }
コード例 #7
0
    public void Test_S2ConvexHullQuery_FullLoop()
    {
        S2ConvexHullQuery query = new();
        S2Loop            full  = (S2Loop.kFull);

        query.AddLoop(full);
        var result = (query.GetConvexHull());

        Assert.True(result.IsFull());
    }
コード例 #8
0
 private static bool LoopHasVertex(S2Loop loop, S2Point p)
 {
     for (int i = 0; i < loop.NumVertices; ++i)
     {
         if (loop.Vertex(i) == p)
         {
             return(true);
         }
     }
     return(false);
 }
コード例 #9
0
 private bool findLoop(S2Loop loop, List <S2Loop> candidates, double maxError)
 {
     for (var i = 0; i < candidates.Count; ++i)
     {
         if (loopsEqual(loop, candidates[i], maxError))
         {
             return(true);
         }
     }
     return(false);
 }
コード例 #10
0
    public void Test_MakeLoop_ValidInput()
    {
        Assert.True(MakeLoop("-20:150, -20:151, -19:150", out var loop));
        var expected = new S2Loop(new[]
        {
            S2LatLng.FromDegrees(-20, 150).ToPoint(),
            S2LatLng.FromDegrees(-20, 151).ToPoint(),
            S2LatLng.FromDegrees(-19, 150).ToPoint(),
        });

        Assert.True(loop.BoundaryApproxEquals(expected));
    }
コード例 #11
0
    public void Test_ContainsBruteForce_ConsistentWithS2Loop()
    {
        // Checks that ContainsBruteForce agrees with S2Loop.Contains().
        var loop = S2Loop.MakeRegularLoop(MakePointOrDie("89:-179"), S1Angle.FromDegrees(10), 100);

        S2Loop.Shape shape = new(loop);
        for (int i = 0; i < loop.NumVertices; ++i)
        {
            Assert.Equal(loop.Contains(loop.Vertex(i)),
                         shape.ContainsBruteForce(loop.Vertex(i)));
        }
    }
コード例 #12
0
        protected override void SetUp()
        {
            base.SetUp();
            southHemi = new S2Loop(northHemi);
            southHemi.Invert();

            eastHemi = new S2Loop(westHemi);
            eastHemi.Invert();

            farHemi = new S2Loop(nearHemi);
            farHemi.Invert();
        }
コード例 #13
0
        protected override void SetUp()
        {
            base.SetUp();
            southHemi = new S2Loop(northHemi);
            southHemi.Invert();

            eastHemi = new S2Loop(westHemi);
            eastHemi.Invert();

            farHemi = new S2Loop(nearHemi);
            farHemi.Invert();
        }
コード例 #14
0
        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);
                }
            }
        }
コード例 #15
0
 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);
     }
 }
コード例 #16
0
 // Initializes an S2LaxLoopShape from the given S2Loop, by copying its data.
 //
 // REQUIRES: !loop.IsFull
 //           [Use S2LaxPolygonShape if you need to represent a full loop.]
 public void Init(S2Loop loop)
 {
     System.Diagnostics.Debug.Assert(!loop.IsFull()); // Full loops not supported; use S2LaxPolygonShape
     if (loop.IsEmpty())
     {
         NumVertices = 0;
         vertices_   = null;
     }
     else
     {
         NumVertices = loop.NumVertices;
         vertices_   = loop.CloneVertices();
     }
 }
コード例 #17
0
ファイル: S2ConvexHullQuery.cs プロジェクト: alas/s2geometry
 // Add a loop to the input geometry.
 public void AddLoop(S2Loop loop)
 {
     bound_ = bound_.Union(loop.GetRectBound());
     if (loop.IsEmptyOrFull())
     {
         // The empty and full loops consist of a single fake "vertex" that should
         // not be added to our point collection.
         return;
     }
     for (int i = 0; i < loop.NumVertices; ++i)
     {
         points_.Add(loop.Vertex(i));
     }
 }
コード例 #18
0
    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));
        }
    }
コード例 #19
0
        public void Test_S2ClosestEdgeQuery_EmptyTargetOptimized()
        {
            // Ensure that the optimized algorithm handles empty targets when a distance
            // limit is specified.
            MutableS2ShapeIndex index = new();

            index.Add(new S2Polygon.OwningShape(new S2Polygon(
                                                    S2Loop.MakeRegularLoop(new S2Point(1, 0, 0), S1Angle.FromRadians(0.1), 1000))));
            S2ClosestEdgeQuery query = new(index);

            query.Options_.MaxDistance = new(S1Angle.FromRadians(1e-5));
            MutableS2ShapeIndex target_index = new();

            S2ClosestEdgeQuery.ShapeIndexTarget target = new(target_index);
            Assert.Empty(query.FindClosestEdges(target));
        }
コード例 #20
0
ファイル: S2TextFormat.cs プロジェクト: alas/s2geometry
    public static string ToDebugString(this S2Loop loop)
    {
        if (loop.IsEmpty())
        {
            return("empty");
        }
        else if (loop.IsFull())
        {
            return("full");
        }

        if (loop.NumVertices > 0)
        {
            return(AppendVertices(loop.CloneVertices(), loop.NumVertices));
        }
        return("");
    }
コード例 #21
0
    private static void TestNorthPoleLoop(S1Angle radius, int num_vertices)
    {
        // If the radius is very close to 90, then it's hard to predict whether the
        // result will be the full loop or not.
        Assert.True(Math.Abs(radius.Radians - S2.M_PI_2) >= S2.DoubleError);

        S2ConvexHullQuery query = new();
        var loop = S2Loop.MakeRegularLoop(new S2Point(0, 0, 1), radius, num_vertices);

        query.AddLoop(loop);
        var result = query.GetConvexHull();

        if (radius > S1Angle.FromRadians(S2.M_PI_2))
        {
            Assert.True(result.IsFull());
        }
        else
        {
            Assert.True(result.BoundaryEquals(loop));
        }
    }
コード例 #22
0
        public void Test_S2PolygonLayer_DuplicateInputEdges()
        {
            // Check that S2PolygonLayer can assemble polygons even when there are
            // duplicate edges (after sibling pairs are removed), and then report the
            // duplicate edges as an error.
            S2Builder builder = new(new Options());
            S2Polygon output  = new();

            S2PolygonLayer.Options options = new();
            options.Validate = (true);
            builder.StartLayer(new S2PolygonLayer(output, options));
            builder.AddPolyline(MakePolylineOrDie(
                                    "0:0, 0:2, 2:2, 1:1, 0:2, 2:2, 2:0, 0:0"));
            Assert.False(builder.Build(out var error));
            Assert.Equal(S2ErrorCode.POLYGON_LOOPS_SHARE_EDGE, error.Code);
            Assert.Equal(2, output.NumLoops());
            S2Loop loop0 = MakeLoopOrDie("0:0, 0:2, 2:2, 2:0");
            S2Loop loop1 = (MakeLoopOrDie("0:2, 2:2, 1:1"));

            Assert.True(loop0 == output.Loop(0));
            Assert.True(loop1 == output.Loop(1));
        }
コード例 #23
0
    public void Test_S2ContainsPointQuery_GetContainingShapes()
    {
        // Also tests ShapeContains().
        int                 kNumVerticesPerLoop = 10;
        S1Angle             kMaxLoopRadius      = S2Testing.KmToAngle(10);
        S2Cap               center_cap          = new(S2Testing.RandomPoint(), kMaxLoopRadius);
        MutableS2ShapeIndex index = new();

        for (int i = 0; i < 100; ++i)
        {
            var loop = S2Loop.MakeRegularLoop(
                S2Testing.SamplePoint(center_cap),
                S2Testing.Random.RandDouble() * kMaxLoopRadius, kNumVerticesPerLoop);
            index.Add(new S2Loop.Shape(loop));
        }
        var query = index.MakeS2ContainsPointQuery();

        for (int i = 0; i < 100; ++i)
        {
            S2Point        p        = S2Testing.SamplePoint(center_cap);
            List <S2Shape> expected = new();
            foreach (var shape in index)
            {
                var loop = ((S2Loop.Shape)shape).Loop;
                if (loop.Contains(p))
                {
                    Assert.True(query.ShapeContains(shape, p));
                    expected.Add(shape);
                }
                else
                {
                    Assert.False(query.ShapeContains(shape, p));
                }
            }
            var actual = query.GetContainingShapes(p);
            Assert.Equal(expected, actual);
        }
    }
コード例 #24
0
ファイル: S2TextFormat.cs プロジェクト: alas/s2geometry
    // As above, but does not Debug.Assert-fail on invalid input. Returns true if
    // conversion is successful.
    public static bool MakeLoop(string str, out S2Loop?loop, S2Debug override_ = S2Debug.ALLOW)
    {
        if (str == "empty")
        {
            loop = S2Loop.kEmpty;
            return(true);
        }

        if (str == "full")
        {
            loop = S2Loop.kFull;
            return(true);
        }

        loop = null;
        var vertices = new List <S2Point>();

        if (!ParsePoints(str, vertices))
        {
            return(false);
        }
        loop = new S2Loop(vertices, override_);
        return(true);
    }
コード例 #25
0
 private bool findLoop(S2Loop loop, List<S2Loop> candidates, double maxError)
 {
     for (var i = 0; i < candidates.Count; ++i)
     {
         if (loopsEqual(loop, candidates[i], maxError))
         {
             return true;
         }
     }
     return false;
 }
コード例 #26
0
        private bool loopsEqual(S2Loop a, S2Loop b, double maxError)
        {
            // Return true if two loops have the same cyclic vertex sequence.

            if (a.NumVertices != b.NumVertices)
            {
                return false;
            }
            for (var offset = 0; offset < a.NumVertices; ++offset)
            {
                if (S2.ApproxEquals(a.Vertex(offset), b.Vertex(0), maxError))
                {
                    var success = true;
                    for (var i = 0; i < a.NumVertices; ++i)
                    {
                        if (!S2.ApproxEquals(a.Vertex(i + offset), b.Vertex(i), maxError))
                        {
                            success = false;
                            break;
                        }
                    }
                    if (success)
                    {
                        return true;
                    }
                    // Otherwise continue looping. There may be more than one candidate
                    // starting offset since vertices are only matched approximately.
                }
            }
            return false;
        }
コード例 #27
0
 public S2LaxClosedPolylineShape(S2Loop loop) : base(loop)
 {
 }
コード例 #28
0
 // Constructs an S2LaxLoopShape from the given S2Loop, by copying its data.
 public S2LaxLoopShape(S2Loop loop)
 {
     Init(loop);
 }
コード例 #29
0
        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);
                }
            }
        }
コード例 #30
0
        public void testAreaCentroid()
        {
            assertDoubleNear(northHemi.Area, 2*S2.Pi);
            assertDoubleNear(eastHemi.Area, 2*S2.Pi);

            // Construct spherical caps of random height, and approximate their boundary
            // with closely spaces vertices. Then check that the area and centroid are
            // correct.

            for (var i = 0; i < 100; ++i)
            {
                // Choose a coordinate frame for the spherical cap.
                var x = randomPoint();
                var y = S2Point.Normalize(S2Point.CrossProd(x, randomPoint()));
                var z = S2Point.Normalize(S2Point.CrossProd(x, y));

                // Given two points at latitude phi and whose longitudes differ by dtheta,
                // the geodesic between the two points has a maximum latitude of
                // atan(Tan(phi) / Cos(dtheta/2)). This can be derived by positioning
                // the two points at (-dtheta/2, phi) and (dtheta/2, phi).
                //
                // We want to position the vertices close enough together so that their
                // maximum distance from the boundary of the spherical cap is kMaxDist.
                // Thus we want fabs(atan(Tan(phi) / Cos(dtheta/2)) - phi) <= kMaxDist.
                var kMaxDist = 1e-6;
                var height = 2*rand.NextDouble();
                var phi = Math.Asin(1 - height);
                var maxDtheta =
                    2*Math.Acos(Math.Tan(Math.Abs(phi))/Math.Tan(Math.Abs(phi) + kMaxDist));
                maxDtheta = Math.Min(S2.Pi, maxDtheta); // At least 3 vertices.

                var vertices = new List<S2Point>();
                for (double theta = 0; theta < 2*S2.Pi; theta += rand.NextDouble()*maxDtheta)
                {
                    var xCosThetaCosPhi = x * (Math.Cos(theta)*Math.Cos(phi));
                    var ySinThetaCosPhi = y * (Math.Sin(theta)*Math.Cos(phi));
                    var zSinPhi = z * Math.Sin(phi);

                    var sum = xCosThetaCosPhi + ySinThetaCosPhi + zSinPhi;

                    vertices.Add(sum);
                }

                var loop = new S2Loop(vertices);
                var areaCentroid = loop.AreaAndCentroid;

                var area = loop.Area;
                var centroid = loop.Centroid;
                var expectedArea = 2*S2.Pi*height;
                assertTrue(areaCentroid.Area == area);
                assertTrue(centroid.Equals(areaCentroid.Centroid));
                assertTrue(Math.Abs(area - expectedArea) <= 2*S2.Pi*kMaxDist);

                // high probability
                assertTrue(Math.Abs(area - expectedArea) >= 0.01*kMaxDist);

                var expectedCentroid = z*expectedArea*(1 - 0.5*height);

                assertTrue((centroid.Value - expectedCentroid).Norm <= 2*kMaxDist);
            }
        }
コード例 #31
0
 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));
     }
 }
コード例 #32
0
 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);
     }
 }
コード例 #33
0
 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));
     }
 }
コード例 #34
0
    public void Test_UninitializedLoop()
    {
        var loop = new S2Loop(Array.Empty <S2Point>());

        Assert.Equal("", loop.ToDebugString());
    }
コード例 #35
0
        public void testAreaCentroid()
        {
            assertDoubleNear(northHemi.Area, 2 * S2.Pi);
            assertDoubleNear(eastHemi.Area, 2 * S2.Pi);

            // Construct spherical caps of random height, and approximate their boundary
            // with closely spaces vertices. Then check that the area and centroid are
            // correct.

            for (var i = 0; i < 100; ++i)
            {
                // Choose a coordinate frame for the spherical cap.
                var x = randomPoint();
                var y = S2Point.Normalize(S2Point.CrossProd(x, randomPoint()));
                var z = S2Point.Normalize(S2Point.CrossProd(x, y));

                // Given two points at latitude phi and whose longitudes differ by dtheta,
                // the geodesic between the two points has a maximum latitude of
                // atan(Tan(phi) / Cos(dtheta/2)). This can be derived by positioning
                // the two points at (-dtheta/2, phi) and (dtheta/2, phi).
                //
                // We want to position the vertices close enough together so that their
                // maximum distance from the boundary of the spherical cap is kMaxDist.
                // Thus we want fabs(atan(Tan(phi) / Cos(dtheta/2)) - phi) <= kMaxDist.
                var kMaxDist  = 1e-6;
                var height    = 2 * rand.NextDouble();
                var phi       = Math.Asin(1 - height);
                var maxDtheta =
                    2 * Math.Acos(Math.Tan(Math.Abs(phi)) / Math.Tan(Math.Abs(phi) + kMaxDist));
                maxDtheta = Math.Min(S2.Pi, maxDtheta); // At least 3 vertices.

                var vertices = new List <S2Point>();
                for (double theta = 0; theta < 2 * S2.Pi; theta += rand.NextDouble() * maxDtheta)
                {
                    var xCosThetaCosPhi = x * (Math.Cos(theta) * Math.Cos(phi));
                    var ySinThetaCosPhi = y * (Math.Sin(theta) * Math.Cos(phi));
                    var zSinPhi         = z * Math.Sin(phi);

                    var sum = xCosThetaCosPhi + ySinThetaCosPhi + zSinPhi;

                    vertices.Add(sum);
                }

                var loop         = new S2Loop(vertices);
                var areaCentroid = loop.AreaAndCentroid;

                var area         = loop.Area;
                var centroid     = loop.Centroid;
                var expectedArea = 2 * S2.Pi * height;
                assertTrue(areaCentroid.Area == area);
                assertTrue(centroid.Equals(areaCentroid.Centroid));
                assertTrue(Math.Abs(area - expectedArea) <= 2 * S2.Pi * kMaxDist);

                // high probability
                assertTrue(Math.Abs(area - expectedArea) >= 0.01 * kMaxDist);

                var expectedCentroid = z * expectedArea * (1 - 0.5 * height);

                assertTrue((centroid.Value - expectedCentroid).Norm <= 2 * kMaxDist);
            }
        }
コード例 #36
0
 private void assertPointApproximatelyEquals(
     S2Loop s2Loop, int vertexIndex, double lat, double lng, double error)
 {
     var latLng = new S2LatLng(s2Loop.Vertex(vertexIndex));
     assertDoubleNear(latLng.LatDegrees, lat, error);
     assertDoubleNear(latLng.LngDegrees, lng, error);
 }
コード例 #37
0
 public void AddEdges(S2Cap index_cap, int num_edges, MutableS2ShapeIndex index)
 {
     index.Add(new S2Loop.Shape(S2Loop.MakeRegularLoop(
                                    index_cap.Center, index_cap.RadiusAngle(), num_edges)));
 }