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 static ulong[] GetCellIdsForLatLong(double latitude, double longitude) { var latLong = S2LatLng.FromDegrees(latitude, longitude); var cell = S2CellId.FromLatLng(latLong); var cellId = cell.ParentForLevel(15); var cells = cellId.GetEdgeNeighbors(); var cellIds = new List <ulong> { cellId.Id }; foreach (var cellEdge1 in cells) { if (!cellIds.Contains(cellEdge1.Id)) { cellIds.Add(cellEdge1.Id); } foreach (var cellEdge2 in cellEdge1.GetEdgeNeighbors()) { if (!cellIds.Contains(cellEdge2.Id)) { cellIds.Add(cellEdge2.Id); } } } return(cellIds.ToArray()); }
public ElevationLocation(ulong c) { var cellId = new S2CellId(c); var latlng = cellId.ToLatLng(); Init(latlng.LatDegrees, latlng.LngDegrees); }
public GeoLocation(ulong capturedCellId) { var cellId = new S2CellId(capturedCellId); var latlng = cellId.ToLatLng(); Init(latlng.LatDegrees, latlng.LngDegrees); }
/** * 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); } } }
private void expandCell( S2CellId parent, List <S2CellId> cells, IDictionary <S2CellId, S2CellId> parentMap) { cells.Add(parent); if (parent.Level == kMaxExpandLevel) { return; } var i = 0; var j = 0; int?orientation = 0; var face = parent.ToFaceIjOrientation(ref i, ref j, ref orientation); JavaAssert.Equal(face, parent.Face); var pos = 0; for (var child = parent.ChildBegin; !child.Equals(parent.ChildEnd); child = child.Next) { // Do some basic checks on the children JavaAssert.Equal(child.Level, parent.Level + 1); Assert.True(!child.IsLeaf); int?childOrientation = 0; JavaAssert.Equal(child.ToFaceIjOrientation(ref i, ref j, ref childOrientation), face); JavaAssert.Equal( childOrientation.Value, orientation.Value ^ S2.PosToOrientation(pos)); parentMap.Add(child, parent); expandCell(child, cells, parentMap); ++pos; } }
public void suppressedTestLoopRelations2() { // Construct polygons consisting of a sequence of adjacent cell ids // at some fixed level. Comparing two polygons at the same level // ensures that there are no T-vertices. for (var iter = 0; iter < 1000; ++iter) { var num = (ulong)LongRandom(); var begin = new S2CellId(num | 1); if (!begin.IsValid) { continue; } begin = begin.ParentForLevel((int)Math.Round(rand.NextDouble() * S2CellId.MaxLevel)); var aBegin = advance(begin, skewed(6)); var aEnd = advance(aBegin, skewed(6) + 1); var bBegin = advance(begin, skewed(6)); var bEnd = advance(bBegin, skewed(6) + 1); if (!aEnd.IsValid || !bEnd.IsValid) { continue; } var a = makeCellLoop(aBegin, aEnd); var b = makeCellLoop(bBegin, bEnd); var contained = (aBegin <= bBegin && bEnd <= aEnd); var intersects = (aBegin < bEnd && bBegin < aEnd); Console.WriteLine( "Checking " + a.NumVertices + " vs. " + b.NumVertices + ", contained = " + contained + ", intersects = " + intersects); assertEquals(contained, a.Contains(b)); assertEquals(intersects, a.Intersects(b)); } }
public void Test_S2CellId_ToString() { Assert.Equal("3/", S2CellId.FromFace(3).ToString()); Assert.Equal("4/000000000000000000000000000000", S2CellId.FromFace(4).RangeMin().ToString()); Assert.Equal("Invalid: 0000000000000000", S2CellId.None.ToString()); }
// Let T be the target S2CellId. If T is contained by some index cell I // (including equality), this method positions the iterator at I and // returns INDEXED. Otherwise if T contains one or more (smaller) index // cells, it positions the iterator at the first such cell I and returns // SUBDIVIDED. Otherwise it returns DISJOINT. public (CellRelation cellRelation, int pos) LocateCell(S2CellId target) { // Let T be the target, let I = cell_map_.GetLowerBound(T.RangeMin), and // let I' be the predecessor of I. If T contains any index cells, then T // contains I. Similarly, if T is contained by an index cell, then the // containing cell is either I or I'. We test for containment by comparing // the ranges of leaf cells spanned by T, I, and I'. var(pos, _) = SeekCell(target.RangeMin()); var id = GetCellId(pos); if (id is not null) { if (id >= target && id.Value.RangeMin() <= target) { return(CellRelation.INDEXED, pos); } if (id <= target.RangeMax()) { return(CellRelation.SUBDIVIDED, pos); } } if (--pos >= 0) { id = GetCellId(pos); if (id != null && id.Value.RangeMax() >= target) { return(CellRelation.INDEXED, pos); } } return(CellRelation.DISJOINT, 0); }
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_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_Containment() { // Test contains() and intersects(). var parent_map = new Dictionary <S2CellId, S2CellId>(); var cells = new List <S2CellId>(); for (int face = 0; face < 6; ++face) { ExpandCell(S2CellId.FromFace(face), cells, parent_map); } foreach (var end_id in cells) { foreach (var begin_id in cells) { bool contained = true; for (var id = begin_id; id != end_id; id = parent_map[id]) { if (!parent_map.ContainsKey(id)) { contained = false; break; } } Assert.Equal(contained, end_id.Contains(begin_id)); Assert.Equal(contained, begin_id >= end_id.RangeMin() && begin_id <= end_id.RangeMax()); Assert.Equal(end_id.Intersects(begin_id), end_id.Contains(begin_id) || begin_id.Contains(end_id)); } } }
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)))); }
public void Test_S2CellUnion_ToStringOneCell() { Assert.Equal(new S2CellUnion(new List <S2CellId> { S2CellId.FromFace(1) }).ToString(), "Size:1 S2CellIds:3"); }
// Clears all state with respect to which range(s) have been visited. public void Reset() { Current = CellNode.Zero; prev_start_id_ = S2CellId.None; node_cutoff_ = -1; next_node_cutoff_ = -1; }
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); } }
public static ulong GetPokeCell(ICoordinate poke) { var latLng = S2LatLng.FromDegrees((double)poke.Latitude, (double)poke.Longitude); var hash = S2CellId.FromLatLng(latLng).ParentForLevel(20).Id; return(hash); }
public void testAllNeighbors(S2CellId id, int level) { Assert.True(level >= id.Level && level < S2CellId.MaxLevel); // We compute GetAllNeighbors, and then add in all the children of "id" // at the given level. We then compare this against the result of finding // all the vertex neighbors of all the vertices of children of "id" at the // given level. These should give the same result. var all = new List <S2CellId>(); var expected = new List <S2CellId>(); id.GetAllNeighbors(level, all); var end = id.ChildEndForLevel(level + 1); for (var c = id.ChildBeginForLevel(level + 1); !c.Equals(end); c = c.Next) { all.Add(c.Parent); c.GetVertexNeighbors(level, expected); } // Sort the results and eliminate duplicates. all.Sort(); expected.Sort(); ISet <S2CellId> allSet = new HashSet <S2CellId>(all); ISet <S2CellId> expectedSet = new HashSet <S2CellId>(expected); var result = allSet.SetEquals(expectedSet); Assert.True(result); }
private void expandCell( S2CellId parent, List<S2CellId> cells, IDictionary<S2CellId, S2CellId> parentMap) { cells.Add(parent); if (parent.Level == kMaxExpandLevel) { return; } var i = 0; var j = 0; int? orientation = 0; var face = parent.ToFaceIjOrientation(ref i, ref j, ref orientation); JavaAssert.Equal(face, parent.Face); var pos = 0; for (var child = parent.ChildBegin; !child.Equals(parent.ChildEnd); child = child.Next) { // Do some basic checks on the children JavaAssert.Equal(child.Level, parent.Level + 1); Assert.True(!child.IsLeaf); int? childOrientation = 0; JavaAssert.Equal(child.ToFaceIjOrientation(ref i, ref j, ref childOrientation), face); JavaAssert.Equal( childOrientation.Value, orientation.Value ^ S2.PosToOrientation(pos)); parentMap.Add(child, parent); expandCell(child, cells, parentMap); ++pos; } }
public override int GetHashCode() { int hash = 1; if (S2CellId != 0UL) { hash ^= S2CellId.GetHashCode(); } if (CurrentTimestampMs != 0L) { hash ^= CurrentTimestampMs.GetHashCode(); } hash ^= forts_.GetHashCode(); hash ^= spawnPoints_.GetHashCode(); hash ^= deletedObjects_.GetHashCode(); if (IsTruncatedList != false) { hash ^= IsTruncatedList.GetHashCode(); } hash ^= fortSummaries_.GetHashCode(); hash ^= decimatedSpawnPoints_.GetHashCode(); hash ^= wildPokemons_.GetHashCode(); hash ^= catchablePokemons_.GetHashCode(); hash ^= nearbyPokemons_.GetHashCode(); return(hash); }
public void testAllNeighbors(S2CellId id, int level) { Assert.True(level >= id.Level && level < S2CellId.MaxLevel); // We compute GetAllNeighbors, and then add in all the children of "id" // at the given level. We then compare this against the result of finding // all the vertex neighbors of all the vertices of children of "id" at the // given level. These should give the same result. var all = new List<S2CellId>(); var expected = new List<S2CellId>(); id.GetAllNeighbors(level, all); var end = id.ChildEndForLevel(level + 1); for (var c = id.ChildBeginForLevel(level + 1); !c.Equals(end); c = c.Next) { all.Add(c.Parent); c.GetVertexNeighbors(level, expected); } // Sort the results and eliminate duplicates. all.Sort(); expected.Sort(); ISet<S2CellId> allSet = new HashSet<S2CellId>(all); ISet<S2CellId> expectedSet = new HashSet<S2CellId>(expected); var result = allSet.SetEquals(expectedSet); Assert.True(result); }
// Like GetSimpleCovering(), but accepts a starting S2CellId rather than a // starting point and cell level. Returns all edge-connected cells at the // same level as "start" that intersect "region", in arbitrary order. public static void FloodFill(IS2Region region, S2CellId start, List <S2CellId> output) { var all = new List <(S2CellId, int)>(); var frontier = new List <S2CellId>(); output.Clear(); all.Add((start, start.GetHashCode())); frontier.Add(start); while (frontier.Any()) { S2CellId id = frontier.Last(); frontier.RemoveAt(frontier.Count - 1); if (!region.MayIntersect(new S2Cell(id))) { continue; } output.Add(id); var neighbors = new S2CellId[4]; id.EdgeNeighbors(neighbors); for (int edge = 0; edge < 4; ++edge) { var nbr = neighbors[edge]; var hash = nbr.GetHashCode(); all.Add((nbr, hash)); if (hash != 0) { frontier.Add(nbr); } } } }
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()); } }
/// <summary> /// Converts a string in the format returned by ToString() to an S2CellId. /// Returns S2CellId.None if the string could not be parsed. /// /// The method name includes "Debug" in order to avoid possible confusion /// with FromToken() above. /// </summary> private static S2CellId S2CellId_FromDebugString(string str) { // This function is reasonably efficient, but is only intended for use in // tests. var level = str.Length - 2; if (level < 0 || level > S2.kMaxCellLevel) { return(S2CellId.None); } var face = (int)char.GetNumericValue(str[0]); if (face < 0 || face > 5 || str[1] != '/') { return(S2CellId.None); } var id = S2CellId.FromFace(face); for (var i = 2; i < str.Length; i++) { var child_pos = (int)char.GetNumericValue(str[i]); if (child_pos < 0 || child_pos > 3) { return(S2CellId.None); } id = id.Child(child_pos); } return(id); }
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); } }
public static async Task <ElevationLocation> FindOrUpdateInDatabase(ulong c, IElevationService service) { var cellId = new S2CellId(c); var latlng = cellId.ToLatLng(); return(await FindOrUpdateInDatabase(latlng.LatDegrees, latlng.LngDegrees, service).ConfigureAwait(false)); }
private S2CellId getCellId(double latDegrees, double lngDegrees) { var id = S2CellId.FromLatLng(S2LatLng.FromDegrees(latDegrees, lngDegrees)); Trace.WriteLine(Convert.ToString(unchecked ((long)id.Id), 16)); return(id); }
// Positions the ContentsIterator at the first (cell_id, label) pair that // covers the given leaf cell range. Note that when multiple leaf cell // ranges are visited using the same ContentsIterator, duplicate values // may be suppressed. If you don't want this behavior, call Clear() first. public bool StartUnion(RangeNode rn) { if (rn.StartId < prev_start_id_) { node_cutoff_ = -1; // Can't automatically eliminate duplicates. } prev_start_id_ = rn.StartId; // TODO(ericv): Since RangeNode only uses 12 of its 16 bytes, we could add a // "label" field without using any extra space. Then we could store a leaf // node of cell_tree_ directly in each RangeNode, where the cell_id is // implicitly defined as the one that covers the current leaf cell range. // This would save quite a bit of space; e.g. if the given cells are // non-overlapping, then cell_tree_ would be empty (since every node is a // leaf node and could therefore be stored directly in a RangeNode). It // would also be faster because cell_tree_ would rarely be accessed. if (rn.Contents <= node_cutoff_) { return(false); } else { Current = cell_tree_[rn.Contents]; } // When visiting ancestors, we can stop as soon as the node index is smaller // than any previously visited node index. Because indexes are assigned // using a preorder traversal, such nodes are guaranteed to have already // been reported. next_node_cutoff_ = rn.Contents; return(true); }
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])); } } }
// Construct the child of "parent" with the given (i,j) index. The four // child cells have indices of (0,0), (0,1), (1,0), (1,1), where the i and j // indices correspond to increasing u- and v-values respectively. public S2PaddedCell(S2PaddedCell parent, int i, int j) { ij_lo_ = new int[2]; Padding = parent.Padding; Level = parent.Level + 1; // Compute the position and orientation of the child incrementally from the // orientation of the parent. int pos = S2.kIJtoPos[parent.orientation_][2 * i + j]; Id = parent.Id.Child(pos); int ij_size = S2CellId.SizeIJ(Level); ij_lo_[0] = parent.ij_lo_[0] + i * ij_size; ij_lo_[1] = parent.ij_lo_[1] + j * ij_size; orientation_ = parent.orientation_ ^ S2.kPosToOrientation[pos]; // For each child, one corner of the bound is taken directly from the parent // while the diagonally opposite corner is taken from middle(). var middle = parent.Middle; var x = new double[] { parent.Bound[0][0], parent.Bound[0][1] }; var y = new double[] { parent.Bound[1][0], parent.Bound[1][1] }; x[1 - i] = middle[0][1 - i]; y[1 - j] = middle[1][1 - j]; Bound = new R2Rect(new R1Interval(x), new R1Interval(y)); }
public static async Task <GeoLocation> FindOrUpdateInDatabase(ulong capturedCellId) { var cellId = new S2CellId(capturedCellId); var latlng = cellId.ToLatLng(); return(await FindOrUpdateInDatabase(latlng.LatDegrees, latlng.LngDegrees)); }
private static S2CellId GetPrevious(S2CellId cellId, int depth) { if (depth < 0) return cellId; depth--; return GetPrevious(cellId.Previous, depth); }
private static S2CellId GetNext(S2CellId cellId, int depth) { if (depth < 0) return cellId; depth--; return GetNext(cellId.Next, depth); }
private static S2CellId GetNext(S2CellId cellId, int depth) { while (true) { if (depth < 0) return cellId; depth--; cellId = cellId.Next; } }
private static S2CellId GetPrevious(S2CellId cellId, int depth) { while (true) { if (depth < 0) return cellId; depth--; cellId = cellId.Previous; } }
public static void DrawS2Cells(List<ulong> cellsIds, GMapOverlay mapLayer) { for (int i=0; i<cellsIds.Count; i++) { S2CellId cellId = new S2CellId(cellsIds[i]); S2Cell cell = new S2Cell(cellId); List<PointLatLng> points = new List<PointLatLng>(); for (int j=0; j<4; j++) { S2LatLng point = new S2LatLng(cell.GetVertex(j)); points.Add(new PointLatLng(point.LatDegrees, point.LngDegrees)); } GMapPolygon polygon = new GMapPolygon(points, "mypolygon"); polygon.Fill = new SolidBrush(Color.FromArgb(50, Color.Red)); polygon.Stroke = new Pen(Color.Red, 1); mapLayer.Polygons.Add(polygon); } }
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 suppressedTestLoopRelations2() { // Construct polygons consisting of a sequence of adjacent cell ids // at some fixed level. Comparing two polygons at the same level // ensures that there are no T-vertices. for (var iter = 0; iter < 1000; ++iter) { var num = (ulong)LongRandom(); var begin = new S2CellId(num | 1); if (!begin.IsValid) { continue; } begin = begin.ParentForLevel((int)Math.Round(rand.NextDouble()*S2CellId.MaxLevel)); var aBegin = advance(begin, skewed(6)); var aEnd = advance(aBegin, skewed(6) + 1); var bBegin = advance(begin, skewed(6)); var bEnd = advance(bBegin, skewed(6) + 1); if (!aEnd.IsValid || !bEnd.IsValid) { continue; } var a = makeCellLoop(aBegin, aEnd); var b = makeCellLoop(bBegin, bEnd); var contained = (aBegin <= bBegin && bEnd <= aEnd); var intersects = (aBegin < bEnd && bBegin < aEnd); Console.WriteLine( "Checking " + a.NumVertices + " vs. " + b.NumVertices + ", contained = " + contained + ", intersects = " + intersects); assertEquals(contained, a.Contains(b)); assertEquals(intersects, a.Intersects(b)); } }
private S2CellId advance(S2CellId id, int n) { while (id.IsValid && --n >= 0) { id = id.Next; } return id; }
private S2Loop makeCellLoop(S2CellId begin, S2CellId end) { // Construct a CCW polygon whose boundary is the union of the cell ids // in the range [begin, end). We Add the edges one by one, removing // any edges that are already present in the opposite direction. IDictionary<S2Point, ISet<S2Point>> edges = new Dictionary<S2Point, ISet<S2Point>>(); for (var id = begin; !id.Equals(end); id = id.Next) { var cell = new S2Cell(id); for (var k = 0; k < 4; ++k) { var a = cell.GetVertex(k); var b = cell.GetVertex((k + 1) & 3); if (!edges.ContainsKey(b)) { edges.Add(b, new HashSet<S2Point>()); } // if a is in b's set, remove it and remove b's set if it's empty // otherwise, Add b to a's set if (!edges[b].Remove(a)) { if (!edges.ContainsKey(a)) { edges.Add(a, new HashSet<S2Point>()); } edges[a].Add(b); } else if (edges[b].Count == 0) { edges.Remove(b); } } } // The remaining edges form a single loop. We simply follow it starting // at an arbitrary vertex and build up a list of vertices. var vertices = new List<S2Point>(); //S2Point p = edges.keySet().iterator().next(); var p = edges.Keys.First(); while (edges.Any()) { assertEquals(1, edges[p].Count); var next = edges[p].First(); //S2Point next = edges[p].iterator().next(); vertices.Add(p); edges.Remove(p); p = next; } return new S2Loop(vertices); }