/** * Checks that "covering" completely covers the given region. If "check_tight" * is true, also checks that it does not contain any cells that do not * intersect the given region. ("id" is only used internally.) */ protected void checkCovering(IS2Region region, S2CellUnion covering, bool checkTight, S2CellId id) { if (!id.IsValid) { for (var face = 0; face < 6; ++face) { checkCovering(region, covering, checkTight, S2CellId.FromFacePosLevel(face, 0, 0)); } return; } if (!region.MayIntersect(new S2Cell(id))) { // If region does not intersect id, then neither should the covering. if (checkTight) { Assert.True(!covering.Intersects(id)); } } else if (!covering.Contains(id)) { // The region may intersect id, but we can't assert that the covering // intersects id because we may discover that the region does not actually // intersect upon further subdivision. (MayIntersect is not exact.) Assert.True(!region.Contains(new S2Cell(id))); var result = !id.IsLeaf; Assert.True(result); var end = id.ChildEnd; for (var child = id.ChildBegin; !child.Equals(end); child = child.Next) { checkCovering(region, covering, checkTight, child); } } }
public void testContainment() { Trace.WriteLine("TestContainment"); IDictionary <S2CellId, S2CellId> parentMap = new Dictionary <S2CellId, S2CellId>(); var cells = new List <S2CellId>(); for (var face = 0; face < 6; ++face) { expandCell(S2CellId.FromFacePosLevel(face, 0, 0), cells, parentMap); } for (var i = 0; i < cells.Count; ++i) { for (var j = 0; j < cells.Count; ++j) { var contained = true; for (var id = cells[j]; id != cells[i]; id = parentMap[id]) { if (!parentMap.ContainsKey(id)) { contained = false; break; } } JavaAssert.Equal(cells[i].Contains(cells[j]), contained); JavaAssert.Equal(cells[j] >= cells[i].RangeMin && cells[j] <= cells[i].RangeMax, contained); JavaAssert.Equal(cells[i].Intersects(cells[j]), cells[i].Contains(cells[j]) || cells[j].Contains(cells[i])); } } }
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); }
public void Test_S2CellId_FromFace() { for (int face = 0; face < 6; ++face) { Assert.Equal(S2CellId.FromFacePosLevel(face, 0, 0), S2CellId.FromFace(face)); } }
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)))); }
/** * Return a random cell id at the given level or at a randomly chosen level. * The distribution is uniform over the space of cell ids, but only * approximately uniform over the surface of the sphere. */ public S2CellId getRandomCellId(int level) { var face = random(S2CellId.NumFaces); var pos = (ulong)LongRandom() & ((1L << (2 * S2CellId.MaxLevel)) - 1); return(S2CellId.FromFacePosLevel(face, pos, level)); }
public void testNeighbors() { Trace.WriteLine("TestNeighbors"); // Check the edge neighbors of face 1. int[] outFaces = { 5, 3, 2, 0 }; var faceNbrs = S2CellId.FromFacePosLevel(1, 0, 0).GetEdgeNeighbors(); for (var i = 0; i < 4; ++i) { Assert.True(faceNbrs[i].IsFace); JavaAssert.Equal(faceNbrs[i].Face, outFaces[i]); } // Check the vertex neighbors of the center of face 2 at level 5. var nbrs = new List <S2CellId>(); S2CellId.FromPoint(new S2Point(0, 0, 1)).GetVertexNeighbors(5, nbrs); nbrs.Sort(); for (var i = 0; i < 4; ++i) { JavaAssert.Equal(nbrs[i], S2CellId.FromFaceIj( 2, (1 << 29) - (i < 2 ? 1 : 0), (1 << 29) - ((i == 0 || i == 3) ? 1 : 0)).ParentForLevel(5)); } nbrs.Clear(); // Check the vertex neighbors of the corner of faces 0, 4, and 5. var id = S2CellId.FromFacePosLevel(0, 0, S2CellId.MaxLevel); id.GetVertexNeighbors(0, nbrs); nbrs.Sort(); JavaAssert.Equal(nbrs.Count, 3); JavaAssert.Equal(nbrs[0], S2CellId.FromFacePosLevel(0, 0, 0)); JavaAssert.Equal(nbrs[1], S2CellId.FromFacePosLevel(4, 0, 0)); JavaAssert.Equal(nbrs[2], S2CellId.FromFacePosLevel(5, 0, 0)); // Check that GetAllNeighbors produces results that are consistent // with GetVertexNeighbors for a bunch of random cells. for (var i = 0; i < 1000; ++i) { var id1 = getRandomCellId(); var toTest = id1; if (id1.IsLeaf) { toTest = id1.Parent; } // TestAllNeighbors computes approximately 2**(2*(diff+1)) cell id1s, // so it's not reasonable to use large values of "diff". var maxDiff = Math.Min(6, S2CellId.MaxLevel - toTest.Level - 1); var level = toTest.Level + random(maxDiff); testAllNeighbors(toTest, level); } }
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); }
public void testFaces() { IDictionary <S2Point, int> edgeCounts = new Dictionary <S2Point, int>(); IDictionary <S2Point, int> vertexCounts = new Dictionary <S2Point, int>(); for (var face = 0; face < 6; ++face) { var id = S2CellId.FromFacePosLevel(face, 0, 0); var cell = new S2Cell(id); JavaAssert.Equal(cell.Id, id); JavaAssert.Equal(cell.Face, face); JavaAssert.Equal(cell.Level, 0); // Top-level faces have alternating orientations to get RHS coordinates. JavaAssert.Equal(cell.Orientation, face & S2.SwapMask); Assert.True(!cell.IsLeaf); for (var k = 0; k < 4; ++k) { if (edgeCounts.ContainsKey(cell.GetEdgeRaw(k))) { edgeCounts[cell.GetEdgeRaw(k)] = edgeCounts[cell .GetEdgeRaw(k)] + 1; } else { edgeCounts[cell.GetEdgeRaw(k)] = 1; } if (vertexCounts.ContainsKey(cell.GetVertexRaw(k))) { vertexCounts[cell.GetVertexRaw(k)] = vertexCounts[cell .GetVertexRaw(k)] + 1; } else { vertexCounts[cell.GetVertexRaw(k)] = 1; } assertDoubleNear(cell.GetVertexRaw(k).DotProd(cell.GetEdgeRaw(k)), 0); assertDoubleNear(cell.GetVertexRaw((k + 1) & 3).DotProd( cell.GetEdgeRaw(k)), 0); assertDoubleNear(S2Point.Normalize( S2Point.CrossProd(cell.GetVertexRaw(k), cell .GetVertexRaw((k + 1) & 3))).DotProd(cell.GetEdge(k)), 1.0); } } // Check that edges have multiplicity 2 and vertices have multiplicity 3. foreach (var i in edgeCounts.Values) { JavaAssert.Equal(i, 2); } foreach (var i in vertexCounts.Values) { JavaAssert.Equal(i, 3); } }
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())); }
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)); }
public void Test_S2CellId_CenterSiTi() { S2CellId id = S2CellId.FromFacePosLevel(3, 0x12345678, S2.kMaxCellLevel); // Check that the (si, ti) coordinates of the center end in a // 1 followed by (30 - level) 0s. // Leaf level, 30. id.CenterSiTi(out var si, out var ti); Assert.Equal(1 << 0, si & 1); Assert.Equal(1 << 0, ti & 1); // Level 29. id.Parent(S2.kMaxCellLevel - 1).CenterSiTi(out si, out ti); Assert.Equal(1 << 1, si & 3); Assert.Equal(1 << 1, ti & 3); // Level 28. id.Parent(S2.kMaxCellLevel - 2).CenterSiTi(out si, out ti); Assert.Equal(1 << 2, si & 7); Assert.Equal(1 << 2, ti & 7); // Level 20. id.Parent(S2.kMaxCellLevel - 10).CenterSiTi(out si, out ti); Assert.Equal(1 << 10, si & ((1 << 11) - 1)); Assert.Equal(1 << 10, ti & ((1 << 11) - 1)); // Level 10. id.Parent(S2.kMaxCellLevel - 20).CenterSiTi(out si, out ti); Assert.Equal(1 << 20, si & ((1 << 21) - 1)); Assert.Equal(1 << 20, ti & ((1 << 21) - 1)); // Level 0. id.Parent(0).CenterSiTi(out si, out ti); Assert.Equal(1 << 30, si & ((1U << 31) - 1)); Assert.Equal(1 << 30, ti & ((1U << 31) - 1)); }
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); } }