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])); } } }
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 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); }
/** * Test all of the interval operations on the given pair of intervals. * "expected_relation" is a sequence of "T" and "F" characters corresponding * to the expected results of contains(), interiorContains(), Intersects(), * and InteriorIntersects() respectively. */ private void testIntervalOps(R1Interval x, R1Interval y, String expectedRelation) { JavaAssert.Equal(x.Contains(y), expectedRelation[0] == 'T'); JavaAssert.Equal(x.InteriorContains(y), expectedRelation[1] == 'T'); JavaAssert.Equal(x.Intersects(y), expectedRelation[2] == 'T'); JavaAssert.Equal(x.InteriorIntersects(y), expectedRelation[3] == 'T'); JavaAssert.Equal(x.Contains(y), x.Union(y).Equals(x)); JavaAssert.Equal(x.Intersects(y), !x.Intersection(y).IsEmpty); }
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 testInverses() { Trace.WriteLine("TestInverses"); // Check the conversion of random leaf cells to S2LatLngs and back. for (var i = 0; i < 200000; ++i) { var id = getRandomCellId(S2CellId.MaxLevel); Assert.True(id.IsLeaf && id.Level == S2CellId.MaxLevel); var center = id.ToLatLng(); JavaAssert.Equal(S2CellId.FromLatLng(center).Id, id.Id); } }
public void testTokens() { Trace.WriteLine("TestTokens"); // Test random cell ids at all levels. for (var i = 0; i < 10000; ++i) { var id = getRandomCellId(); if (!id.IsValid) { continue; } var token = id.ToToken(); Assert.True(token.Length <= 16); JavaAssert.Equal(S2CellId.FromToken(token), id); } // Check that invalid cell ids can be encoded. var token1 = S2CellId.None.ToToken(); JavaAssert.Equal(S2CellId.FromToken(token1), S2CellId.None); }
public void S1AngleBasicTest() { // Check that the conversion between Pi radians and 180 degrees is exact. JavaAssert.Equal(S1Angle.FromRadians(Math.PI).Radians, Math.PI); JavaAssert.Equal(S1Angle.FromRadians(Math.PI).Degrees, 180.0); JavaAssert.Equal(S1Angle.FromDegrees(180).Radians, Math.PI); JavaAssert.Equal(S1Angle.FromDegrees(180).Degrees, 180.0); JavaAssert.Equal(S1Angle.FromRadians(Math.PI / 2).Degrees, 90.0); // Check negative angles. JavaAssert.Equal(S1Angle.FromRadians(-Math.PI / 2).Degrees, -90.0); JavaAssert.Equal(S1Angle.FromDegrees(-45).Radians, -Math.PI / 4); // Check that E5/E6/E7 representations work as expected. JavaAssert.Equal(S1Angle.E5(2000000), S1Angle.FromDegrees(20)); JavaAssert.Equal(S1Angle.E6(-60000000), S1Angle.FromDegrees(-60)); JavaAssert.Equal(S1Angle.E7(750000000), S1Angle.FromDegrees(75)); JavaAssert.Equal(S1Angle.FromDegrees(12.34567).E5(), 1234567); JavaAssert.Equal(S1Angle.FromDegrees(12.345678).E6(), 12345678); JavaAssert.Equal(S1Angle.FromDegrees(-12.3456789).E7(), -123456789); }
public void testCells() { // 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. // The distance from the center of a face to one of its vertices. var kFaceRadius = Math.Atan(S2.Sqrt2); for (var face = 0; face < 6; ++face) { // The cell consisting of the entire face. var rootCell = S2Cell.FromFacePosLevel(face, (byte)0, 0); // A leaf cell at the midpoint of the v=1 edge. var edgeCell = new S2Cell(S2Projections.FaceUvToXyz(face, 0, 1 - EPS)); // A leaf cell at the u=1, v=1 corner. var cornerCell = new S2Cell(S2Projections.FaceUvToXyz(face, 1 - EPS, 1 - EPS)); // Quick check for full and empty caps. Assert.True(S2Cap.Full.Contains(rootCell)); Assert.True(!S2Cap.Empty.MayIntersect(rootCell)); // 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. var first = cornerCell.Id.Previous.Previous.Previous; var last = cornerCell.Id.Next.Next.Next.Next; for (var id = first; id < last; id = id.Next) { var cell = new S2Cell(id); JavaAssert.Equal(cell.CapBound.Contains(cornerCell), id.Equals(cornerCell.Id)); JavaAssert.Equal( cell.CapBound.MayIntersect(cornerCell), id.Parent.Contains(cornerCell.Id)); } var antiFace = (face + 3) % 6; // Opposite face. for (var capFace = 0; capFace < 6; ++capFace) { // A cap that barely contains all of 'cap_face'. var center = S2Projections.GetNorm(capFace); var covering = S2Cap.FromAxisAngle(center, S1Angle.FromRadians(kFaceRadius + EPS)); JavaAssert.Equal(covering.Contains(rootCell), capFace == face); JavaAssert.Equal(covering.MayIntersect(rootCell), capFace != antiFace); JavaAssert.Equal(covering.Contains(edgeCell), center.DotProd(edgeCell.Center) > 0.1); JavaAssert.Equal(covering.Contains(edgeCell), covering.MayIntersect(edgeCell)); JavaAssert.Equal(covering.Contains(cornerCell), capFace == face); JavaAssert.Equal( covering.MayIntersect(cornerCell), center.DotProd(cornerCell.Center) > 0); // A cap that barely intersects the edges of 'cap_face'. var bulging = S2Cap.FromAxisAngle(center, S1Angle.FromRadians(S2.PiOver4 + EPS)); Assert.True(!bulging.Contains(rootCell)); JavaAssert.Equal(bulging.MayIntersect(rootCell), capFace != antiFace); JavaAssert.Equal(bulging.Contains(edgeCell), capFace == face); JavaAssert.Equal(bulging.MayIntersect(edgeCell), center.DotProd(edgeCell.Center) > 0.1); Assert.True(!bulging.Contains(cornerCell)); Assert.True(!bulging.MayIntersect(cornerCell)); // A singleton cap. var singleton = S2Cap.FromAxisAngle(center, S1Angle.FromRadians(0)); JavaAssert.Equal(singleton.MayIntersect(rootCell), capFace == face); Assert.True(!singleton.MayIntersect(edgeCell)); Assert.True(!singleton.MayIntersect(cornerCell)); } } }
public void S2CapBasicTest() { // Test basic properties of empty and full caps. var empty = S2Cap.Empty; var full = S2Cap.Full; Assert.True(empty.IsValid); Assert.True(empty.IsEmpty); Assert.True(empty.Complement.IsFull); Assert.True(full.IsValid); Assert.True(full.IsFull); Assert.True(full.Complement.IsEmpty); JavaAssert.Equal(full.Height, 2.0); assertDoubleNear(full.Angle.Degrees, 180); // Containment and intersection of empty and full caps. Assert.True(empty.Contains(empty)); Assert.True(full.Contains(empty)); Assert.True(full.Contains(full)); Assert.True(!empty.InteriorIntersects(empty)); Assert.True(full.InteriorIntersects(full)); Assert.True(!full.InteriorIntersects(empty)); // Singleton cap containing the x-axis. var xaxis = S2Cap.FromAxisHeight(new S2Point(1, 0, 0), 0); Assert.True(xaxis.Contains(new S2Point(1, 0, 0))); Assert.True(!xaxis.Contains(new S2Point(1, 1e-20, 0))); JavaAssert.Equal(xaxis.Angle.Radians, 0.0); // Singleton cap containing the y-axis. var yaxis = S2Cap.FromAxisAngle(new S2Point(0, 1, 0), S1Angle.FromRadians(0)); Assert.True(!yaxis.Contains(xaxis.Axis)); JavaAssert.Equal(xaxis.Height, 0.0); // Check that the complement of a singleton cap is the full cap. var xcomp = xaxis.Complement; Assert.True(xcomp.IsValid); Assert.True(xcomp.IsFull); Assert.True(xcomp.Contains(xaxis.Axis)); // Check that the complement of the complement is *not* the original. Assert.True(xcomp.Complement.IsValid); Assert.True(xcomp.Complement.IsEmpty); Assert.True(!xcomp.Complement.Contains(xaxis.Axis)); // Check that very small caps can be represented accurately. // Here "kTinyRad" is small enough that unit vectors perturbed by this // amount along a tangent do not need to be renormalized. var kTinyRad = 1e-10; var tiny = S2Cap.FromAxisAngle(S2Point.Normalize(new S2Point(1, 2, 3)), S1Angle.FromRadians(kTinyRad)); var tangent = S2Point.Normalize(S2Point.CrossProd(tiny.Axis, new S2Point(3, 2, 1))); Assert.True(tiny.Contains(tiny.Axis + (tangent * 0.99 * kTinyRad))); Assert.True(!tiny.Contains(tiny.Axis + (tangent * 1.01 * kTinyRad))); // Basic tests on a hemispherical cap. var hemi = S2Cap.FromAxisHeight(S2Point.Normalize(new S2Point(1, 0, 1)), 1); JavaAssert.Equal(hemi.Complement.Axis, -hemi.Axis); JavaAssert.Equal(hemi.Complement.Height, 1.0); Assert.True(hemi.Contains(new S2Point(1, 0, 0))); Assert.True(!hemi.Complement.Contains(new S2Point(1, 0, 0))); Assert.True(hemi.Contains(S2Point.Normalize(new S2Point(1, 0, -(1 - EPS))))); Assert.True(!hemi.InteriorContains(S2Point.Normalize(new S2Point(1, 0, -(1 + EPS))))); // A concave cap. var concave = S2Cap.FromAxisAngle(getLatLngPoint(80, 10), S1Angle.FromDegrees(150)); Assert.True(concave.Contains(getLatLngPoint(-70 * (1 - EPS), 10))); Assert.True(!concave.Contains(getLatLngPoint(-70 * (1 + EPS), 10))); Assert.True(concave.Contains(getLatLngPoint(-50 * (1 - EPS), -170))); Assert.True(!concave.Contains(getLatLngPoint(-50 * (1 + EPS), -170))); // Cap containment tests. Assert.True(!empty.Contains(xaxis)); Assert.True(!empty.InteriorIntersects(xaxis)); Assert.True(full.Contains(xaxis)); Assert.True(full.InteriorIntersects(xaxis)); Assert.True(!xaxis.Contains(full)); Assert.True(!xaxis.InteriorIntersects(full)); Assert.True(xaxis.Contains(xaxis)); Assert.True(!xaxis.InteriorIntersects(xaxis)); Assert.True(xaxis.Contains(empty)); Assert.True(!xaxis.InteriorIntersects(empty)); Assert.True(hemi.Contains(tiny)); Assert.True(hemi.Contains( S2Cap.FromAxisAngle(new S2Point(1, 0, 0), S1Angle.FromRadians(S2.PiOver4 - EPS)))); Assert.True(!hemi.Contains( S2Cap.FromAxisAngle(new S2Point(1, 0, 0), S1Angle.FromRadians(S2.PiOver4 + EPS)))); Assert.True(concave.Contains(hemi)); Assert.True(concave.InteriorIntersects(hemi.Complement)); Assert.True(!concave.Contains(S2Cap.FromAxisHeight(-concave.Axis, 0.1))); }
protected static void assertEquals(object actual, object expected) { JavaAssert.Equal(actual, expected); }
public void testToToken() { JavaAssert.Equal("000000000000010a", new S2CellId(266).ToToken()); JavaAssert.Equal("80855c", new S2CellId(unchecked ((ulong)-9185834709882503168L)).ToToken()); }
public void testSubdivide(S2Cell cell) { gatherStats(cell); if (cell.IsLeaf) { return; } var children = new S2Cell[4]; for (var i = 0; i < children.Length; ++i) { children[i] = new S2Cell(); } Assert.True(cell.Subdivide(children)); var childId = cell.Id.ChildBegin; double exactArea = 0; double approxArea = 0; double averageArea = 0; for (var i = 0; i < 4; ++i, childId = childId.Next) { exactArea += children[i].ExactArea(); approxArea += children[i].ApproxArea(); averageArea += children[i].AverageArea(); // Check that the child geometry is consistent with its cell id. JavaAssert.Equal(children[i].Id, childId); Assert.True(children[i].Center.ApproxEquals(childId.ToPoint(), 1e-15)); var direct = new S2Cell(childId); JavaAssert.Equal(children[i].Face, direct.Face); JavaAssert.Equal(children[i].Level, direct.Level); JavaAssert.Equal(children[i].Orientation, direct.Orientation); JavaAssert.Equal(children[i].CenterRaw, direct.CenterRaw); for (var k = 0; k < 4; ++k) { JavaAssert.Equal(children[i].GetVertexRaw(k), direct.GetVertexRaw(k)); JavaAssert.Equal(children[i].GetEdgeRaw(k), direct.GetEdgeRaw(k)); } // Test Contains() and MayIntersect(). Assert.True(cell.Contains(children[i])); Assert.True(cell.MayIntersect(children[i])); Assert.True(!children[i].Contains(cell)); Assert.True(cell.Contains(children[i].CenterRaw)); for (var j = 0; j < 4; ++j) { Assert.True(cell.Contains(children[i].GetVertexRaw(j))); if (j != i) { Assert.True(!children[i].Contains(children[j].CenterRaw)); Assert.True(!children[i].MayIntersect(children[j])); } } // Test GetCapBound and GetRectBound. var parentCap = cell.CapBound; var parentRect = cell.RectBound; if (cell.Contains(new S2Point(0, 0, 1)) || cell.Contains(new S2Point(0, 0, -1))) { Assert.True(parentRect.Lng.IsFull); } var childCap = children[i].CapBound; var childRect = children[i].RectBound; Assert.True(childCap.Contains(children[i].Center)); Assert.True(childRect.Contains(children[i].CenterRaw)); Assert.True(parentCap.Contains(children[i].Center)); Assert.True(parentRect.Contains(children[i].CenterRaw)); for (var j = 0; j < 4; ++j) { Assert.True(childCap.Contains(children[i].GetVertex(j))); Assert.True(childRect.Contains(children[i].GetVertex(j))); Assert.True(childRect.Contains(children[i].GetVertexRaw(j))); Assert.True(parentCap.Contains(children[i].GetVertex(j))); if (!parentRect.Contains(children[i].GetVertex(j))) { Console.WriteLine("cell: " + cell + " i: " + i + " j: " + j); Console.WriteLine("Children " + i + ": " + children[i]); Console.WriteLine("Parent rect: " + parentRect); Console.WriteLine("Vertex raw(j) " + children[i].GetVertex(j)); Console.WriteLine("Latlng of vertex: " + new S2LatLng(children[i].GetVertex(j))); Console.WriteLine("RectBound: " + cell.RectBound); } Assert.True(parentRect.Contains(children[i].GetVertex(j))); if (!parentRect.Contains(children[i].GetVertexRaw(j))) { Console.WriteLine("cell: " + cell + " i: " + i + " j: " + j); Console.WriteLine("Children " + i + ": " + children[i]); Console.WriteLine("Parent rect: " + parentRect); Console.WriteLine("Vertex raw(j) " + children[i].GetVertexRaw(j)); Console.WriteLine("Latlng of vertex: " + new S2LatLng(children[i].GetVertexRaw(j))); Console.WriteLine("RectBound: " + cell.RectBound); } Assert.True(parentRect.Contains(children[i].GetVertexRaw(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. var capCount = 0; var rectCount = 0; for (var k = 0; k < 4; ++k) { if (childCap.Contains(children[j].GetVertex(k))) { ++capCount; } if (childRect.Contains(children[j].GetVertexRaw(k))) { ++rectCount; } } Assert.True(capCount <= 2); if (childRect.LatLo.Radians > -S2.PiOver2 && childRect.LatHi.Radians < S2.PiOver2) { // Bounding rectangles may be too large at the poles because the // pole itself has an arbitrary fixed longitude. Assert.True(rectCount <= 2); } } } // Check all children for the first few levels, and then sample randomly. // Also subdivide one corner cell, one edge cell, and one center cell // so that we have a better chance of sample the minimum metric values. var forceSubdivide = false; var center = S2Projections.GetNorm(children[i].Face); var edge = center + S2Projections.GetUAxis(children[i].Face); var corner = edge + S2Projections.GetVAxis(children[i].Face); for (var j = 0; j < 4; ++j) { var p = children[i].GetVertexRaw(j); if (p.Equals(center) || p.Equals(edge) || p.Equals(corner)) { forceSubdivide = true; } } if (forceSubdivide || cell.Level < (DEBUG_MODE ? 5 : 6) || random(DEBUG_MODE ? 10 : 4) == 0) { 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(exactArea / cell.ExactArea())) <= Math .Abs(Math.Log(1 + 1e-6))); Assert.True(Math.Abs(Math.Log(approxArea / cell.ApproxArea())) <= Math .Abs(Math.Log(1.03))); Assert.True(Math.Abs(Math.Log(averageArea / cell.AverageArea())) <= Math .Abs(Math.Log(1 + 1e-15))); }
public void R1IntervalBasicTest() { // Constructors and accessors. var unit = new R1Interval(0, 1); var negunit = new R1Interval(-1, 0); JavaAssert.Equal(unit.Lo, 0.0); JavaAssert.Equal(unit.Hi, 1.0); JavaAssert.Equal(negunit.Lo, -1.0); JavaAssert.Equal(negunit.Hi, 0.0); // is_empty() var half = new R1Interval(0.5, 0.5); Assert.True(!unit.IsEmpty); Assert.True(!half.IsEmpty); var empty = R1Interval.Empty; Assert.True(empty.IsEmpty); // GetCenter(), GetLength() JavaAssert.Equal(unit.Center, 0.5); JavaAssert.Equal(half.Center, 0.5); JavaAssert.Equal(negunit.Length, 1.0); JavaAssert.Equal(half.Length, 0.0); Assert.True(empty.Length < 0); // contains(double), interiorContains(double) Assert.True(unit.Contains(0.5)); Assert.True(unit.InteriorContains(0.5)); Assert.True(unit.Contains(0)); Assert.True(!unit.InteriorContains(0)); Assert.True(unit.Contains(1)); Assert.True(!unit.InteriorContains(1)); // contains(R1Interval), interiorContains(R1Interval) // Intersects(R1Interval), InteriorIntersects(R1Interval) testIntervalOps(empty, empty, "TTFF"); testIntervalOps(empty, unit, "FFFF"); testIntervalOps(unit, half, "TTTT"); testIntervalOps(unit, unit, "TFTT"); testIntervalOps(unit, empty, "TTFF"); testIntervalOps(unit, negunit, "FFTF"); testIntervalOps(unit, new R1Interval(0, 0.5), "TFTT"); testIntervalOps(half, new R1Interval(0, 0.5), "FFTF"); // addPoint() R1Interval r; r = empty.AddPoint(5); Assert.True(r.Lo == 5.0 && r.Hi == 5.0); r = r.AddPoint(-1); Assert.True(r.Lo == -1.0 && r.Hi == 5.0); r = r.AddPoint(0); Assert.True(r.Lo == -1.0 && r.Hi == 5.0); // fromPointPair() JavaAssert.Equal(R1Interval.FromPointPair(4, 4), new R1Interval(4, 4)); JavaAssert.Equal(R1Interval.FromPointPair(-1, -2), new R1Interval(-2, -1)); JavaAssert.Equal(R1Interval.FromPointPair(-5, 3), new R1Interval(-5, 3)); // expanded() JavaAssert.Equal(empty.Expanded(0.45), empty); JavaAssert.Equal(unit.Expanded(0.5), new R1Interval(-0.5, 1.5)); // union(), intersection() Assert.True(new R1Interval(99, 100).Union(empty).Equals(new R1Interval(99, 100))); Assert.True(empty.Union(new R1Interval(99, 100)).Equals(new R1Interval(99, 100))); Assert.True(new R1Interval(5, 3).Union(new R1Interval(0, -2)).IsEmpty); Assert.True(new R1Interval(0, -2).Union(new R1Interval(5, 3)).IsEmpty); Assert.True(unit.Union(unit).Equals(unit)); Assert.True(unit.Union(negunit).Equals(new R1Interval(-1, 1))); Assert.True(negunit.Union(unit).Equals(new R1Interval(-1, 1))); Assert.True(half.Union(unit).Equals(unit)); Assert.True(unit.Intersection(half).Equals(half)); Assert.True(unit.Intersection(negunit).Equals(new R1Interval(0, 0))); Assert.True(negunit.Intersection(half).IsEmpty); Assert.True(unit.Intersection(empty).IsEmpty); Assert.True(empty.Intersection(unit).IsEmpty); }