public void Test_S2CellId_ParentChildRelationships() { S2CellId id = S2CellId.FromFacePosLevel(3, 0x12345678, S2.kMaxCellLevel - 4); Assert.True(id.IsValid()); Assert.Equal(3UL, id.Face()); Assert.Equal(0x12345700UL, id.Pos()); Assert.Equal(S2.kMaxCellLevel - 4, id.Level()); Assert.False(id.IsLeaf()); Assert.Equal(0x12345610UL, id.ChildBegin(id.Level() + 2).Pos()); Assert.Equal(0x12345640UL, id.ChildBegin().Pos()); Assert.Equal(0x12345400UL, id.Parent().Pos()); Assert.Equal(0x12345000UL, id.Parent(id.Level() - 2).Pos()); // Check ordering of children relative to parents. Assert.True(id.ChildBegin() < id); Assert.True(id.ChildEnd() > id); Assert.Equal(id.ChildEnd(), id.ChildBegin().Next().Next().Next().Next()); Assert.Equal(id.RangeMin(), id.ChildBegin(S2.kMaxCellLevel)); Assert.Equal(id.RangeMax().Next(), id.ChildEnd(S2.kMaxCellLevel)); // Check that cells are represented by the position of their center // along the Hilbert curve. Assert.Equal(2 * id.Id, id.RangeMin().Id + id.RangeMax().Id); }
private readonly int orientation_; // Hilbert curve orientation of this cell (see s2coords.h) #region Constructors // Construct an S2PaddedCell for the given cell id and padding. public S2PaddedCell(S2CellId id, double padding) { ij_lo_ = new int[2]; Id = id; Padding = padding; if (Id.IsFace()) { // Fast path for constructing a top-level face (the most common case). double limit = 1 + padding; Bound = new R2Rect(new R1Interval(-limit, limit), new R1Interval(-limit, limit)); middle_ = new R2Rect(new R1Interval(-padding, padding), new R1Interval(-padding, padding)); ij_lo_[0] = ij_lo_[1] = 0; orientation_ = (int)(Id.Face() & 1); Level = 0; } else { var ij = new int[2]; id.ToFaceIJOrientation(out ij[0], out ij[1], out orientation_, true); Level = id.Level(); Bound = S2CellId.IJLevelToBoundUV(ij, Level).Expanded(padding); int ij_size = S2CellId.SizeIJ(Level); ij_lo_[0] = ij[0] & -ij_size; ij_lo_[1] = ij[1] & -ij_size; } }
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); } }
private static S2Shape NewPaddedCell(S2CellId id, double padding_uv) { var ij = new int[2]; var face = id.ToFaceIJOrientation(out ij[0], out ij[1], out _, false); var uv = S2CellId.IJLevelToBoundUV(ij, id.Level()).Expanded(padding_uv); var vertices = new S2Point[4]; for (int i = 0; i < 4; ++i) { vertices[i] = S2.FaceUVtoXYZ(face, uv.GetVertex(i)).Normalize(); } return(new S2LaxLoopShape(vertices)); }
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())); }
// Returns true if "covering" contains all children of "id" at level // (id.Level + options_.level_mod()). private bool ContainsAllChildren(List <S2CellId> covering, S2CellId id) { var it = covering.GetLowerBound(id.RangeMin()); int level = id.Level() + Options_.LevelMod; var limit = id.ChildEnd(level); for (var child = id.ChildBegin(level); child != limit; child = child.Next()) { if (it == covering.Count || covering[it] != child) { return(false); } it++; } return(true); }
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)); } }
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); } }