Exemplo n.º 1
0
        public void Test_S2PaddedCell_GetEntryExitVertices()
        {
            int kIters = 1000;

            for (int iter = 0; iter < kIters; ++iter)
            {
                S2CellId id = S2Testing.GetRandomCellId();
                // Check that entry/exit vertices do not depend on padding.
                Assert.Equal(new S2PaddedCell(id, 0).GetEntryVertex(),
                             new S2PaddedCell(id, 0.5).GetEntryVertex());
                Assert.Equal(new S2PaddedCell(id, 0).GetExitVertex(),
                             new S2PaddedCell(id, 0.5).GetExitVertex());

                // Check that the exit vertex of one cell is the same as the entry vertex
                // of the immediately following cell.  (This also tests wrapping from the
                // end to the start of the S2CellId curve with high probability.)
                Assert.Equal(new S2PaddedCell(id, 0).GetExitVertex(),
                             new S2PaddedCell(id.NextWrap(), 0).GetEntryVertex());

                // Check that the entry vertex of a cell is the same as the entry vertex
                // of its first child, and similarly for the exit vertex.
                if (!id.IsLeaf())
                {
                    Assert.Equal(new S2PaddedCell(id, 0).GetEntryVertex(),
                                 new S2PaddedCell(id.Child(0), 0).GetEntryVertex());
                    Assert.Equal(new S2PaddedCell(id, 0).GetExitVertex(),
                                 new S2PaddedCell(id.Child(3), 0).GetExitVertex());
                }
            }
        }
Exemplo n.º 2
0
        public void Test_S2CellUnion_FromMinMax()
        {
            // Check the very first leaf cell and face cell.
            S2CellId face1_id = S2CellId.FromFace(0);

            TestFromMinMax(face1_id.RangeMin(), face1_id.RangeMin());
            TestFromMinMax(face1_id.RangeMin(), face1_id.RangeMax());

            // Check the very last leaf cell and face cell.
            S2CellId face5_id = S2CellId.FromFace(5);

            TestFromMinMax(face5_id.RangeMin(), face5_id.RangeMax());
            TestFromMinMax(face5_id.RangeMax(), face5_id.RangeMax());

            // Check random ranges of leaf cells.
            for (int iter = 0; iter < 100; ++iter)
            {
                S2CellId x = S2Testing.GetRandomCellId(S2.kMaxCellLevel);
                S2CellId y = S2Testing.GetRandomCellId(S2.kMaxCellLevel);
                if (x > y)
                {
                    var tmp = x; x = y; y = tmp;
                }
                TestFromMinMax(x, y);
            }
        }
Exemplo n.º 3
0
 public void Test_GetCrossingCandidates_DegenerateEdgeOnCellVertexIsItsOwnCandidate()
 {
     for (int i = 0; i < 100; ++i)
     {
         List <(S2Point, S2Point)> edges = new();
         S2Cell cell = new(S2Testing.GetRandomCellId());
         edges.Add((cell.Vertex(0), cell.Vertex(0)));
         TestAllCrossings(edges);
     }
 }
Exemplo n.º 4
0
        public void Test_S2CellId_ExpandedByDistanceUV()
        {
            const double max_dist_degrees = 10;

            for (var iter = 0; iter < 100; ++iter)
            {
                S2CellId id           = S2Testing.GetRandomCellId();
                double   dist_degrees = S2Testing.Random.UniformDouble(-max_dist_degrees, max_dist_degrees);
                TestExpandedByDistanceUV(id, S1Angle.FromDegrees(dist_degrees));
            }
        }
Exemplo n.º 5
0
        public void Test_XYZToFaceSiTi()
        {
            // Check the conversion of random cells to center points and back.
            for (int level = 0; level <= S2.kMaxCellLevel; ++level)
            {
                for (int i = 0; i < 1000; ++i)
                {
                    S2CellId id           = S2Testing.GetRandomCellId(level);
                    int      actual_level = S2.XYZtoFaceSiTi(id.ToPoint(), out var face, out var si, out var ti);
                    Assert.Equal(level, actual_level);
                    S2CellId actual_id =
                        S2CellId.FromFaceIJ(face, (int)(si / 2), (int)(ti / 2)).Parent(level);
                    Assert.Equal(id, actual_id);

                    // Now test a point near the cell center but not equal to it.
                    S2Point p_moved = id.ToPoint() + new S2Point(1e-13, 1e-13, 1e-13);
                    actual_level = S2.XYZtoFaceSiTi(p_moved, out var face_moved, out var si_moved, out var ti_moved);
                    Assert.Equal(-1, actual_level);
                    Assert.Equal(face, face_moved);
                    Assert.Equal(si, si_moved);
                    Assert.Equal(ti, ti_moved);

                    // Finally, test some random (si,ti) values that may be at different
                    // levels, or not at a valid level at all (for example, si == 0).
                    int  face_random = S2Testing.Random.Uniform(S2CellId.kNumFaces);
                    uint si_random, ti_random;
                    uint mask = ~0U << (S2.kMaxCellLevel - level);
                    do
                    {
                        si_random = S2Testing.Random.Rand32() & mask;
                        ti_random = S2Testing.Random.Rand32() & mask;
                    } while (si_random > S2.kMaxSiTi || ti_random > S2.kMaxSiTi);
                    S2Point p_random = S2.FaceSiTitoXYZ(face_random, si_random, ti_random);
                    actual_level = S2.XYZtoFaceSiTi(p_random, out face, out si, out ti);
                    if (face != face_random)
                    {
                        // The chosen point is on the edge of a top-level face cell.
                        Assert.Equal(-1, actual_level);
                        Assert.True(si == 0 || si == S2.kMaxSiTi ||
                                    ti == 0 || ti == S2.kMaxSiTi);
                    }
                    else
                    {
                        Assert.Equal(si_random, si);
                        Assert.Equal(ti_random, ti);
                        if (actual_level >= 0)
                        {
                            Assert.Equal(p_random, S2CellId.FromFaceIJ(face, (int)(si / 2), (int)(ti / 2)).Parent(actual_level).ToPoint());
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
 public void Test_S2CellId_Inverses()
 {
     // Check the conversion of random leaf cells to S2LatLngs and back.
     for (int i = 0; i < 200000; ++i)
     {
         S2CellId id = S2Testing.GetRandomCellId(S2.kMaxCellLevel);
         Assert.True(id.IsLeaf());
         Assert.Equal(S2.kMaxCellLevel, id.Level());
         S2LatLng center = id.ToLatLng();
         Assert.Equal(id.Id, new S2CellId(center).Id);
     }
 }
    public void Test_GetReferencePoint_PartiallyDegenerateLoops()
    {
        for (var iter = 0; iter < 100; ++iter)
        {
            // First we construct a long convoluted edge chain that follows the
            // S2CellId Hilbert curve.  At some random point along the curve, we
            // insert a small triangular loop.
            List <List <S2Point> > loops = new(1) { new() };
            var loop         = loops[0];
            int num_vertices = 100;
            var start        = S2Testing.GetRandomCellId(S2.kMaxCellLevel - 1);
            var end          = start.AdvanceWrap(num_vertices);
            var loop_cellid  = start.AdvanceWrap(
                S2Testing.Random.Uniform(num_vertices - 2) + 1);
            var triangle = new List <S2Point>();
            for (var cellid = start; cellid != end; cellid = cellid.NextWrap())
            {
                if (cellid == loop_cellid)
                {
                    // Insert a small triangular loop.  We save the loop so that we can
                    // test whether it contains the origin later.
                    triangle.Add(cellid.Child(0).ToPoint());
                    triangle.Add(cellid.Child(1).ToPoint());
                    triangle.Add(cellid.Child(2).ToPoint());
                    loop.AddRange(triangle);
                    loop.Add(cellid.Child(0).ToPoint());
                }
                else
                {
                    loop.Add(cellid.ToPoint());
                }
            }
            // Now we retrace our steps, except that we skip the three edges that form
            // the triangular loop above.
            for (S2CellId cellid = end; cellid != start; cellid = cellid.PrevWrap())
            {
                if (cellid == loop_cellid)
                {
                    loop.Add(cellid.Child(0).ToPoint());
                }
                else
                {
                    loop.Add(cellid.ToPoint());
                }
            }
            S2LaxPolygonShape shape         = new(loops);
            S2Loop            triangle_loop = new(triangle);
            var rp = shape.GetReferencePoint();
            Assert.Equal(triangle_loop.Contains(rp.Point), rp.Contained);
        }
    }
}
 public void Test_S2CellIdSnapFunction_SnapPoint()
 {
     for (int iter = 0; iter < 1000; ++iter)
     {
         for (int level = 0; level <= S2.kMaxCellLevel; ++level)
         {
             // This checks that points are snapped to the correct level, since
             // S2CellId centers at different levels are always different.
             S2CellIdSnapFunction f = new(level);
             S2Point p = S2Testing.GetRandomCellId(level).ToPoint();
             Assert.Equal(p, f.SnapPoint(p));
         }
     }
 }
Exemplo n.º 9
0
        public void Test_S2Cell_GetMaxDistanceToCell()
        {
            for (int i = 0; i < 1000; i++)
            {
                S2Cell   cell                = new(S2Testing.GetRandomCellId());
                S2Cell   test_cell           = new(S2Testing.GetRandomCellId());
                S2CellId antipodal_leaf_id   = new(-test_cell.Center());
                S2Cell   antipodal_test_cell = new(antipodal_leaf_id.Parent(test_cell.Level));

                S1ChordAngle dist_from_min = S1ChordAngle.Straight -
                                             cell.Distance(antipodal_test_cell);
                S1ChordAngle dist_from_max = cell.MaxDistance(test_cell);
                Assert2.Near(dist_from_min.Radians(), dist_from_max.Radians(), 1e-8);
            }
        }
Exemplo n.º 10
0
        public void Test_S2Cell_ConsistentWithS2CellIdFromPoint()
        {
            // Construct many points that are nearly on an S2Cell edge, and verify that
            // S2Cell(S2CellId(p)).Contains(p) is always true.

            for (int iter = 0; iter < 1000; ++iter)
            {
                S2Cell  cell = new(S2Testing.GetRandomCellId());
                int     i    = S2Testing.Random.Uniform(4);
                S2Point v1   = cell.Vertex(i);
                S2Point v2   = S2Testing.SamplePoint(
                    new S2Cap(cell.Vertex(i + 1), S1Angle.FromRadians(1e-15)));
                S2Point p = S2.Interpolate(S2Testing.Random.RandDouble(), v1, v2);
                Assert.True(new S2Cell(new S2CellId(p)).Contains(p));
            }
        }
Exemplo n.º 11
0
        public void Test_S2RegionCoverer_RandomCells()
        {
            S2RegionCoverer.Options options = new()
            {
                MaxCells = 1
            };
            S2RegionCoverer coverer = new(options);

            // Test random cell ids at all levels.
            for (int i = 0; i < 10000; ++i)
            {
                S2CellId id = S2Testing.GetRandomCellId();
                // var info = $"Iteration {i}, cell ID token {id.ToToken()}";
                var covering = coverer.GetCovering(new S2Cell(id)).CellIds;//.Release();
                Assert.Single(covering);
                Assert.Equal(id, covering[0]);
            }
        }
Exemplo n.º 12
0
        public void Test_S2PaddedCell_ShrinkToFit()
        {
            const int kIters = 1000;

            for (int iter = 0; iter < kIters; ++iter)
            {
                // Start with the desired result and work backwards.
                S2CellId result    = S2Testing.GetRandomCellId();
                R2Rect   result_uv = result.BoundUV();
                R2Point  size_uv   = result_uv.GetSize();

                // Find the biggest rectangle that fits in "result" after padding.
                // (These calculations ignore numerical errors.)
                double max_padding = 0.5 * Math.Min(size_uv[0], size_uv[1]);
                double padding     = max_padding * S2Testing.Random.RandDouble();
                R2Rect max_rect    = result_uv.Expanded(-padding);

                // Start with a random subset of the maximum rectangle.
                R2Point a = new(SampleInterval(max_rect[0]), SampleInterval(max_rect[1]));
                R2Point b = new(SampleInterval(max_rect[0]), SampleInterval(max_rect[1]));
                if (!result.IsLeaf())
                {
                    // If the result is not a leaf cell, we must ensure that no child of
                    // "result" also satisfies the conditions of ShrinkToFit().  We do this
                    // by ensuring that "rect" intersects at least two children of "result"
                    // (after padding).
                    int    axis   = S2Testing.Random.Uniform(2);
                    double center = result.CenterUV()[axis];

                    // Find the range of coordinates that are shared between child cells
                    // along that axis.
                    R1Interval shared = new(center - padding, center + padding);
                    double     mid    = SampleInterval(shared.Intersection(max_rect[axis]));
                    a = a.SetAxis(axis, SampleInterval(new R1Interval(max_rect[axis].Lo, mid)));
                    b = b.SetAxis(axis, SampleInterval(new R1Interval(mid, max_rect[axis].Hi)));
                }
                R2Rect rect = R2Rect.FromPointPair(a, b);

                // Choose an arbitrary ancestor as the S2PaddedCell.
                S2CellId initial_id = result.Parent(S2Testing.Random.Uniform(result.Level() + 1));
                Assert.Equal(result, new S2PaddedCell(initial_id, padding).ShrinkToFit(rect));
            }
        }
Exemplo n.º 13
0
        public void Test_S2ClosestCellQuery_EmptyTargetOptimized()
        {
            // Ensure that the optimized algorithm handles empty targets when a distance
            // limit is specified.
            S2CellIndex index = new();

            for (int i = 0; i < 1000; ++i)
            {
                index.Add(S2Testing.GetRandomCellId(), i);
            }
            index.Build();
            S2ClosestCellQuery query = new(index);

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

            S2ClosestCellQuery.ShapeIndexTarget target = new(target_index);
            Assert.Empty(query.FindClosestCells(target));
        }
Exemplo n.º 14
0
        public void Test_S2Cell_RectBoundIsLargeEnough()
        {
            // Construct many points that are nearly on an S2Cell edge, and verify that
            // whenever the cell contains a point P then its bound contains S2LatLng(P).

            for (int iter = 0; iter < 1000; /* advanced in loop below */)
            {
                S2Cell  cell = new(S2Testing.GetRandomCellId());
                int     i    = S2Testing.Random.Uniform(4);
                S2Point v1   = cell.Vertex(i);
                S2Point v2   = S2Testing.SamplePoint(
                    new S2Cap(cell.Vertex(i + 1), S1Angle.FromRadians(1e-15)));
                S2Point p = S2.Interpolate(S2Testing.Random.RandDouble(), v1, v2);
                if (new S2Loop(cell).Contains(p))
                {
                    Assert.True(cell.GetRectBound().Contains(new S2LatLng(p)));
                    ++iter;
                }
            }
        }
Exemplo n.º 15
0
 public void Test_S2Cell_GetDistanceToPoint()
 {
     S2Testing.Random.Reset(S2Testing.Random.RandomSeed);
     for (int iter = 0; iter < 1000; ++iter)
     {
         _logger.WriteLine($"Iteration {iter}");
         S2Cell  cell   = new(S2Testing.GetRandomCellId());
         S2Point target = S2Testing.RandomPoint();
         S1Angle expected_to_boundary =
             GetDistanceToPointBruteForce(cell, target).ToAngle();
         S1Angle expected_to_interior =
             cell.Contains(target) ? S1Angle.Zero : expected_to_boundary;
         S1Angle expected_max =
             GetMaxDistanceToPointBruteForce(cell, target).ToAngle();
         S1Angle actual_to_boundary = cell.BoundaryDistance(target).ToAngle();
         S1Angle actual_to_interior = cell.Distance(target).ToAngle();
         S1Angle actual_max         = cell.MaxDistance(target).ToAngle();
         // The error has a peak near Pi/2 for edge distance, and another peak near
         // Pi for vertex distance.
         Assert2.Near(expected_to_boundary.Radians,
                      actual_to_boundary.Radians, 1e-12);
         Assert2.Near(expected_to_interior.Radians,
                      actual_to_interior.Radians, 1e-12);
         Assert2.Near(expected_max.Radians,
                      actual_max.Radians, 1e-12);
         if (expected_to_boundary.Radians <= Math.PI / 3)
         {
             Assert2.Near(expected_to_boundary.Radians,
                          actual_to_boundary.Radians, S2.DoubleError);
             Assert2.Near(expected_to_interior.Radians,
                          actual_to_interior.Radians, S2.DoubleError);
         }
         if (expected_max.Radians <= Math.PI / 3)
         {
             Assert2.Near(expected_max.Radians, actual_max.Radians, S2.DoubleError);
         }
     }
 }
Exemplo n.º 16
0
        public void Test_S2Cell_CellVsLoopRectBound()
        {
            // This test verifies that the S2Cell and S2Loop bounds contain each other
            // to within their maximum errors.
            //
            // The S2Cell and S2Loop calculations for the latitude of a vertex can differ
            // by up to 2 * S2Constants.DoubleEpsilon, therefore the S2Cell bound should never exceed
            // the S2Loop bound by more than this (the reverse is not true, because the
            // S2Loop code sometimes thinks that the maximum occurs along an edge).
            // Similarly, the longitude bounds can differ by up to 4 * S2Constants.DoubleEpsilon since
            // the S2Cell bound has an error of 2 * S2Constants.DoubleEpsilon and then expands by this
            // amount, while the S2Loop bound does no expansion at all.

            for (int iter = 0; iter < 1000; ++iter)
            {
                S2Cell       cell       = new(S2Testing.GetRandomCellId());
                S2Loop       loop       = new(cell);
                S2LatLngRect cell_bound = cell.GetRectBound();
                S2LatLngRect loop_bound = loop.GetRectBound();
                Assert.True(loop_bound.Expanded(kCellError).Contains(cell_bound));
                Assert.True(cell_bound.Expanded(kLoopError).Contains(loop_bound));
            }
        }
Exemplo n.º 17
0
    public void Test_GetCrossingCandidates_CollinearEdgesOnCellBoundaries()
    {
        int kNumEdgeIntervals = 8;  // 9*8/2 = 36 edges

        for (int level = 0; level <= S2.kMaxCellLevel; ++level)
        {
            S2Cell  cell  = new(S2Testing.GetRandomCellId(level));
            int     j2    = S2Testing.Random.Uniform(4);
            S2Point p1    = cell.VertexRaw(j2);
            S2Point p2    = cell.VertexRaw(j2 + 1);
            S2Point delta = (p2 - p1) / kNumEdgeIntervals;
            List <(S2Point, S2Point)> edges = new();
            for (int i = 0; i <= kNumEdgeIntervals; ++i)
            {
                for (int j = 0; j < i; ++j)
                {
                    edges.Add(((p1 + i * delta).Normalize(),
                               (p1 + j * delta).Normalize()));
                }
            }
            TestAllCrossings(edges);
        }
    }
Exemplo n.º 18
0
        public void Test_S2CellId_Tokens()
        {
            // Test random cell ids at all levels.
            for (int i = 0; i < 10000; ++i)
            {
                var id    = S2Testing.GetRandomCellId();
                var token = id.ToToken();
                Assert.True(token.Length <= 16);
                Assert.Equal(id, S2CellId.FromToken(token));
                Assert.Equal(id, S2CellId.FromToken(token));
            }
            // Check that invalid cell ids can be encoded, and round-trip is
            // the identity operation.
            string token2 = S2CellId.None.ToToken();

            Assert.Equal(S2CellId.None, S2CellId.FromToken(token2));
            Assert.Equal(S2CellId.None, S2CellId.FromToken(token2));

            // Sentinel is invalid.
            token2 = S2CellId.Sentinel.ToToken();
            Assert.Equal(S2CellId.FromToken(token2), S2CellId.Sentinel);
            Assert.Equal(S2CellId.FromToken(token2),
                         S2CellId.Sentinel);

            // Check an invalid face.
            token2 = S2CellId.FromFace(7).ToToken();
            Assert.Equal(S2CellId.FromToken(token2), S2CellId.FromFace(7));
            Assert.Equal(S2CellId.FromToken(token2),
                         S2CellId.FromFace(7));

            // Check that supplying tokens with non-alphanumeric characters
            // returns S2CellId.None.
            Assert.Equal(S2CellId.None, S2CellId.FromToken("876b e99"));
            Assert.Equal(S2CellId.None, S2CellId.FromToken("876bee99\n"));
            Assert.Equal(S2CellId.None, S2CellId.FromToken("876[ee99"));
            Assert.Equal(S2CellId.None, S2CellId.FromToken(" 876bee99"));
        }
Exemplo n.º 19
0
        public void Test_S2Cell_GetDistanceToEdge()
        {
            S2Testing.Random.Reset(S2Testing.Random.RandomSeed);
            for (int iter = 0; iter < 1000; ++iter)
            {
                _logger.WriteLine($"Iteration {iter}");
                S2Cell cell = new(S2Testing.GetRandomCellId());
                ChooseEdgeNearCell(cell, out var a, out var b);
                S1Angle expected_min = GetDistanceToEdgeBruteForce(cell, a, b).ToAngle();
                S1Angle expected_max =
                    GetMaxDistanceToEdgeBruteForce(cell, a, b).ToAngle();
                S1Angle actual_min = cell.Distance(a, b).ToAngle();
                S1Angle actual_max = cell.MaxDistance(a, b).ToAngle();
                // The error has a peak near Pi/2 for edge distance, and another peak near
                // Pi for vertex distance.
                if (expected_min.Radians > S2.M_PI_2)
                {
                    // Max error for S1ChordAngle as it approaches Pi is about 2e-8.
                    Assert2.Near(expected_min.Radians, actual_min.Radians, 2e-8);
                }
                else if (expected_min.Radians <= Math.PI / 3)
                {
                    Assert2.Near(expected_min.Radians, actual_min.Radians, S2.DoubleError);
                }
                else
                {
                    Assert2.Near(expected_min.Radians, actual_min.Radians, 1e-12);
                }

                Assert2.Near(expected_max.Radians, actual_max.Radians, 1e-12);
                if (expected_max.Radians <= Math.PI / 3)
                {
                    Assert2.Near(expected_max.Radians, actual_max.Radians, S2.DoubleError);
                }
            }
        }
Exemplo n.º 20
0
        public void Test_S2PaddedCell_S2CellMethods()
        {
            // Test the S2PaddedCell methods that have approximate S2Cell equivalents.
            int kIters = 1000;

            for (int iter = 0; iter < kIters; ++iter)
            {
                S2CellId     id      = S2Testing.GetRandomCellId();
                double       padding = Math.Pow(1e-15, S2Testing.Random.RandDouble());
                S2Cell       cell    = new(id);
                S2PaddedCell pcell   = new(id, padding);
                CompareS2CellToPadded(cell, pcell, padding);
                if (!id.IsLeaf())
                {
                    var children = new S2Cell[4];
                    Assert.True(cell.Subdivide(children));
                    for (int pos = 0; pos < 4; ++pos)
                    {
                        pcell.GetChildIJ(pos, out var i, out var j);
                        CompareS2CellToPadded(children[pos], new S2PaddedCell(pcell, i, j), padding);
                    }
                }
            }
        }
Exemplo n.º 21
0
        public void Test_S2CellId_MaximumTile()
        {
            // This method is tested more thoroughly in s2cell_union_test.cc.
            for (int iter = 0; iter < 1000; ++iter)
            {
                S2CellId id = S2Testing.GetRandomCellId(10);

                // Check that "limit" is returned for tiles at or beyond "limit".
                Assert.Equal(id, id.MaximumTile(id));
                Assert.Equal(id, id.Child(0).MaximumTile(id));
                Assert.Equal(id, id.Child(1).MaximumTile(id));
                Assert.Equal(id, id.Next().MaximumTile(id));
                Assert.Equal(id.Child(0), id.MaximumTile(id.Child(0)));

                // Check that the tile size is increased when possible.
                Assert.Equal(id, id.Child(0).MaximumTile(id.Next()));
                Assert.Equal(id, id.Child(0).MaximumTile(id.Next().Child(0)));
                Assert.Equal(id, id.Child(0).MaximumTile(id.Next().Child(1).Child(0)));
                Assert.Equal(id, id.Child(0).Child(0).MaximumTile(id.Next()));
                Assert.Equal(id, id.Child(0).Child(0).Child(0).MaximumTile(id.Next()));

                // Check that the tile size is decreased when necessary.
                Assert.Equal(id.Child(0), id.MaximumTile(id.Child(0).Next()));
                Assert.Equal(id.Child(0), id.MaximumTile(id.Child(0).Next().Child(0)));
                Assert.Equal(id.Child(0), id.MaximumTile(id.Child(0).Next().Child(1)));
                Assert.Equal(id.Child(0).Child(0),
                             id.MaximumTile(id.Child(0).Child(0).Next()));
                Assert.Equal(id.Child(0).Child(0).Child(0),
                             id.MaximumTile(id.Child(0).Child(0).Child(0).Next()));

                // Check that the tile size is otherwise unchanged.
                Assert.Equal(id, id.MaximumTile(id.Next()));
                Assert.Equal(id, id.MaximumTile(id.Next().Child(0)));
                Assert.Equal(id, id.MaximumTile(id.Next().Child(1).Child(0)));
            }
        }
Exemplo n.º 22
0
        public void Test_S2CellId_Neighbors()
        {
            // Check the edge neighbors of face 1.
            var out_faces = new[] { 5, 3, 2, 0 };
            var face_nbrs = new S2CellId[4];

            S2CellId.FromFace(1).EdgeNeighbors(face_nbrs);
            for (int i = 0; i < 4; ++i)
            {
                Assert.True(face_nbrs[i].IsFace());
                Assert.Equal(out_faces[i], (int)face_nbrs[i].Face());
            }

            // Check the edge neighbors of the corner cells at all levels.  This case is
            // trickier because it requires projecting onto adjacent faces.
            const int kMaxIJ = S2CellId.kMaxSize - 1;

            for (int level = 1; level <= S2.kMaxCellLevel; ++level)
            {
                S2CellId id2   = S2CellId.FromFaceIJ(1, 0, 0).Parent(level);
                var      nbrs2 = new S2CellId[4];
                id2.EdgeNeighbors(nbrs2);
                // These neighbors were determined manually using the face and axis
                // relationships defined in s2coords.cc.
                int size_ij = S2CellId.SizeIJ(level);
                Assert.Equal(S2CellId.FromFaceIJ(5, kMaxIJ, kMaxIJ).Parent(level), nbrs2[0]);
                Assert.Equal(S2CellId.FromFaceIJ(1, size_ij, 0).Parent(level), nbrs2[1]);
                Assert.Equal(S2CellId.FromFaceIJ(1, 0, size_ij).Parent(level), nbrs2[2]);
                Assert.Equal(S2CellId.FromFaceIJ(0, kMaxIJ, 0).Parent(level), nbrs2[3]);
            }

            // Check the vertex neighbors of the center of face 2 at level 5.
            var nbrs = new List <S2CellId>();

            new S2CellId(new S2Point(0, 0, 1)).AppendVertexNeighbors(5, nbrs);
            nbrs.Sort();
            for (int i = 0; i < 4; ++i)
            {
                Assert.Equal(S2CellId.FromFaceIJ(
                                 2, (1 << 29) - ((i < 2) ? 1 : 0), (1 << 29) - ((i == 0 || i == 3) ? 1 : 0))
                             .Parent(5), nbrs[i]);
            }
            nbrs.Clear();

            // Check the vertex neighbors of the corner of faces 0, 4, and 5.
            S2CellId id1 = S2CellId.FromFacePosLevel(0, 0, S2.kMaxCellLevel);

            id1.AppendVertexNeighbors(0, nbrs);
            nbrs.Sort();
            Assert.Equal(3, nbrs.Count);
            Assert.Equal(S2CellId.FromFace(0), nbrs[0]);
            Assert.Equal(S2CellId.FromFace(4), nbrs[1]);
            Assert.Equal(S2CellId.FromFace(5), nbrs[2]);

            // Check that AppendAllNeighbors produces results that are consistent
            // with AppendVertexNeighbors for a bunch of random cells.
            for (var i = 0; i < 1000; ++i)
            {
                S2CellId id2 = S2Testing.GetRandomCellId();
                if (id2.IsLeaf())
                {
                    id2 = id2.Parent();
                }

                // TestAllNeighbors computes approximately 2**(2*(diff+1)) cell ids,
                // so it's not reasonable to use large values of "diff".
                int max_diff = Math.Min(5, S2.kMaxCellLevel - id2.Level() - 1);
                int level    = id2.Level() + S2Testing.Random.Uniform(max_diff + 1);
                TestAllNeighbors(id2, level);
            }
        }