Exemplo n.º 1
0
        public void Test_S2CellUnion_FromBeginEnd()
        {
            // Since FromMinMax() is implemented in terms of FromBeginEnd(), we
            // focus on test cases that generate an empty range.
            S2CellId initial_id = S2CellId.FromFace(3);

            // Test an empty range before the minimum S2CellId.
            S2CellUnion cell_union = new(new List <S2CellId> {
                initial_id
            });
            S2CellId id_begin      = S2CellId.Begin(S2.kMaxCellLevel);

            cell_union.InitFromBeginEnd(id_begin, id_begin);
            Assert.True(cell_union.IsEmpty());

            // Test an empty range after the maximum S2CellId.
            cell_union = new S2CellUnion(new List <S2CellId> {
                initial_id
            });
            S2CellId id_end = S2CellId.End(S2.kMaxCellLevel);

            cell_union.InitFromBeginEnd(id_end, id_end);
            Assert.True(cell_union.IsEmpty());

            // Test the full sphere.
            cell_union = S2CellUnion.FromBeginEnd(id_begin, id_end);
            Assert.Equal(6, cell_union.Size());
            foreach (S2CellId id in cell_union)
            {
                Assert.True(id.IsFace());
            }
        }
Exemplo n.º 2
0
        public static S2CellUnion FindCellIds(S2LatLngRect latLngRect)
        {
            var queue = new ConcurrentQueue <S2CellId>();


            var cellIds = new List <S2CellId>();

            for (var c = S2CellId.Begin(0); !c.Equals(S2CellId.End(0)); c = c.Next)
            {
                if (ContainsGeodataToFind(c, latLngRect))
                {
                    queue.Enqueue(c);
                }
            }

            ProcessQueue(queue, cellIds, latLngRect);
            Debug.Assert(queue.Count == 0);

            queue = null;

            if (cellIds.Count > 0)
            {
                var cellUnion = new S2CellUnion();
                cellUnion.InitFromCellIds(cellIds); // This normalize the cells.
                // cellUnion.initRawCellIds(cellIds); // This does not normalize the cells.
                cellIds = null;

                return(cellUnion);
            }

            return(null);
        }
        public void testContinuity()
        {
            Trace.WriteLine("TestContinuity");
            // Make sure that sequentially increasing cell ids form a continuous
            // path over the surface of the sphere, i.e. there are no
            // discontinuous jumps from one region to another.

            var maxDist = S2Projections.MaxEdge.GetValue(MAX_WALK_LEVEL);
            var end     = S2CellId.End(MAX_WALK_LEVEL);
            var id      = S2CellId.Begin(MAX_WALK_LEVEL);

            for (; !id.Equals(end); id = id.Next)
            {
                Assert.True(id.ToPointRaw().Angle(id.NextWithWrap.ToPointRaw()) <= maxDist);

                // Check that the ToPointRaw() returns the center of each cell
                // in (s,t) coordinates.
                var p    = id.ToPointRaw();
                var face = S2Projections.XyzToFace(p);
                var uv   = S2Projections.ValidFaceXyzToUv(face, p);
                assertDoubleNear(Math.IEEERemainder(
                                     S2Projections.UvToSt(uv.X), 1.0 / (1 << MAX_WALK_LEVEL)), 0);
                assertDoubleNear(Math.IEEERemainder(
                                     S2Projections.UvToSt(uv.Y), 1.0 / (1 << MAX_WALK_LEVEL)), 0);
            }
        }
Exemplo n.º 4
0
        public void Test_S2CellId_Advance()
        {
            S2CellId id = S2CellId.FromFacePosLevel(3, 0x12345678,
                                                    S2.kMaxCellLevel - 4);

            // Check basic properties of advance().
            Assert.Equal(S2CellId.End(0), S2CellId.Begin(0).Advance(7));
            Assert.Equal(S2CellId.End(0), S2CellId.Begin(0).Advance(12));
            Assert.Equal(S2CellId.Begin(0), S2CellId.End(0).Advance(-7));
            Assert.Equal(S2CellId.Begin(0), S2CellId.End(0).Advance(-12000000));
            int num_level_5_cells = 6 << (2 * 5);

            Assert.Equal(S2CellId.End(5).Advance(500 - num_level_5_cells),
                         S2CellId.Begin(5).Advance(500));
            Assert.Equal(id.Next().ChildBegin(S2.kMaxCellLevel),
                         id.ChildBegin(S2.kMaxCellLevel).Advance(256));
            Assert.Equal(S2CellId.FromFacePosLevel(5, 0, S2.kMaxCellLevel),
                         S2CellId.FromFacePosLevel(1, 0, S2.kMaxCellLevel)
                         .Advance((long)(4UL << (2 * S2.kMaxCellLevel))));

            // Check basic properties of advance_wrap().
            Assert.Equal(S2CellId.FromFace(1), S2CellId.Begin(0).AdvanceWrap(7));
            Assert.Equal(S2CellId.Begin(0), S2CellId.Begin(0).AdvanceWrap(12));
            Assert.Equal(S2CellId.FromFace(4), S2CellId.FromFace(5).AdvanceWrap(-7));
            Assert.Equal(S2CellId.Begin(0), S2CellId.Begin(0).AdvanceWrap(-12000000));
            Assert.Equal(S2CellId.Begin(5).AdvanceWrap(6644),
                         S2CellId.Begin(5).AdvanceWrap(-11788));
            Assert.Equal(id.Next().ChildBegin(S2.kMaxCellLevel),
                         id.ChildBegin(S2.kMaxCellLevel).AdvanceWrap(256));
            Assert.Equal(S2CellId.FromFacePosLevel(1, 0, S2.kMaxCellLevel),
                         S2CellId.FromFacePosLevel(5, 0, S2.kMaxCellLevel)
                         .AdvanceWrap((long)(2UL << (2 * S2.kMaxCellLevel))));
        }
Exemplo n.º 5
0
 public void Run()
 {
     for (S2CellId id = S2CellId.Begin(0);
          id != S2CellId.End(0); id = id.Next())
     {
         TestCell(new S2Cell(id));
     }
 }
        public void S2CellIdTestBasic()
        {
            Trace.WriteLine("TestBasic");
            // Check default constructor.
            var id = new S2CellId();

            //JavaAssert.Equal(id.id(), 0);
            //Assert.True(!id.isValid());

            // Check basic accessor methods.
            id = S2CellId.FromFacePosLevel(3, 0x12345678, S2CellId.MaxLevel - 4);
            //Assert.True(id.isValid());
            //JavaAssert.Equal(id.face(), 3);
            // JavaAssert.Equal(id.pos(), 0x12345700);
            //JavaAssert.Equal(id.level(), S2CellId.MAX_LEVEL - 4);
            //Assert.True(!id.isLeaf());

            //// Check face definitions
            //JavaAssert.Equal(getCellId(0, 0).face(), 0);
            //JavaAssert.Equal(getCellId(0, 90).face(), 1);
            //JavaAssert.Equal(getCellId(90, 0).face(), 2);
            //JavaAssert.Equal(getCellId(0, 180).face(), 3);
            //JavaAssert.Equal(getCellId(0, -90).face(), 4);
            //JavaAssert.Equal(getCellId(-90, 0).face(), 5);

            //// Check parent/child relationships.
            //JavaAssert.Equal(id.childBegin(id.level() + 2).pos(), 0x12345610);
            //JavaAssert.Equal(id.childBegin().pos(), 0x12345640);
            //JavaAssert.Equal(id.parent().pos(), 0x12345400);
            //JavaAssert.Equal(id.parent(id.level() - 2).pos(), 0x12345000);

            //// Check ordering of children relative to parents.
            //Assert.True(id.childBegin().lessThan(id));
            //var childEnd = id.childEnd();
            //var childId = childEnd.id();
            //var id1 = id.id();

            //Assert.True(id.childEnd().greaterThan(id));
            //JavaAssert.Equal(id.childBegin().next().next().next().next(), id.childEnd());
            //JavaAssert.Equal(id.childBegin(S2CellId.MAX_LEVEL), id.rangeMin());
            //JavaAssert.Equal(id.childEnd(S2CellId.MAX_LEVEL), id.rangeMax().next());

            // Check wrapping from beginning of Hilbert curve to end and vice versa.
            // JavaAssert.Equal(S2CellId.begin(0).prevWrap(), S2CellId.end(0).prev());

            JavaAssert.Equal(S2CellId.Begin(S2CellId.MaxLevel).PreviousWithWrap,
                             S2CellId.FromFacePosLevel(5, ~0UL >> S2CellId.FaceBits, S2CellId.MaxLevel));

            JavaAssert.Equal(S2CellId.End(4).Previous.NextWithWrap, S2CellId.Begin(4));
            JavaAssert.Equal(S2CellId.End(S2CellId.MaxLevel).Previous.NextWithWrap,
                             S2CellId.FromFacePosLevel(0, 0, S2CellId.MaxLevel));

            // Check that cells are represented by the position of their center
            // along the Hilbert curve.
            JavaAssert.Equal(id.RangeMin.Id + id.RangeMax.Id, 2 * id.Id);
        }
Exemplo n.º 7
0
    // Constructs the index.  This method may only be called once.  No iterators
    // may be used until the index is built.
    public void Build()
    {
        // To build the cell tree and leaf cell ranges, we maintain a stack of
        // (cell_id, label) pairs that contain the current leaf cell.  This class
        // represents an instruction to push or pop a (cell_id, label) pair.
        //
        // If label >= 0, the (cell_id, label) pair is pushed on the stack.
        // If cell_id == S2CellId.Sentinel(), a pair is popped from the stack.
        // Otherwise the stack is unchanged but a RangeNode is still emitted.


        var deltas = new List <DeltaBuild>(2 * cell_tree_.Count + 2);

        // Create two deltas for each (cell_id, label) pair: one to add the pair to
        // the stack (at the start of its leaf cell range), and one to remove it from
        // the stack (at the end of its leaf cell range).
        foreach (var node in cell_tree_)
        {
            deltas.Add(new DeltaBuild(node.CellId.RangeMin(), node.CellId, node.Label));
            deltas.Add(new DeltaBuild(node.CellId.RangeMax().Next(), S2CellId.Sentinel, -1));
        }
        // We also create two special deltas to ensure that a RangeNode is emitted at
        // the beginning and end of the S2CellId range.
        deltas.Add(new DeltaBuild(S2CellId.Begin(S2.kMaxCellLevel), S2CellId.None, -1));
        deltas.Add(new DeltaBuild(S2CellId.End(S2.kMaxCellLevel), S2CellId.None, -1));
        deltas.Sort();

        // Now walk through the deltas to build the leaf cell ranges and cell tree
        // (which is essentially a permanent form of the "stack" described above).
        cell_tree_.Clear();
        range_nodes_.Capacity = deltas.Count;
        int contents = -1;

        for (int i = 0; i < deltas.Count;)
        {
            var start_id = deltas[i].StartId;
            // Process all the deltas associated with the current start_id.
            for (; i < deltas.Count && deltas[i].StartId == start_id; ++i)
            {
                if (deltas[i].Label >= 0)
                {
                    cell_tree_.Add(new CellNode(deltas[i].CellId, deltas[i].Label, contents));
                    contents = cell_tree_.Count - 1;
                }
                else if (deltas[i].CellId == S2CellId.Sentinel)
                {
                    contents = cell_tree_[contents].Parent;
                }
            }
            range_nodes_.Add(new RangeNode(start_id, contents));
        }
    }
        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);
                }
            }
        }
Exemplo n.º 9
0
        public void Test_S2CellId_DistanceFromBegin()
        {
            Assert.Equal(6, S2CellId.End(0).DistanceFromBegin());
            Assert.Equal(6 * (1L << (2 * S2.kMaxCellLevel)),
                         S2CellId.End(S2.kMaxCellLevel).DistanceFromBegin());

            Assert.Equal(0, S2CellId.Begin(0).DistanceFromBegin());
            Assert.Equal(0, S2CellId.Begin(S2.kMaxCellLevel).DistanceFromBegin());

            S2CellId id = S2CellId.FromFacePosLevel(3, 0x12345678, S2.kMaxCellLevel - 4);

            Assert.Equal(id, S2CellId.Begin(id.Level()).Advance(id.DistanceFromBegin()));
        }
Exemplo n.º 10
0
 public void Test_EncodedS2PointVectorTest_LastTwoPointsAtAllLevels()
 {
     // Test encoding the last two S2CellIds at each level.
     for (int level = 0; level <= S2.kMaxCellLevel; ++level)
     {
         _logger.WriteLine("Level = " + level);
         S2CellId id = S2CellId.End(level).Prev();
         // Notice that this costs only 4 bits more than encoding the last S2CellId
         // by itself (see LastAtAllLevels).  This is because encoding a block of
         // size 1 uses 8-bit deltas (which reduces the size of "base" by 4 bits),
         // while this test uses two 4-bit deltas.
         int expected_size = 6 + (level + 2) / 4;
         TestEncodedS2PointVector(new S2Point[] { id.ToPoint(), id.Prev().ToPoint() },
                                  CodingHint.COMPACT, expected_size);
     }
 }
Exemplo n.º 11
0
 public void Test_EncodedS2PointVectorTest_LastAtAllLevels()
 {
     // Test encoding the last S2CellId at each level.  It turns out that such
     // S2CellIds have the largest possible face and ti values, and the minimum
     // possible si value at that level.  Such S2CellIds can be encoded in 6 to 13
     // bytes depending on the level.
     for (int level = 0; level <= S2.kMaxCellLevel; ++level)
     {
         _logger.WriteLine("Level = " + level);
         // Note that 8 bit deltas are used to encode blocks of size 1, which
         // reduces the size of "base" from ((level + 2) / 4) to (level / 4) bytes.
         int expected_size = 6 + level / 4;
         TestEncodedS2PointVector(new S2Point[] { S2CellId.End(level).Prev().ToPoint() },
                                  CodingHint.COMPACT, expected_size);
     }
 }
Exemplo n.º 12
0
    public void Test_EncodedS2CellIdVector_LowerBoundLimits()
    {
        // Test seeking before the beginning and past the end of the vector.
        var     first    = S2CellId.Begin(S2.kMaxCellLevel);
        var     last     = S2CellId.End(S2.kMaxCellLevel).Prev();
        Encoder encoder  = new();
        var     cell_ids = MakeEncodedS2CellIdVector(
            new() { first, last }, encoder);

        Assert.Equal(0, cell_ids.LowerBound(S2CellId.None));
        Assert.Equal(0, cell_ids.LowerBound(first));
        Assert.Equal(1, cell_ids.LowerBound(first.Next()));
        Assert.Equal(1, cell_ids.LowerBound(last.Prev()));
        Assert.Equal(1, cell_ids.LowerBound(last));
        Assert.Equal(2, cell_ids.LowerBound(last.Next()));
        Assert.Equal(2, cell_ids.LowerBound(S2CellId.Sentinel));
    }
Exemplo n.º 13
0
    public void Test_EncodedS2PointVectorTest_SixtyFourBitOffset()
    {
        // Tests a case where a 64-bit block offset is needed.
        //
        // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes)
        // Block 0: header (1 byte), 8 deltas (8 bytes)
        // Block 1: header (1 byte), offset (8 bytes), 2 deltas (1 byte)
        const int level  = S2.kMaxCellLevel;
        var       points = new S2Point[kBlockSize]
                           .Fill(S2CellId.Begin(level).ToPoint());

        points = new List <S2Point>(points)
        {
            S2CellId.End(level).Prev().ToPoint(),
            S2CellId.End(level).Prev().Prev().ToPoint(),
        }.ToArray();
        TestEncodedS2PointVector(points, CodingHint.COMPACT, 16 + kBlockSize / 2);
    }
Exemplo n.º 14
0
        public void Test_S2CellId_Wrapping()
        {
            // Check wrapping from beginning of Hilbert curve to end and vice versa.
            Assert.Equal(S2CellId.End(0).Prev(), S2CellId.Begin(0).PrevWrap());

            Assert.Equal(S2CellId.FromFacePosLevel(
                             5, ~0UL >> S2CellId.kFaceBits, S2.kMaxCellLevel),
                         S2CellId.Begin(S2.kMaxCellLevel).PrevWrap());
            Assert.Equal(S2CellId.FromFacePosLevel(
                             5, ~0UL >> S2CellId.kFaceBits, S2.kMaxCellLevel),
                         S2CellId.Begin(S2.kMaxCellLevel).AdvanceWrap(-1));

            Assert.Equal(S2CellId.Begin(4), S2CellId.End(4).Prev().NextWrap());
            Assert.Equal(S2CellId.Begin(4), S2CellId.End(4).Advance(-1).AdvanceWrap(1));

            Assert.Equal(S2CellId.FromFacePosLevel(0, 0, S2.kMaxCellLevel),
                         S2CellId.End(S2.kMaxCellLevel).Prev().NextWrap());
            Assert.Equal(S2CellId.FromFacePosLevel(0, 0, S2.kMaxCellLevel),
                         S2CellId.End(S2.kMaxCellLevel).Advance(-1).AdvanceWrap(1));
        }
Exemplo n.º 15
0
 public void Test_EncodedS2PointVectorTest_ManyDuplicatePointsAtAllLevels()
 {
     // Test encoding 32 copies of the last S2CellId at each level.  This uses
     // between 27 and 38 bytes depending on the level.  (Note that the encoding
     // can use less than 1 byte per point in this situation.)
     for (int level = 0; level <= S2.kMaxCellLevel; ++level)
     {
         _logger.WriteLine("Level = " + level);
         S2CellId id = S2CellId.End(level).Prev();
         // Encoding: header (2 bytes), base ((level + 2) / 4 bytes), block count
         // (1 byte), block offsets (2 bytes), block headers (2 bytes), 32 deltas
         // (16 bytes).  At level 30 the encoding size goes up by 1 byte because
         // we can't encode an 8 byte "base" value, so instead this case uses a
         // base of 7 bytes plus a one-byte offset in each of the 2 blocks.
         int expected_size = 23 + (level + 2) / 4;
         if (level == 30)
         {
             expected_size += 1;
         }
         var points = new S2Point[32].Fill(id.ToPoint());
         TestEncodedS2PointVector(points, CodingHint.COMPACT, expected_size);
     }
 }
Exemplo n.º 16
0
        public void Test_S2CellId_Continuity()
        {
            // Make sure that sequentially increasing cell ids form a continuous
            // path over the surface of the sphere, i.e. there are no
            // discontinuous jumps from one region to another.

            double   max_dist = S2.kMaxEdge.GetValue(kMaxWalkLevel);
            S2CellId end      = S2CellId.End(kMaxWalkLevel);
            S2CellId id       = S2CellId.Begin(kMaxWalkLevel);

            for (; id != end; id = id.Next())
            {
                Assert.True(id.ToPointRaw().Angle(id.NextWrap().ToPointRaw()) <= max_dist);
                Assert.Equal(id.NextWrap(), id.AdvanceWrap(1));
                Assert.Equal(id, id.NextWrap().AdvanceWrap(-1));

                // Check that the ToPointRaw() returns the center of each cell
                // in (s,t) coordinates.
                S2.XYZtoFaceUV(id.ToPointRaw(), out var u, out var v);
                Assert2.Near(Math.IEEERemainder(S2.UVtoST(u), 0.5 * kCellSize), 0.0, S2.DoubleError);
                Assert2.Near(Math.IEEERemainder(S2.UVtoST(v), 0.5 * kCellSize), 0.0, S2.DoubleError);
            }
        }