Esempio n. 1
0
    public void Test_S2RegionTermIndexer_MaxLevelSetLoosely()
    {
        // Test that correct terms are generated even when (max_level - min_level)
        // is not a multiple of level_mod.
        var options = new S2RegionTermIndexer.Options();

        options.MinLevel = (1);
        options.LevelMod = (2);
        options.MaxLevel = (19);
        var indexer1 = new S2RegionTermIndexer(options);

        options.MaxLevel = (20);
        var indexer2 = new S2RegionTermIndexer(options);

        S2Point point = S2Testing.RandomPoint();

        Assert.Equal(indexer1.GetIndexTerms(point, ""),
                     indexer2.GetIndexTerms(point, ""));
        Assert.Equal(indexer1.GetQueryTerms(point, ""),
                     indexer2.GetQueryTerms(point, ""));

        S2Cap cap = S2Testing.GetRandomCap(0.0, 1.0);  // Area range.

        Assert.Equal(indexer1.GetIndexTerms(cap, ""),
                     indexer2.GetIndexTerms(cap, ""));
        Assert.Equal(indexer1.GetQueryTerms(cap, ""),
                     indexer2.GetQueryTerms(cap, ""));
    }
Esempio n. 2
0
        private static void ChooseEdgeNearCell(S2Cell cell, out S2Point a, out S2Point b)
        {
            S2Cap cap = cell.GetCapBound();

            if (S2Testing.Random.OneIn(5))
            {
                // Choose a point anywhere on the sphere.
                a = S2Testing.RandomPoint();
            }
            else
            {
                // Choose a point inside or somewhere near the cell.
                a = S2Testing.SamplePoint(new S2Cap(cap.Center, 1.5 * cap.RadiusAngle()));
            }
            // Now choose a maximum edge length ranging from very short to very long
            // relative to the cell size, and choose the other endpoint.
            double max_length = Math.Min(100 * Math.Pow(1e-4, S2Testing.Random.RandDouble()) *
                                         cap.Radius.Radians(), S2.M_PI_2);

            b = S2Testing.SamplePoint(new S2Cap(a, S1Angle.FromRadians(max_length)));

            if (S2Testing.Random.OneIn(20))
            {
                // Occasionally replace edge with antipodal edge.
                a = -a;
                b = -b;
            }
        }
Esempio n. 3
0
        public List <Guid> Search(double lon, double lat, int radius)
        {
            var latlng = S2LatLng.FromDegrees(lat, lon);

            var centerPoint = pointFromLatLng(lat, lon);

            var centerAngle = ((double)radius) / EarthRadiusM;

            var cap = S2Cap.FromAxisAngle(centerPoint, S1Angle.FromRadians(centerAngle));

            var regionCoverer = new S2RegionCoverer();

            regionCoverer.MaxLevel = 13;

            //  regionCoverer.MinLevel = 13;


            //regionCoverer.MaxCells = 1000;
            // regionCoverer.LevelMod = 0;


            var covering = regionCoverer.GetCovering(cap);



            var res = new List <Guid>();


            foreach (var u in covering)
            {
                var sell = new S2CellId(u.Id);

                if (sell.Level < _level)
                {
                    var begin = sell.ChildBeginForLevel(_level);
                    var end   = sell.ChildEndForLevel(_level);
                    do
                    {
                        var cur = tree.Search(new S2CellId(begin.Id));

                        if (cur != null)
                        {
                            res.AddRange(cur.Pointer);
                        }

                        begin = begin.Next;
                    } while (begin.Id != end.Id);
                }
                else
                {
                    var item = tree.Search(sell);
                    if (item != null)
                    {
                        res.AddRange(item.Pointer);
                    }
                }
            }
            return(res);
        }
Esempio n. 4
0
        public void Test_S2Cap_AddNonEmptyCapToEmptyCap()
        {
            S2Cap empty         = S2Cap.Empty;
            S2Cap non_empty_cap = new(new S2Point(1, 0, 0), S1Angle.FromDegrees(10));

            empty = empty.AddCap(non_empty_cap);
            Assert.Equal(non_empty_cap.Area(), empty.Area());
        }
Esempio n. 5
0
        public List <Guid> Search(double lon, double lat, int radius)
        {
            var latlng = S2LatLng.FromDegrees(lat, lon);

            var centerPoint = Index.pointFromLatLng(lat, lon);

            var centerAngle = ((double)radius) / Index.EarthRadiusM;

            var cap = S2Cap.FromAxisAngle(centerPoint, S1Angle.FromRadians(centerAngle));

            var regionCoverer = new S2RegionCoverer();

            regionCoverer.MaxLevel = 13;

            //  regionCoverer.MinLevel = 13;


            //regionCoverer.MaxCells = 1000;
            // regionCoverer.LevelMod = 0;


            var covering = regionCoverer.GetCovering(cap);



            var res = new List <Guid>();


            foreach (var u in covering)
            {
                var sell = new S2CellId(u.Id);

                if (sell.Level < _level)
                {
                    var begin = sell.ChildBeginForLevel(_level);
                    var end   = sell.ChildEndForLevel(_level);

                    var qres = rtree.Query(new Range <S2CellId>(begin, end));

                    foreach (var r in qres)
                    {
                        res.AddRange(r.Content);
                    }
                }
                else
                {
                    var qres = rtree.Query(new Range <S2CellId>(sell));
                    if (qres.Count > 0)
                    {
                        foreach (var r in qres)
                        {
                            res.AddRange(r.Content);
                        }
                    }
                }
            }
            return(res);
        }
    public void AddEdges(S2Cap index_cap, int num_edges, MutableS2ShapeIndex index)
    {
        var fractal = new S2Testing.Fractal();

        fractal.SetLevelForApproxMaxEdges(num_edges);
        index.Add(new S2Loop.Shape(
                      fractal.MakeLoop(S2Testing.GetRandomFrameAt(index_cap.Center),
                                       index_cap.RadiusAngle())));
    }
Esempio n. 7
0
    public void Test_S2ConvexHullQuery_PointsInsideHull()
    {
        // Repeatedly build the convex hull of a set of points, then add more points
        // inside that loop and build the convex hull again.  The result should
        // always be the same.
        int kIters = 1000;

        for (int iter = 0; iter < kIters; ++iter)
        {
            S2Testing.Random.Reset(iter + 1);  // Easier to reproduce a specific case.

            // Choose points from within a cap of random size, up to but not including
            // an entire hemisphere.
            S2Cap             cap   = S2Testing.GetRandomCap(S2.DoubleError, 1.999 * Math.PI);
            S2ConvexHullQuery query = new();
            int num_points1         = S2Testing.Random.Uniform(100) + 3;
            for (int i = 0; i < num_points1; ++i)
            {
                query.AddPoint(S2Testing.SamplePoint(cap));
            }
            var hull = query.GetConvexHull();

            // When the convex hull is nearly a hemisphere, the algorithm sometimes
            // returns a full cap instead.  This is because it first computes a
            // bounding rectangle for all the input points/edges and then converts it
            // to a bounding cap, which sometimes yields a non-convex cap (radius
            // larger than 90 degrees).  This should not be a problem in practice
            // (since most convex hulls are not hemispheres), but in order make this
            // test pass reliably it means that we need to reject convex hulls whose
            // bounding cap (when computed from a bounding rectangle) is not convex.
            //
            // TODO(b/203702905): This test can still fail (about 1 iteration in
            // 500,000) because the S2LatLngRect::GetCapBound implementation does not
            // guarantee that A.Contains(B) implies
            // A.GetCapBound().Contains(B.GetCapBound()).
            if (hull.GetCapBound().Height() >= 1)
            {
                continue;
            }

            // Otherwise, add more points inside the convex hull.
            int num_points2 = 1000;
            for (int i = 0; i < num_points2; ++i)
            {
                S2Point p = S2Testing.SamplePoint(cap);
                if (hull.Contains(p))
                {
                    query.AddPoint(p);
                }
            }
            // Finally, build a new convex hull and check that it hasn't changed.
            var hull2 = (query.GetConvexHull());
            _logger.WriteLine("Iteration: " + iter);
            Assert.True(hull2.BoundaryEquals(hull));
        }
    }
    public void AddEdges(S2Cap index_cap, int num_edges, MutableS2ShapeIndex index)
    {
        var points = new List <S2Point>();

        for (int i = 0; i < num_edges; ++i)
        {
            points.Add(S2Testing.SamplePoint(index_cap));
        }
        index.Add(new S2PointVectorShape(points.ToArray()));
    }
        protected S2Cap getRandomCap(double minArea, double maxArea)
        {
            var capArea = maxArea
                          * Math.Pow(minArea / maxArea, rand.NextDouble());

            Assert.True(capArea >= minArea && capArea <= maxArea);

            // The surface area of a cap is 2*Pi times its height.
            return(S2Cap.FromAxisArea(randomPoint(), capArea));
        }
Esempio n. 10
0
            public void AddPoints(S2Cap index_cap, int num_points, TestIndex index)
            {
                var points = S2Testing.MakeRegularPoints(
                    index_cap.Center, index_cap.RadiusAngle(), num_points);

                for (int i = 0; i < points.Length; ++i)
                {
                    index.Add(points[i], i);
                }
            }
Esempio n. 11
0
        public void Test_S2Cap_Union()
        {
            // Two caps which have the same center but one has a larger radius.
            S2Cap a = new(GetLatLngPoint(50.0, 10.0), S1Angle.FromDegrees(0.2));
            S2Cap b = new(GetLatLngPoint(50.0, 10.0), S1Angle.FromDegrees(0.3));

            Assert.True(b.Contains(a));
            Assert.Equal(b, a.Union(b));

            // Two caps where one is the full cap.
            Assert.True(a.Union(S2Cap.Full).IsFull());

            // Two caps where one is the empty cap.
            Assert.Equal(a, a.Union(S2Cap.Empty));

            // Two caps which have different centers, one entirely encompasses the other.
            S2Cap c = new(GetLatLngPoint(51.0, 11.0), S1Angle.FromDegrees(1.5));

            Assert.True(c.Contains(a));
            Assert.Equal(a.Union(c).Center, c.Center);
            Assert.Equal(a.Union(c).Radius, c.Radius);

            // Two entirely disjoint caps.
            S2Cap d = new(GetLatLngPoint(51.0, 11.0), S1Angle.FromDegrees(0.1));

            Assert.False(d.Contains(a));
            Assert.False(d.Intersects(a));
            Assert.True(a.Union(d).ApproxEquals(d.Union(a)));
            Assert2.Near(50.4588, new S2LatLng(a.Union(d).Center).Lat().GetDegrees(), 0.001);
            Assert2.Near(10.4525, new S2LatLng(a.Union(d).Center).Lng().GetDegrees(), 0.001);
            Assert2.Near(0.7425, a.Union(d).Radius.Degrees(), 0.001);

            // Two partially overlapping caps.
            S2Cap e = new(GetLatLngPoint(50.3, 10.3), S1Angle.FromDegrees(0.2));

            Assert.False(e.Contains(a));
            Assert.True(e.Intersects(a));
            Assert.True(a.Union(e).ApproxEquals(e.Union(a)));
            Assert2.Near(50.1500, new S2LatLng(a.Union(e).Center).Lat().GetDegrees(), 0.001);
            Assert2.Near(10.1495, new S2LatLng(a.Union(e).Center).Lng().GetDegrees(), 0.001);
            Assert2.Near(0.3781, a.Union(e).Radius.Degrees(), 0.001);

            // Two very large caps, whose radius sums to in excess of 180 degrees, and
            // whose centers are not antipodal.
            S2Cap f = new(new S2Point(0, 0, 1).Normalize(), S1Angle.FromDegrees(150));
            S2Cap g = new(new S2Point(0, 1, 0).Normalize(), S1Angle.FromDegrees(150));

            Assert.True(f.Union(g).IsFull());

            // Two non-overlapping hemisphere caps with antipodal centers.
            S2Cap hemi = S2Cap.FromCenterHeight(new S2Point(0, 0, 1).Normalize(), 1);

            Assert.True(hemi.Union(hemi.Complement()).IsFull());
        }
        /**
   * Generates a random edge whose center is in the given cap.
   */

        private S2Edge randomEdgeCrossingCap(double maxLengthMeters, S2Cap cap)
        {
            // Pick the edge center at random.
            var edgeCenter = samplePoint(cap);
            // Pick two random points in a suitably sized cap about the edge center.
            var edgeCap = S2Cap.FromAxisAngle(
                edgeCenter, S1Angle.FromRadians(maxLengthMeters/S2LatLng.EarthRadiusMeters/2));
            var p1 = samplePoint(edgeCap);
            var p2 = samplePoint(edgeCap);
            return new S2Edge(p1, p2);
        }
        /*
         * Generates "numEdges" random edges, of length at most "edgeLengthMetersMax"
         * and each of whose center is in a randomly located cap with radius
         * "capSpanMeters", and puts results into "edges".
         */

        private void generateRandomEarthEdges(
            double edgeLengthMetersMax, double capSpanMeters, int numEdges, List <S2Edge> edges)
        {
            var cap = S2Cap.FromAxisAngle(
                randomPoint(), S1Angle.FromRadians(capSpanMeters / S2LatLng.EarthRadiusMeters));

            for (var i = 0; i < numEdges; ++i)
            {
                edges.Add(randomEdgeCrossingCap(edgeLengthMetersMax, cap));
            }
        }
Esempio n. 14
0
        public void Test_S2Cap_EncodeDecode()
        {
            S2Cap   cap     = S2Cap.FromCenterHeight(new S2Point(3, 2, 1).Normalize(), 1);
            Encoder encoder = new();

            cap.Encode(encoder);
            var decoder = encoder.Decoder();

            var(success, decoded_cap) = S2Cap.Decode(decoder);
            Assert.True(success);
            Assert.Equal(cap, decoded_cap);
        }
Esempio n. 15
0
        public void Test_S2Cap_GetRectBound()
        {
            // Empty and full caps.
            Assert.True(S2Cap.Empty.GetRectBound().IsEmpty());
            Assert.True(S2Cap.Full.GetRectBound().IsFull());

            // Maximum allowable error for latitudes and longitudes measured in
            // degrees.  (Assert2.Near isn't sufficient.)

            // Cap that includes the south pole.
            S2LatLngRect rect = new S2Cap(GetLatLngPoint(-45, 57),
                                          S1Angle.FromDegrees(50)).GetRectBound();

            Assert2.Near(rect.LatLo().GetDegrees(), -90, kDegreeEps);
            Assert2.Near(rect.LatHi().GetDegrees(), 5, kDegreeEps);
            Assert.True(rect.Lng.IsFull());

            // Cap that is tangent to the north pole.
            rect = new S2Cap(new S2Point(1, 0, 1).Normalize(),
                             S1Angle.FromRadians(S2.M_PI_4 + 1e-16)).GetRectBound();
            Assert2.Near(rect.Lat.Lo, 0, kEps);
            Assert2.Near(rect.Lat.Hi, S2.M_PI_2, kEps);
            Assert.True(rect.Lng.IsFull());

            var p   = new S2Point(1, 0, 1).Normalize();
            var rb1 = S1Angle.FromDegrees(45 + 5e-15);

            rect = new S2Cap(p, rb1).GetRectBound();
            Assert2.Near(rect.LatLo().GetDegrees(), 0, kDegreeEps);
            Assert2.Near(rect.LatHi().GetDegrees(), 90, kDegreeEps);
            Assert.True(rect.Lng.IsFull());

            // The eastern hemisphere.
            var rb2 = S1Angle.FromRadians(S2.M_PI_2 + 2e-16);

            rect = new S2Cap(new S2Point(0, 1, 0), rb2).GetRectBound();
            Assert2.Near(rect.LatLo().GetDegrees(), -90, kDegreeEps);
            Assert2.Near(rect.LatHi().GetDegrees(), 90, kDegreeEps);
            Assert.True(rect.Lng.IsFull());

            // A cap centered on the equator.
            rect = new S2Cap(GetLatLngPoint(0, 50), S1Angle.FromDegrees(20)).GetRectBound();
            Assert2.Near(rect.LatLo().GetDegrees(), -20, kDegreeEps);
            Assert2.Near(rect.LatHi().GetDegrees(), 20, kDegreeEps);
            Assert2.Near(rect.LngLo().GetDegrees(), 30, kDegreeEps);
            Assert2.Near(rect.LngHi().GetDegrees(), 70, kDegreeEps);

            // A cap centered on the north pole.
            rect = new S2Cap(GetLatLngPoint(90, 123), S1Angle.FromDegrees(10)).GetRectBound();
            Assert2.Near(rect.LatLo().GetDegrees(), 80, kDegreeEps);
            Assert2.Near(rect.LatHi().GetDegrees(), 90, kDegreeEps);
            Assert.True(rect.Lng.IsFull());
        }
Esempio n. 16
0
        public void Test_S2CellUnion_Expand()
        {
            // This test generates coverings for caps of random sizes, expands
            // the coverings by a random radius, and then make sure that the new
            // covering covers the expanded cap.  It also makes sure that the
            // new covering is not too much larger than expected.

            var coverer = new S2RegionCoverer();

            for (var i = 0; i < 1000; ++i)
            {
                _logger.WriteLine($"Iteration {i}");
                var cap = S2Testing.GetRandomCap(
                    S2Cell.AverageArea(S2.kMaxCellLevel), S2.M_4_PI);

                // Expand the cap area by a random factor whose log is uniformly
                // distributed between 0 and log(1e2).
                var expanded_cap = S2Cap.FromCenterHeight(
                    cap.Center, Math.Min(2.0, Math.Pow(1e2, rnd.RandDouble()) * cap.Height()));

                var radius         = (expanded_cap.Radius - cap.Radius).Radians();
                var max_level_diff = rnd.Uniform(8);

                // Generate a covering for the original cap, and measure the maximum
                // distance from the cap center to any point in the covering.
                coverer.Options_.MaxCells = 1 + rnd.Skewed(10);
                var covering = coverer.GetCovering(cap);
                S2Testing.CheckCovering(cap, covering, true);
                var covering_radius = GetRadius(covering, cap.Center);

                // This code duplicates the logic in Expand(min_radius, max_level_diff)
                // that figures out an appropriate cell level to use for the expansion.
                int min_level = S2.kMaxCellLevel;
                foreach (var id in covering)
                {
                    min_level = Math.Min(min_level, id.Level());
                }
                var expand_level = Math.Min(min_level + max_level_diff,
                                            S2.kMinWidth.GetLevelForMinValue(radius));

                // Generate a covering for the expanded cap, and measure the new maximum
                // distance from the cap center to any point in the covering.
                covering.Expand(S1Angle.FromRadians(radius), max_level_diff);
                S2Testing.CheckCovering(expanded_cap, covering, false);
                double expanded_covering_radius = GetRadius(covering, cap.Center);

                // If the covering includes a tiny cell along the boundary, in theory the
                // maximum angle of the covering from the cap center can increase by up to
                // twice the maximum length of a cell diagonal.
                Assert.True(expanded_covering_radius - covering_radius <=
                            2 * S2.kMaxDiag.GetValue(expand_level));
            }
        }
        /**
         * Generates a random edge whose center is in the given cap.
         */

        private S2Edge randomEdgeCrossingCap(double maxLengthMeters, S2Cap cap)
        {
            // Pick the edge center at random.
            var edgeCenter = samplePoint(cap);
            // Pick two random points in a suitably sized cap about the edge center.
            var edgeCap = S2Cap.FromAxisAngle(
                edgeCenter, S1Angle.FromRadians(maxLengthMeters / S2LatLng.EarthRadiusMeters / 2));
            var p1 = samplePoint(edgeCap);
            var p2 = samplePoint(edgeCap);

            return(new S2Edge(p1, p2));
        }
Esempio n. 18
0
            public void AddPoints(S2Cap index_cap, int num_points, TestIndex index)
            {
                S2Testing.Fractal fractal = new();
                fractal.SetLevelForApproxMaxEdges(num_points);
                fractal.FractalDimension = (1.5);
                var loop = (
                    fractal.MakeLoop(S2Testing.GetRandomFrameAt(index_cap.Center),
                                     index_cap.RadiusAngle()));

                for (int i = 0; i < loop.NumVertices; ++i)
                {
                    index.Add(loop.Vertex(i), i);
                }
            }
Esempio n. 19
0
        public void testRectBound()
        {
            // Empty and full caps.
            Assert.True(S2Cap.Empty.RectBound.IsEmpty);
            Assert.True(S2Cap.Full.RectBound.IsFull);

            var kDegreeEps = 1e-13;
            // Maximum allowable error for latitudes and longitudes measured in
            // degrees. (assertDoubleNear uses a fixed tolerance that is too small.)

            // Cap that includes the south pole.
            var rect =
                S2Cap.FromAxisAngle(getLatLngPoint(-45, 57), S1Angle.FromDegrees(50)).RectBound;

            assertDoubleNear(rect.LatLo.Degrees, -90, kDegreeEps);
            assertDoubleNear(rect.LatHi.Degrees, 5, kDegreeEps);
            Assert.True(rect.Lng.IsFull);

            // Cap that is tangent to the north pole.
            rect = S2Cap.FromAxisAngle(S2Point.Normalize(new S2Point(1, 0, 1)), S1Angle.FromRadians(S2.PiOver4)).RectBound;
            assertDoubleNear(rect.Lat.Lo, 0);
            assertDoubleNear(rect.Lat.Hi, S2.PiOver2);
            Assert.True(rect.Lng.IsFull);

            rect = S2Cap
                   .FromAxisAngle(S2Point.Normalize(new S2Point(1, 0, 1)), S1Angle.FromDegrees(45)).RectBound;
            assertDoubleNear(rect.LatLo.Degrees, 0, kDegreeEps);
            assertDoubleNear(rect.LatHi.Degrees, 90, kDegreeEps);
            Assert.True(rect.Lng.IsFull);

            // The eastern hemisphere.
            rect = S2Cap
                   .FromAxisAngle(new S2Point(0, 1, 0), S1Angle.FromRadians(S2.PiOver2 + 5e-16)).RectBound;
            assertDoubleNear(rect.LatLo.Degrees, -90, kDegreeEps);
            assertDoubleNear(rect.LatHi.Degrees, 90, kDegreeEps);
            Assert.True(rect.Lng.IsFull);

            // A cap centered on the equator.
            rect = S2Cap.FromAxisAngle(getLatLngPoint(0, 50), S1Angle.FromDegrees(20)).RectBound;
            assertDoubleNear(rect.LatLo.Degrees, -20, kDegreeEps);
            assertDoubleNear(rect.LatHi.Degrees, 20, kDegreeEps);
            assertDoubleNear(rect.LngLo.Degrees, 30, kDegreeEps);
            assertDoubleNear(rect.LngHi.Degrees, 70, kDegreeEps);

            // A cap centered on the north pole.
            rect = S2Cap.FromAxisAngle(getLatLngPoint(90, 123), S1Angle.FromDegrees(10)).RectBound;
            assertDoubleNear(rect.LatLo.Degrees, 80, kDegreeEps);
            assertDoubleNear(rect.LatHi.Degrees, 90, kDegreeEps);
            Assert.True(rect.Lng.IsFull);
        }
Esempio n. 20
0
        // Encode/Decode not yet implemented for these types.
        // S2R2Rect
        // S2RegionIntersection
        // S2RegionUnion
        // TestEncodeDecode tests that the input encodes to match the expected
        // golden data, and then returns the decode of the data into dst.
        private static Region TestEncodeDecode <Region>(string golden, Region src) where Region : IEncoder, IS2Region <Region>
        {
            Encoder encoder = new();

            src.Encode(encoder);

            var str = encoder.HexString();

            Assert.Equal(golden, str);

            var decoder = encoder.Decoder();
            Dictionary <Type, Func <Decoder, (bool, IEncoder?)> > funcDict = new()
            {
                { typeof(S2Cap), (d) => S2Cap.Decode(d) },
                { typeof(S2Cell), (d) => S2Cell.Decode(d) },
Esempio n. 21
0
        public void Test_S2RegionEncodeDecodeTest_S2Cap()
        {
            S2Cap cap_from_point         = S2Cap.FromPoint(new S2Point(3, 2, 1).Normalize());
            var   cap_from_center_height = S2Cap.FromCenterHeight(new S2Point(0, 0, 1).Normalize(), 5);

            var cap = TestEncodeDecode(kEncodedCapEmpty, S2Cap.Empty);

            Assert.True(S2Cap.Empty.ApproxEquals(cap));
            cap = TestEncodeDecode(kEncodedCapFull, S2Cap.Full);
            Assert.True(S2Cap.Full.ApproxEquals(cap));
            cap = TestEncodeDecode(kEncodedCapFromPoint, cap_from_point);
            Assert.True(cap_from_point.ApproxEquals(cap));
            cap = TestEncodeDecode(kEncodedCapFromCenterHeight, cap_from_center_height);
            Assert.True(cap_from_center_height.ApproxEquals(cap));
        }
Esempio n. 22
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));
        }
    }
Esempio n. 23
0
        public void Test_S2Cap_GetCentroid()
        {
            // Empty and full caps.
            Assert.Equal(new S2Point(), S2Cap.Empty.Centroid());
            Assert.True(S2Cap.Full.Centroid().Norm() <= S2.DoubleError);

            // Random caps.
            for (int i = 0; i < 100; ++i)
            {
                S2Point center   = S2Testing.RandomPoint();
                double  height   = S2Testing.Random.UniformDouble(0.0, 2.0);
                S2Cap   cap      = S2Cap.FromCenterHeight(center, height);
                S2Point centroid = cap.Centroid();
                S2Point expected = center * (1.0 - height / 2.0) * cap.Area();
                Assert.True((expected - centroid).Norm() <= S2.DoubleError);
            }
        }
Esempio n. 24
0
    public void Test_S2ShapeIndexRegion_GetCapBound()
    {
        var id = S2CellId.FromDebugString("3/0123012301230123012301230123");

        // Add a polygon that is slightly smaller than the cell being tested.
        MutableS2ShapeIndex index = new();

        index.Add(NewPaddedCell(id, -kPadding));
        S2Cap cell_bound  = new S2Cell(id).GetCapBound();
        S2Cap index_bound = index.MakeS2ShapeIndexRegion().GetCapBound();

        Assert.True(index_bound.Contains(cell_bound));

        // Note that S2CellUnion.GetCapBound returns a slightly larger bound than
        // S2Cell.GetBound even when the cell union consists of a single S2CellId.
        Assert.True(index_bound.RadiusAngle() <= 1.00001 * cell_bound.RadiusAngle());
    }
Esempio n. 25
0
            public void AddPoints(S2Cap index_cap, int num_points, TestIndex index)
            {
                int            sqrt_num_points = (int)Math.Ceiling(Math.Sqrt(num_points));
                S2PointVector3 frame           = S2Testing.GetRandomFrameAt(index_cap.Center);
                double         radius          = index_cap.RadiusAngle().Radians;
                double         spacing         = 2 * radius / sqrt_num_points;

                for (int i = 0; i < sqrt_num_points; ++i)
                {
                    for (int j = 0; j < sqrt_num_points; ++j)
                    {
                        S2Point point = new(Math.Tan((i + 0.5) * spacing - radius),
                                            Math.Tan((j + 0.5) * spacing - radius), 1.0);
                        index.Add(S2.FromFrame(frame, point.Normalize()),
                                  i * sqrt_num_points + j);
                    }
                }
            }
Esempio n. 26
0
    public void Test_S2LatLngRect_GetCapBound()
    {
        // Bounding cap at center is smaller:
        Assert.True(RectFromDegrees(-45, -45, 45, 45).GetCapBound().
                    ApproxEquals(S2Cap.FromCenterHeight(new S2Point(1, 0, 0), 0.5)));

        // Bounding cap at north pole is smaller:
        Assert.True(RectFromDegrees(88, -80, 89, 80).GetCapBound().
                    ApproxEquals(new S2Cap(new S2Point(0, 0, 1), S1Angle.FromDegrees(2))));

        // Longitude span > 180 degrees:
        Assert.True(RectFromDegrees(-30, -150, -10, 50).GetCapBound().
                    ApproxEquals(new S2Cap(new S2Point(0, 0, -1), S1Angle.FromDegrees(80))));

        // Ensure hemispheres are bounded conservatively.
        Assert.True(RectFromDegrees(-10, -100, 0, 100).GetCapBound().Radius >=
                    S1ChordAngle.Right);
    }
Esempio n. 27
0
        private void getVertices(String str,
                                 S2Point x,
                                 S2Point y,
                                 S2Point z,
                                 double maxPerturbation,
                                 List <S2Point> vertices)
        {
            // Parse the vertices, perturb them if desired, and transform them into the
            // given frame.
            var line = makePolyline(str);

            for (var i = 0; i < line.NumVertices; ++i)
            {
                var p = line.Vertex(i);
                // (p[0]*x + p[1]*y + p[2]*z).Normalize()
                var axis = S2Point.Normalize(((x * p.X) + (y * p.Y)) + (z * p.Z));
                var cap  = S2Cap.FromAxisAngle(axis, S1Angle.FromRadians(maxPerturbation));
                vertices.Add(samplePoint(cap));
            }
        }
        protected S2Point samplePoint(S2Cap cap)
        {
            // We consider the cap axis to be the "z" axis. We choose two other axes to
            // complete the coordinate frame.

            var z = cap.Axis;
            var x = z.Ortho;
            var y = S2Point.CrossProd(z, x);

            // The surface area of a spherical cap is directly proportional to its
            // height. First we choose a random height, and then we choose a random
            // point along the circle at that height.

            var h     = rand.NextDouble() * cap.Height;
            var theta = 2 * S2.Pi * rand.NextDouble();
            var r     = Math.Sqrt(h * (2 - h)); // Radius of circle.

            // (cos(theta)*r*x + sin(theta)*r*y + (1-h)*z).Normalize()
            return(S2Point.Normalize(((x * Math.Cos(theta) * r) + (y * Math.Sin(theta) * r)) + (z * (1 - h))));
        }
Esempio n. 29
0
        public void Test_S2RegionCoverer_SimpleCoverings()
        {
            Assert.True(false); //TODO

            const int kMaxLevel = S2.kMaxCellLevel;
            var       options   = new S2RegionCoverer.Options
            {
                MaxCells = Int32.MaxValue
            };

            for (int i = 0; i < 1000; ++i)
            {
                int level = S2Testing.Random.Uniform(kMaxLevel + 1);
                options.MinLevel = (level);
                options.MaxLevel = (level);
                double max_area = Math.Min(S2.M_4_PI, 1000 * S2Cell.AverageArea(level));
                S2Cap  cap      = S2Testing.GetRandomCap(0.1 * S2Cell.AverageArea(kMaxLevel), max_area);
                var    covering = new List <S2CellId>();
                S2RegionCoverer.GetSimpleCovering(cap, cap.Center, level, covering);
                CheckCovering(options, cap, covering, false);
            }
        }
Esempio n. 30
0
        public void Test_S2RegionCoverer_RandomCaps()
        {
            const int kMaxLevel = S2.kMaxCellLevel;

            S2RegionCoverer.Options options = new();
            for (int i = 0; i < 1000; ++i)
            {
                do
                {
                    options.MinLevel = (S2Testing.Random.Uniform(kMaxLevel + 1));
                    options.MaxLevel = (S2Testing.Random.Uniform(kMaxLevel + 1));
                } while (options.MinLevel > options.MaxLevel);
                options.MaxCells = S2Testing.Random.Skewed(10);
                options.LevelMod = (1 + S2Testing.Random.Uniform(3));
                double max_area = Math.Min(S2.M_4_PI, (3 * options.MaxCells + 1) *
                                           S2Cell.AverageArea(options.MinLevel));
                S2Cap cap = S2Testing.GetRandomCap(0.1 * S2Cell.AverageArea(kMaxLevel),
                                                   max_area);
                S2RegionCoverer coverer = new(options);
                coverer.GetCovering(cap, out var covering);
                CheckCovering(options, cap, covering, false);
                coverer.GetInteriorCovering(cap, out var interior);
                CheckCovering(options, cap, interior, true);

                // Check that GetCovering is deterministic.
                coverer.GetCovering(cap, out var covering2);
                Assert.Equal(covering, covering2);

                // Also check S2CellUnion.Denormalize().  The denormalized covering
                // may still be different and smaller than "covering" because
                // S2RegionCoverer does not guarantee that it will not output all four
                // children of the same parent.
                S2CellUnion cells        = new(covering);
                var         denormalized = new List <S2CellId>();
                cells.Denormalize(options.MinLevel, options.LevelMod, denormalized);
                CheckCovering(options, cap, denormalized, false);
            }
        }
Esempio n. 31
0
    // The implementation is approximate but conservative; it always returns
    // "false" if the cell is not contained by the buffered region, but it may
    // also return false in some cases where "cell" is in fact contained.
    public bool Contains(S2Cell cell)
    {
        // Return true if the buffered region is guaranteed to cover whole globe.
        if (radius_successor_ > S1ChordAngle.Straight)
        {
            return(true);
        }

        // To implement this method perfectly would require computing the directed
        // Hausdorff distance, which is expensive (and not currently implemented).
        // However the following heuristic is almost as good in practice and much
        // cheaper to compute.

        // Return true if the unbuffered region contains this cell.
        if (Index().MakeS2ShapeIndexRegion().Contains(cell))
        {
            return(true);
        }

        // Otherwise approximate the cell by its bounding cap.
        //
        // NOTE(ericv): It would be slightly more accurate to first find the closest
        // point in the indexed geometry to the cell, and then measure the actual
        // maximum distance from that point to the cell (a poor man's Hausdorff
        // distance).  But based on actual tests this is not worthwhile.
        S2Cap cap = cell.GetCapBound();

        if (Radius < cap.Radius)
        {
            return(false);
        }

        // Return true if the distance to the cell center plus the radius of the
        // cell's bounding cap is less than or equal to "radius_".
        var target = new S2ClosestEdgeQuery.PointTarget(cell.Center());

        return(query_.IsDistanceLess(target, radius_successor_ - cap.Radius));
    }
        protected S2Point samplePoint(S2Cap cap)
        {
            // We consider the cap axis to be the "z" axis. We choose two other axes to
            // complete the coordinate frame.

            var z = cap.Axis;
            var x = z.Ortho;
            var y = S2Point.CrossProd(z, x);

            // The surface area of a spherical cap is directly proportional to its
            // height. First we choose a random height, and then we choose a random
            // point along the circle at that height.

            var h = rand.NextDouble()*cap.Height;
            var theta = 2*S2.Pi*rand.NextDouble();
            var r = Math.Sqrt(h*(2 - h)); // Radius of circle.

            // (cos(theta)*r*x + sin(theta)*r*y + (1-h)*z).Normalize()
            return S2Point.Normalize(((x * Math.Cos(theta)*r) + (y * Math.Sin(theta)*r)) + (z * (1 - h)));
        }