Exemplo n.º 1
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.º 2
0
 public void Run()
 {
     for (S2CellId id = S2CellId.Begin(0);
          id != S2CellId.End(0); id = id.Next())
     {
         TestCell(new S2Cell(id));
     }
 }
Exemplo n.º 3
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.º 4
0
        public void Test_S2CellUnion_RefuseToDecode()
        {
            List <S2CellId> cellids = new();
            S2CellId        id      = S2CellId.Begin(S2.kMaxCellLevel);

            for (int i = 0; i <= S2CellUnion.Union_decode_max_num_cells; ++i)
            {
                cellids.Add(id);
                id = id.Next();
            }
            S2CellUnion cell_union = S2CellUnion.FromVerbatim(cellids);
            Encoder     encoder    = new();

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

            var(success, _) = S2CellUnion.Decode(decoder);
            Assert.False(success);
        }
Exemplo n.º 5
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);
            }
        }
Exemplo n.º 6
0
        static void TestSubdivide(S2Cell cell)
        {
            GatherStats(cell);
            if (cell.IsLeaf())
            {
                return;
            }

            var children = new S2Cell[4];

            Assert.True(cell.Subdivide(children));
            S2CellId child_id     = cell.Id.ChildBegin();
            double   exact_area   = 0;
            double   approx_area  = 0;
            double   average_area = 0;

            for (int i = 0; i < 4; ++i, child_id = child_id.Next())
            {
                exact_area   += children[i].ExactArea();
                approx_area  += children[i].ApproxArea();
                average_area += children[i].AverageArea();

                // Check that the child geometry is consistent with its cell ID.
                Assert.Equal(child_id, children[i].Id);
                Assert.True(S2.ApproxEquals(children[i].Center(), child_id.ToPoint()));
                S2Cell direct = new(child_id);
                Assert.Equal(direct.Face, children[i].Face);
                Assert.Equal(direct.Level, children[i].Level);
                Assert.Equal(direct.Orientation, children[i].Orientation);
                Assert.Equal(direct.CenterRaw(), children[i].CenterRaw());
                for (int k = 0; k < 4; ++k)
                {
                    Assert.Equal(direct.VertexRaw(k), children[i].VertexRaw(k));
                    Assert.Equal(direct.EdgeRaw(k), children[i].EdgeRaw(k));
                }

                // Test Contains() and MayIntersect().
                Assert.True(cell.Contains(children[i]));
                Assert.True(cell.MayIntersect(children[i]));
                Assert.False(children[i].Contains(cell));
                Assert.True(cell.Contains(children[i].CenterRaw()));
                for (int j = 0; j < 4; ++j)
                {
                    Assert.True(cell.Contains(children[i].VertexRaw(j)));
                    if (j != i)
                    {
                        Assert.False(children[i].Contains(children[j].CenterRaw()));
                        Assert.False(children[i].MayIntersect(children[j]));
                    }
                }

                // Test GetCapBound and GetRectBound.
                S2Cap        parent_cap  = cell.GetCapBound();
                S2LatLngRect parent_rect = cell.GetRectBound();
                if (cell.Contains(new S2Point(0, 0, 1)) || cell.Contains(new S2Point(0, 0, -1)))
                {
                    Assert.True(parent_rect.Lng.IsFull());
                }
                S2Cap        child_cap  = children[i].GetCapBound();
                S2LatLngRect child_rect = children[i].GetRectBound();
                Assert.True(child_cap.Contains(children[i].Center()));
                Assert.True(child_rect.Contains(children[i].CenterRaw()));
                Assert.True(parent_cap.Contains(children[i].Center()));
                Assert.True(parent_rect.Contains(children[i].CenterRaw()));
                for (int j = 0; j < 4; ++j)
                {
                    Assert.True(child_cap.Contains(children[i].Vertex(j)));
                    Assert.True(child_rect.Contains(children[i].Vertex(j)));
                    Assert.True(child_rect.Contains(children[i].VertexRaw(j)));
                    Assert.True(parent_cap.Contains(children[i].Vertex(j)));
                    Assert.True(parent_rect.Contains(children[i].Vertex(j)));
                    Assert.True(parent_rect.Contains(children[i].VertexRaw(j)));
                    if (j != i)
                    {
                        // The bounding caps and rectangles should be tight enough so that
                        // they exclude at least two vertices of each adjacent cell.
                        int cap_count  = 0;
                        int rect_count = 0;
                        for (int k = 0; k < 4; ++k)
                        {
                            if (child_cap.Contains(children[j].Vertex(k)))
                            {
                                ++cap_count;
                            }
                            if (child_rect.Contains(children[j].VertexRaw(k)))
                            {
                                ++rect_count;
                            }
                        }
                        Assert.True(cap_count <= 2);
                        if (child_rect.LatLo().Radians > -S2.M_PI_2 &&
                            child_rect.LatHi().Radians < S2.M_PI_2)
                        {
                            // Bounding rectangles may be too large at the poles because the
                            // pole itself has an arbitrary fixed longitude.
                            Assert.True(rect_count <= 2);
                        }
                    }
                }

                // Check all children for the first few levels, and then sample randomly.
                // We also always subdivide the cells containing a few chosen points so
                // that we have a better chance of sampling the minimum and maximum metric
                // values.  kMaxSizeUV is the absolute value of the u- and v-coordinate
                // where the cell size at a given level is maximal.
                double    kMaxSizeUV = 0.3964182625366691;
                R2Point[] special_uv =
                {
                    new R2Point(S2.DoubleEpsilon, S2.DoubleEpsilon), // Face center
                    new R2Point(S2.DoubleEpsilon, 1),                // Edge midpoint
                    new R2Point(1, 1),                               // Face corner
                    new R2Point(kMaxSizeUV, kMaxSizeUV),             // Largest cell area
                    new R2Point(S2.DoubleEpsilon, kMaxSizeUV),       // Longest edge/diagonal
                };
                bool force_subdivide = false;
                foreach (R2Point uv in special_uv)
                {
                    if (children[i].BoundUV.Contains(uv))
                    {
                        force_subdivide = true;
                    }
                }

                var debugFlag =
#if s2debug
                    true;
#else
                    false;
#endif

                if (force_subdivide ||
                    cell.Level < (debugFlag ? 5 : 6) ||
                    S2Testing.Random.OneIn(debugFlag ? 5 : 4))
                {
                    TestSubdivide(children[i]);
                }
            }

            // Check sum of child areas equals parent area.
            //
            // For ExactArea(), the best relative error we can expect is about 1e-6
            // because the precision of the unit vector coordinates is only about 1e-15
            // and the edge length of a leaf cell is about 1e-9.
            //
            // For ApproxArea(), the areas are accurate to within a few percent.
            //
            // For AverageArea(), the areas themselves are not very accurate, but
            // the average area of a parent is exactly 4 times the area of a child.

            Assert.True(Math.Abs(Math.Log(exact_area / cell.ExactArea())) <= Math.Abs(Math.Log((1 + 1e-6))));
            Assert.True(Math.Abs(Math.Log((approx_area / cell.ApproxArea()))) <= Math.Abs(Math.Log((1.03))));
            Assert.True(Math.Abs(Math.Log((average_area / cell.AverageArea()))) <= Math.Abs(Math.Log((1 + 1e-15))));
        }
Exemplo n.º 7
0
        public void Test_S2Cap_S2CellMethods()
        {
            // For each cube face, we construct some cells on
            // that face and some caps whose positions are relative to that face,
            // and then check for the expected intersection/containment results.

            for (var face = 0; face < 6; ++face)
            {
                // The cell consisting of the entire face.
                S2Cell root_cell = S2Cell.FromFace(face);

                // A leaf cell at the midpoint of the v=1 edge.
                S2Cell edge_cell = new(S2.FaceUVtoXYZ(face, 0, 1 - kEps));

                // A leaf cell at the u=1, v=1 corner.
                S2Cell corner_cell = new(S2.FaceUVtoXYZ(face, 1 - kEps, 1 - kEps));

                // Quick check for full and empty caps.
                Assert.True(S2Cap.Full.Contains(root_cell));
                Assert.False(S2Cap.Empty.MayIntersect(root_cell));

                // Check intersections with the bounding caps of the leaf cells that are
                // adjacent to 'corner_cell' along the Hilbert curve.  Because this corner
                // is at (u=1,v=1), the curve stays locally within the same cube face.
                S2CellId first = corner_cell.Id.Advance(-3);
                S2CellId last  = corner_cell.Id.Advance(4);
                for (S2CellId id = first; id < last; id = id.Next())
                {
                    S2Cell cell = new(id);
                    Assert.Equal(id == corner_cell.Id,
                                 cell.GetCapBound().Contains(corner_cell));
                    Assert.Equal(id.Parent().Contains(corner_cell.Id),
                                 cell.GetCapBound().MayIntersect(corner_cell));
                }

                var anti_face = (face + 3) % 6;  // Opposite face.
                for (var cap_face = 0; cap_face < 6; ++cap_face)
                {
                    // A cap that barely contains all of 'cap_face'.
                    S2Point center   = S2.GetNorm(cap_face);
                    S2Cap   covering = new(center, S1Angle.FromRadians(kFaceRadius + kEps));
                    Assert.Equal(cap_face == face, covering.Contains(root_cell));
                    Assert.Equal(cap_face != anti_face, covering.MayIntersect(root_cell));
                    Assert.Equal(center.DotProd(edge_cell.Center()) > 0.1,
                                 covering.Contains(edge_cell));
                    Assert.Equal(covering.MayIntersect(edge_cell), covering.Contains(edge_cell));
                    Assert.Equal(cap_face == face, covering.Contains(corner_cell));
                    Assert.Equal(center.DotProd(corner_cell.Center()) > 0,
                                 covering.MayIntersect(corner_cell));

                    // A cap that barely intersects the edges of 'cap_face'.
                    S2Cap bulging = new(center, S1Angle.FromRadians(S2.M_PI_4 + kEps));
                    Assert.False(bulging.Contains(root_cell));
                    Assert.Equal(cap_face != anti_face, bulging.MayIntersect(root_cell));
                    Assert.Equal(cap_face == face, bulging.Contains(edge_cell));
                    Assert.Equal(center.DotProd(edge_cell.Center()) > 0.1,
                                 bulging.MayIntersect(edge_cell));
                    Assert.False(bulging.Contains(corner_cell));
                    Assert.False(bulging.MayIntersect(corner_cell));

                    // A singleton cap.
                    S2Cap singleton = new(center, S1Angle.Zero);
                    Assert.Equal(cap_face == face, singleton.MayIntersect(root_cell));
                    Assert.False(singleton.MayIntersect(edge_cell));
                    Assert.False(singleton.MayIntersect(corner_cell));
                }
            }
        }