예제 #1
0
        public MainPage()
        {
            InitializeComponent();

            CheckDatabase();

            portals    = new List <PointOfInterest>();
            lvl14Cells = new List <MapPolygon>();
            lvl17Cells = new List <MapPolygon>();

            portalIcon      = null;
            portalHoverIcon = null;
            stopIcon        = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/pokedisk_blue_36.png"));
            stopHoverIcon   = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/pokedisk_black_36.png"));
            gymIcon         = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/gym_red_48.png"));
            gymHoverIcon    = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/gym_black_48.png"));

            lvl17Coverer = new S2RegionCoverer
            {
                MaxLevel = 17,
                MinLevel = 17,
                MaxCells = 1
            };

            lvl14Coverer = new S2RegionCoverer
            {
                MaxLevel = 14,
                MinLevel = 14
            };
        }
    // Verifies that an arbitrary S2ShapeIndex is buffered correctly, by first
    // converting the covering to an S2Polygon and then checking that (a) the
    // S2Polygon contains the original geometry and (b) the distance between the
    // original geometry and the boundary of the S2Polygon is at least "radius".
    //
    // The "radius" parameter is an S1Angle for convenience.
    // TODO(ericv): Add Degrees, Radians, etc, methods to S1ChordAngle?
    private static void TestBufferIndex(string index_str, S1Angle radius_angle, S2RegionCoverer coverer)
    {
        var          index    = MakeIndexOrDie(index_str);
        S1ChordAngle radius   = new(radius_angle);
        var          region   = new S2ShapeIndexBufferedRegion(index, radius);
        S2CellUnion  covering = coverer.GetCovering(region);
        // Compute an S2Polygon representing the union of the cells in the covering.
        S2Polygon covering_polygon = new();

        covering_polygon.InitToCellUnionBorder(covering);
        MutableS2ShapeIndex covering_index = new();

        covering_index.Add(new S2Polygon.Shape(covering_polygon));

        // (a) Check that the covering contains the original index.
        Assert.True(S2BooleanOperation.Contains(covering_index, index));

        // (b) Check that the distance between the boundary of the covering and the
        // the original indexed geometry is at least "radius".
        S2ClosestEdgeQuery query = new(covering_index);

        query.Options_.IncludeInteriors = (false);
        var target = new S2ClosestEdgeQuery.ShapeIndexTarget(index);

        Assert.False(query.IsDistanceLess(target, radius));
    }
        private static List <Coordinate> GetS2Cells(BoundingBox bbox)
        {
            var regionCoverer = new S2RegionCoverer
            {
                MinLevel = 15,
                MaxLevel = 15,
                //MaxCells = 100,
            };
            var region = new S2LatLngRect(
                S2LatLng.FromDegrees(bbox.MinimumLatitude, bbox.MinimumLongitude),
                S2LatLng.FromDegrees(bbox.MaximumLatitude, bbox.MaximumLongitude)
                );
            var cellIds = regionCoverer.GetCovering(region);
            var list    = new List <Coordinate>();

            foreach (var cellId in cellIds)
            {
                var center = cellId.ToLatLng();
                list.Add(new Coordinate(center.LatDegrees, center.LngDegrees));
            }
            // TODO: Check if point is within geofence
            //var filtered = FilterCoordinates(coordinates);
            //return filtered;
            return(list);
        }
예제 #4
0
        /// <summary>
        /// Find the cell of the given level that covers the given Geoposition.
        /// This method uses the library given S2RegionCoverer to find the leaf cell containing the given Geoposition
        /// and uses binary operation on the leaf cell's Id to find the higher level cell containing the leaf.
        /// This is somehow more accurate than using the S2RegionCoverer for the higher level cell, where some errors occured.
        /// </summary>
        /// <param name="pos">Position in the cell</param>
        /// <param name="level">Level of the cell</param>
        /// <returns>The cell covering the given position that matches the specifications</returns>
        private S2Cell FindExactCell(BasicGeoposition pos, int level)
        {
            var point = S2LatLngRect.FromPoint(S2LatLng.FromDegrees(pos.Latitude, pos.Longitude));

            var cells = new List <S2CellId>();

            // find leaf cell
            var coverer = new S2RegionCoverer()
            {
                MinLevel = 30,
                MaxLevel = 30,
                MaxCells = 1
            };

            coverer.GetCovering(point, cells);

            var leaf = new S2Cell(cells[0]);

            int   shift = 64 - (3 + level * 2 + 1);
            ulong id    = leaf.Id.Id & ulong.MaxValue << shift;

            id |= 0 | ((ulong)1 << shift);

            return(new S2Cell(new S2CellId(id)));
        }
예제 #5
0
        public List <S2CellId> GetS2CellIds(ushort level, int maxCells)
        {
            //var geofence = Geofence.FromMultiPolygon(this);
            var bbox          = GetBoundingBox();
            var regionCoverer = new S2RegionCoverer
            {
                MinLevel = level,
                MaxLevel = level,
                MaxCells = maxCells,
            };
            var region = new S2LatLngRect(
                S2LatLng.FromDegrees(bbox.MinimumLatitude, bbox.MinimumLongitude),
                S2LatLng.FromDegrees(bbox.MaximumLatitude, bbox.MaximumLongitude)
                );
            var coverage = new List <S2CellId>();

            regionCoverer.GetCovering(region, coverage);
            var result = new List <S2CellId>();

            foreach (var cellId in coverage)
            {
                var cell = new S2Cell(cellId);
                for (var i = 0; i <= 3; i++)
                {
                    var vertex = cell.GetVertex(i);
                    var coord  = new S2LatLng(new S2Point(vertex.X, vertex.Y, vertex.Z));
                    //if (geofence.Intersects(coord.LatDegrees, coord.LngDegrees))
                    if (GeofenceService.InPolygon(this, coord.LatDegrees, coord.LngDegrees))
                    {
                        result.Add(cellId);
                    }
                }
            }
            return(result);
        }
예제 #6
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);
        }
    public void Test_S2ShapeIndexBufferedRegion_PointSet()
    {
        // Test buffering a set of points.
        var coverer = new S2RegionCoverer();

        coverer.Options_.MaxCells = 100;
        TestBufferIndex("10:20 | 10:23 | 10:26 # #", S1Angle.FromDegrees(5), coverer);
    }
예제 #8
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 Test_S2ShapeIndexBufferedRegion_EmptyIndex()
    {
        // Test buffering an empty S2ShapeIndex.
        var         index    = new MutableS2ShapeIndex();
        var         radius   = new S1ChordAngle(S1Angle.FromDegrees(2));
        var         region   = new S2ShapeIndexBufferedRegion(index, radius);
        var         coverer  = new S2RegionCoverer();
        S2CellUnion covering = coverer.GetCovering(region);

        Assert.True(covering.IsEmpty());
    }
예제 #10
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));
            }
        }
예제 #11
0
        public void Test_S2RegionUnionTest_Basic()
        {
            S2RegionUnion ru_empty = new(new List <IS2Region>());

            Assert.Equal(0, ru_empty.Count());
            Assert.Equal(S2Cap.Empty, ru_empty.GetCapBound());
            Assert.Equal(S2LatLngRect.Empty, ru_empty.GetRectBound());
            var empty_clone = (S2RegionUnion)ru_empty.CustomClone();

            var two_point_region = new List <IS2Region>
            {
                new S2PointRegion(S2LatLng.FromDegrees(35, 40).ToPoint()),
                new S2PointRegion(S2LatLng.FromDegrees(-35, -40).ToPoint())
            };

            var two_points_orig = new S2RegionUnion(two_point_region);
            // two_point_region is in a valid, but unspecified, state.

            // Check that Clone() returns a deep copy.
            var two_points = (S2RegionUnion)two_points_orig.CustomClone();

            // The bounds below may not be exactly equal because the S2PointRegion
            // version converts each S2LatLng value to an S2Point and back.
            Assert.True(MakeLatLngRectOrDie("-35:-40,35:40") !.Value
                        .ApproxEquals(two_points.GetRectBound()));

            S2Cell face0 = S2Cell.FromFace(0);

            Assert.True(two_points.MayIntersect(face0));
            Assert.False(two_points.Contains(face0));

            Assert.True(two_points.Contains(S2LatLng.FromDegrees(35, 40).ToPoint()));
            Assert.True(two_points.Contains(S2LatLng.FromDegrees(-35, -40).ToPoint()));
            Assert.False(two_points.Contains(S2LatLng.FromDegrees(0, 0).ToPoint()));

            // Check that we can Add() another region.
            var three_points = (S2RegionUnion)two_points.CustomClone();

            Assert.False(three_points.Contains(S2LatLng.FromDegrees(10, 10).ToPoint()));
            three_points.Add(new S2RegionUnion(new List <IS2Region> {
                new S2PointRegion(S2LatLng.FromDegrees(10, 10).ToPoint())
            }));
            Assert.True(three_points.Contains(S2LatLng.FromDegrees(10, 10).ToPoint()));

            var coverer = new S2RegionCoverer();

            coverer.Options_.MaxCells = 1;
            coverer.GetCovering(two_points, out var covering);
            Assert.Single(covering);
            Assert.Equal(face0.Id, covering[0]);
        }
    public void Test_S2ShapeIndexBufferedRegion_FullPolygon()
    {
        // Test buffering an S2ShapeIndex that contains a full polygon.
        var         index    = MakeIndexOrDie("# # full");
        var         radius   = new S1ChordAngle(S1Angle.FromDegrees(2));
        var         region   = new S2ShapeIndexBufferedRegion(index, radius);
        var         coverer  = new S2RegionCoverer();
        S2CellUnion covering = coverer.GetCovering(region);

        Assert.Equal(6, covering.Size());
        foreach (S2CellId id in covering)
        {
            Assert.True(id.IsFace());
        }
    }
    public void Test_S2ShapeIndexBufferedRegion_PointZeroRadius()
    {
        // Test that buffering a point using a zero radius produces a non-empty
        // covering.  (This requires using "less than or equal to" distance tests.)
        var         index    = MakeIndexOrDie("34:25 # #");
        var         region   = new S2ShapeIndexBufferedRegion(index, S1ChordAngle.Zero);
        var         coverer  = new S2RegionCoverer();
        S2CellUnion covering = coverer.GetCovering(region);

        Assert.Equal(1, covering.Size());
        foreach (S2CellId id in covering)
        {
            Assert.True(id.IsLeaf());
        }
    }
        public void checkCovering(
            S2RegionCoverer coverer, IS2Region region, List <S2CellId> covering, bool interior)
        {
            // Keep track of how many cells have the same coverer.min_level() ancestor.
            IDictionary <S2CellId, int> minLevelCells = new Dictionary <S2CellId, int>();

            for (var i = 0; i < covering.Count; ++i)
            {
                var level = covering[i].Level;
                assertTrue(level >= coverer.MinLevel);
                assertTrue(level <= coverer.MaxLevel);
                assertEquals((level - coverer.MinLevel) % coverer.LevelMod, 0);
                var key = covering[i].ParentForLevel(coverer.MinLevel);
                if (!minLevelCells.ContainsKey(key))
                {
                    minLevelCells.Add(key, 1);
                }
                else
                {
                    minLevelCells[key] = minLevelCells[key] + 1;
                }
            }
            if (covering.Count > coverer.MaxCells)
            {
                // If the covering has more than the requested number of cells, then check
                // that the cell count cannot be reduced by using the parent of some cell.
                foreach (var i in minLevelCells.Values)
                {
                    assertEquals(i, 1);
                }
            }

            if (interior)
            {
                for (var i = 0; i < covering.Count; ++i)
                {
                    assertTrue(region.Contains(new S2Cell(covering[i])));
                }
            }
            else
            {
                var cellUnion = new S2CellUnion();
                cellUnion.InitFromCellIds(covering);
                checkCovering(region, cellUnion, true, new S2CellId());
            }
        }
예제 #15
0
    // Computes a set of initial candidates that cover the given region.
    private void GetInitialCandidates(List <S2CellId> result)
    {
        // Optimization: start with a small (usually 4 cell) covering of the
        // region's bounding cap.
        var tmp_coverer = new S2RegionCoverer();

        tmp_coverer.Options_.MaxCells = Math.Min(4, Options_.MaxCells);
        tmp_coverer.Options_.MaxLevel = (Options_.MaxLevel);
        var cells = new List <S2CellId>();

        tmp_coverer.GetFastCovering(region_, cells);
        AdjustCellLevels(cells);
        foreach (var cell_id in cells)
        {
            AddCandidate(NewCandidate(new S2Cell(cell_id)), result);
        }
    }
    public void Test_S2ShapeIndexBufferedRegion_FullAfterBuffering()
    {
        // Test a region that becomes the full polygon after buffering.
        var index   = MakeIndexOrDie("0:0 | 0:90 | 0:180 | 0:-90 | 90:0 | -90:0 # #");
        var radius  = new S1ChordAngle(S1Angle.FromDegrees(60));
        var region  = new S2ShapeIndexBufferedRegion(index, radius);
        var coverer = new S2RegionCoverer();

        coverer.Options_.MaxCells = 1000;
        S2CellUnion covering = coverer.GetCovering(region);

        Assert.Equal(6, covering.Size());
        foreach (S2CellId id in covering)
        {
            Assert.True(id.IsFace());
        }
    }
        public void checkCovering(
            S2RegionCoverer coverer, IS2Region region, List<S2CellId> covering, bool interior)
        {
            // Keep track of how many cells have the same coverer.min_level() ancestor.
            IDictionary<S2CellId, int> minLevelCells = new Dictionary<S2CellId, int>();
            for (var i = 0; i < covering.Count; ++i)
            {
                var level = covering[i].Level;
                assertTrue(level >= coverer.MinLevel);
                assertTrue(level <= coverer.MaxLevel);
                assertEquals((level - coverer.MinLevel)%coverer.LevelMod, 0);
                var key = covering[i].ParentForLevel(coverer.MinLevel);
                if (!minLevelCells.ContainsKey(key))
                {
                    minLevelCells.Add(key, 1);
                }
                else
                {
                    minLevelCells[key] = minLevelCells[key] + 1;
                }
            }
            if (covering.Count > coverer.MaxCells)
            {
                // If the covering has more than the requested number of cells, then check
                // that the cell count cannot be reduced by using the parent of some cell.
                foreach (var i in minLevelCells.Values)
                {
                    assertEquals(i, 1);
                }
            }

            if (interior)
            {
                for (var i = 0; i < covering.Count; ++i)
                {
                    assertTrue(region.Contains(new S2Cell(covering[i])));
                }
            }
            else
            {
                var cellUnion = new S2CellUnion();
                cellUnion.InitFromCellIds(covering);
                checkCovering(region, cellUnion, true, new S2CellId());
            }
        }
        public void testRandomCaps()
        {
            Console.WriteLine("TestRandomCaps");

            var kMaxLevel = S2CellId.MaxLevel;
            var coverer   = new S2RegionCoverer();

            for (var i = 0; i < 1000; ++i)
            {
                do
                {
                    coverer.MinLevel = random(kMaxLevel + 1);
                    coverer.MaxLevel = random(kMaxLevel + 1);
                } while (coverer.MinLevel > coverer.MaxLevel);
                coverer.MaxCells = skewed(10);
                coverer.LevelMod = 1 + random(3);
                var maxArea = Math.Min(
                    4 * S2.Pi, (3 * coverer.MaxCells + 1) * S2Cell.AverageArea(coverer.MinLevel));
                var cap      = getRandomCap(0.1 * S2Cell.AverageArea(kMaxLevel), maxArea);
                var covering = new List <S2CellId>();
                var interior = new List <S2CellId>();

                coverer.GetCovering(cap, covering);
                checkCovering(coverer, cap, covering, false);

                coverer.GetInteriorCovering(cap, interior);
                checkCovering(coverer, cap, interior, true);


                // Check that GetCovering is deterministic.
                var covering2 = new List <S2CellId>();
                coverer.GetCovering(cap, covering2);
                assertTrue(covering.SequenceEqual(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.
                var cells = new S2CellUnion();
                cells.InitFromCellIds(covering);
                var denormalized = new List <S2CellId>();
                cells.Denormalize(coverer.MinLevel, coverer.LevelMod, denormalized);
                checkCovering(coverer, cap, denormalized, false);
            }
        }
        public void testRandomCells()
        {
            Console.WriteLine("TestRandomCells");

            var coverer = new S2RegionCoverer();

            coverer.MaxCells = 1;

            // Test random cell ids at all levels.
            for (var i = 0; i < 10000; ++i)
            {
                var id       = getRandomCellId();
                var covering = new S2CellUnion();
                coverer.GetCovering(new S2Cell(id), covering.CellIds);
                assertEquals(covering.Count, 1);
                assertEquals(covering.CellId(0), id);
            }
        }
        public void testRandomCaps()
        {
            Console.WriteLine("TestRandomCaps");

            var kMaxLevel = S2CellId.MaxLevel;
            var coverer = new S2RegionCoverer();
            for (var i = 0; i < 1000; ++i)
            {
                do
                {
                    coverer.MinLevel = random(kMaxLevel + 1);
                    coverer.MaxLevel = random(kMaxLevel + 1);
                } while (coverer.MinLevel > coverer.MaxLevel);
                coverer.MaxCells = skewed(10);
                coverer.LevelMod = 1 + random(3);
                var maxArea = Math.Min(
                    4*S2.Pi, (3*coverer.MaxCells + 1)*S2Cell.AverageArea(coverer.MinLevel));
                var cap = getRandomCap(0.1*S2Cell.AverageArea(kMaxLevel), maxArea);
                var covering = new List<S2CellId>();
                var interior = new List<S2CellId>();

                coverer.GetCovering(cap, covering);
                checkCovering(coverer, cap, covering, false);

                coverer.GetInteriorCovering(cap, interior);
                checkCovering(coverer, cap, interior, true);


                // Check that GetCovering is deterministic.
                var covering2 = new List<S2CellId>();
                coverer.GetCovering(cap, covering2);
                assertTrue(covering.SequenceEqual(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.
                var cells = new S2CellUnion();
                cells.InitFromCellIds(covering);
                var denormalized = new List<S2CellId>();
                cells.Denormalize(coverer.MinLevel, coverer.LevelMod, denormalized);
                checkCovering(coverer, cap, denormalized, false);
            }
        }
        public void testSimpleCoverings()
        {
            Console.WriteLine("TestSimpleCoverings");

            var kMaxLevel = S2CellId.MaxLevel;
            var coverer   = new S2RegionCoverer();

            coverer.MaxCells = int.MaxValue;
            for (var i = 0; i < 1000; ++i)
            {
                var level = random(kMaxLevel + 1);
                coverer.MinLevel = level;
                coverer.MaxLevel = level;
                var maxArea  = Math.Min(4 * S2.Pi, 1000 * S2Cell.AverageArea(level));
                var cap      = getRandomCap(0.1 * S2Cell.AverageArea(kMaxLevel), maxArea);
                var covering = new List <S2CellId>();
                S2RegionCoverer.GetSimpleCovering(cap, cap.Axis, level, covering);
                checkCovering(coverer, cap, covering, false);
            }
        }
예제 #22
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);
            }
        }
        private IEnumerable <S2CellId> GetCurrentS2CellIds(GPSLatLong currentLatLong)
        {
            // Info on S2 Geometry - https://s2geometry.io/
            // Code taken from this video - https://www.youtube.com/watch?v=UZsf3bqmmKs  (6:26)
            // Min/Max Level and Max Cells taken from here - https://s2.sidewalklabs.com/regioncoverer/
            // Using Nuget S2Geometry vs 1.0.3 (https://www.nuget.org/packages/S2Geometry/)
            S2RegionCoverer rc = new S2RegionCoverer();

            rc.MaxCells = S2RegionCoverer.DefaultMaxCells;
            rc.MinLevel = rc.MaxLevel = 14;

            // var southwestLat = new GPSLatLong { Latitude = 47.013859, Longitude = -122.920682 };
            // var northeast = new GPSLatLong { Latitude = 47.033532, Longitude = -122.894687 };
            //
            // S2LatLng low = S2LatLng.FromDegrees(southwestLat.Latitude, southwestLat.Longitude);
            // S2LatLng high = S2LatLng.FromDegrees(northeast.Latitude, northeast.Longitude);
            //
            // S2LatLngRect latLngRect = new S2LatLngRect(low, high);
            // return rc.GetCovering(latLngRect);


            //// https://stackoverflow.com/questions/7477003/calculating-new-longitude-latitude-from-old-n-meters
            //// number of km per degree = ~111km (111.32 in google maps, but range varies
            //// between 110.567km at the equator and 111.699km at the poles)
            //// 1km in degree = 1 / 111.32km = 0.0089
            //// 1m in degree = 0.0089 / 1000 = 0.0000089
            double meters   = this.loadRadiusInMeters;
            double coef     = meters * 0.0000089;
            double new_lat  = /*currentLatLong.Latitude +*/ coef;
            double new_long = /*currentLatLong.Longitude +*/ coef / Math.Cos(currentLatLong.Latitude * (Math.PI / 180.0));

            S2LatLng center = S2LatLng.FromDegrees(currentLatLong.Latitude, currentLatLong.Longitude);
            S2LatLng size   = S2LatLng.FromDegrees(new_lat, new_long);

            return(rc.GetCovering(S2LatLngRect.FromCenterSize(center, size)));
        }
        private async Task <BootstrapTask> GetBootstrapTask()
        {
            ulong target;

            lock (_bootstrapLock)
            {
                target = _bootstrapCellIds.FirstOrDefault();
                if (target == default)
                {
                    return(null);
                }
                _bootstrapCellIds.Remove(target);
            }

            var cell   = new S2Cell(new S2CellId(target));
            var latlng = new S2LatLng(cell.Center);

            double radius;

            if (latlng.LatDegrees <= 39)
            {
                radius = 715;
            }
            else if (latlng.LatDegrees >= 69)
            {
                radius = 330;
            }
            else
            {
                radius = (-13 * latlng.LatDegrees) + 1225;
            }

            var radians = radius / 6378137;
            var centerNormalizedPoint = latlng.Normalized.ToPoint();
            var circle  = S2Cap.FromAxisHeight(centerNormalizedPoint, (radians * radians) / 2);
            var coverer = new S2RegionCoverer
            {
                MinLevel = 15,
                MaxLevel = 15,
                MaxCells = 100
            };
            var nearbyCellIds = coverer.GetCovering(circle).Select(x => x.Id);

            lock (_bootstrapCellIds)
            {
                _bootstrapCellIds.RemoveAll(cell => nearbyCellIds.Contains(cell));
            }
            if (_bootstrapCellIds.Count == 0)
            {
                await Bootstrap().ConfigureAwait(false);

                if (_bootstrapCellIds.Count == 0)
                {
                    await Update().ConfigureAwait(false);
                }
            }
            return(new BootstrapTask
            {
                Action = ActionType.ScanRaid,
                Area = Name,
                Latitude = latlng.LatDegrees,
                Longitude = latlng.LngDegrees,
                MinimumLevel = MinimumLevel,
                MaximumLevel = MaximumLevel,
            });
        }
예제 #25
0
        public List <Guid> Search(double lon, double lat, int radius)
        {
            lock (locker)
            {
                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);

                        var qres = rtree.Search(new Interval <UserList>(new UserList()
                        {
                            s2CellId = begin
                        }, new UserList()
                        {
                            s2CellId = end
                        }));


                        foreach (var item in qres)
                        {
                            res.AddRange(item.Start.list);
                        }
                    }
                    else
                    {
                        var qres = rtree.Search(new UserList()
                        {
                            s2CellId = sell
                        });
                        if (qres.Count > 0)
                        {
                            foreach (var r in qres)
                            {
                                res.AddRange(r.Start.list);
                            }
                        }
                    }
                }
                return(res);
            }
        }
        public void testSimpleCoverings()
        {
            Console.WriteLine("TestSimpleCoverings");

            var kMaxLevel = S2CellId.MaxLevel;
            var coverer = new S2RegionCoverer();
            coverer.MaxCells = int.MaxValue;
            for (var i = 0; i < 1000; ++i)
            {
                var level = random(kMaxLevel + 1);
                coverer.MinLevel = level;
                coverer.MaxLevel = level;
                var maxArea = Math.Min(4*S2.Pi, 1000*S2Cell.AverageArea(level));
                var cap = getRandomCap(0.1*S2Cell.AverageArea(kMaxLevel), maxArea);
                var covering = new List<S2CellId>();
                S2RegionCoverer.GetSimpleCovering(cap, cap.Axis, level, covering);
                checkCovering(coverer, cap, covering, false);
            }
        }
예제 #27
0
    private void TestRandomCaps(S2RegionTermIndexer.Options options, QueryType query_type)
    {
        // This function creates an index consisting either of points (if
        // options.index_contains_points_only() is true) or S2Caps of random size.
        // It then executes queries consisting of points (if query_type == POINT)
        // or S2Caps of random size (if query_type == CAP).
        var indexer = new S2RegionTermIndexer(options);
        var coverer = new S2RegionCoverer(options);
        var caps = new List <S2Cap>();
        var coverings = new List <S2CellUnion>();
        var index = new Dictionary <string, List <int> >();
        int index_terms = 0, query_terms = 0;

        for (int i = 0; i < iters; ++i)
        {
            // Choose the region to be indexed: either a single point or a cap
            // of random size (up to a full sphere).
            S2Cap         cap;
            List <string> terms;
            if (options.IndexContainsPointsOnly)
            {
                cap   = S2Cap.FromPoint(S2Testing.RandomPoint());
                terms = indexer.GetIndexTerms(cap.Center, "");
            }
            else
            {
                cap = S2Testing.GetRandomCap(
                    0.3 * S2Cell.AverageArea(options.MaxLevel),
                    4.0 * S2Cell.AverageArea(options.MinLevel));
                terms = indexer.GetIndexTerms(cap, "");
            }
            caps.Add(cap);
            coverings.Add(coverer.GetCovering(cap));
            foreach (var term in terms)
            {
                if (!index.ContainsKey(term))
                {
                    index.Add(term, new List <int>());
                }

                index[term].Add(i);
            }
            index_terms += terms.Count;
        }
        for (int i = 0; i < iters; ++i)
        {
            // Choose the region to be queried: either a random point or a cap of
            // random size.
            S2Cap         cap;
            List <string> terms;
            if (query_type == QueryType.CAP)
            {
                cap   = S2Cap.FromPoint(S2Testing.RandomPoint());
                terms = indexer.GetQueryTerms(cap.Center, "");
            }
            else
            {
                cap = S2Testing.GetRandomCap(
                    0.3 * S2Cell.AverageArea(options.MaxLevel),
                    4.0 * S2Cell.AverageArea(options.MinLevel));
                terms = indexer.GetQueryTerms(cap, "");
            }
            // Compute the expected results of the S2Cell query by brute force.
            S2CellUnion covering = coverer.GetCovering(cap);
            var         expected = new List <int>();
            var         actual   = new List <int>();
            for (int j = 0; j < caps.Count; ++j)
            {
                if (covering.Intersects(coverings[j]))
                {
                    expected.Add(j);
                }
            }
            foreach (var term in terms)
            {
                actual.AddRange(index[term]);
            }
            Assert.Equal(expected, actual);
            query_terms += terms.Count;
        }
        _logger.WriteLine($"Index terms/doc: {((double)index_terms) / iters:2f},  Query terms/doc: {((double)query_terms) / iters:2f}");
    }
        public void testRandomCells()
        {
            Console.WriteLine("TestRandomCells");

            var coverer = new S2RegionCoverer();
            coverer.MaxCells = 1;

            // Test random cell ids at all levels.
            for (var i = 0; i < 10000; ++i)
            {
                var id = getRandomCellId();
                var covering = new S2CellUnion();
                coverer.GetCovering(new S2Cell(id), covering.CellIds);
                assertEquals(covering.Count, 1);
                assertEquals(covering.CellId(0), id);
            }
        }