public void testFaceUVtoXYZ() { // Check that each face appears exactly once. var sum = new S2Point(); for (var face = 0; face < 6; ++face) { var center = S2Projections.FaceUvToXyz(face, 0, 0); assertEquals(S2Projections.GetNorm(face), center); assertEquals(Math.Abs(center[center.LargestAbsComponent]), 1.0); sum = sum + S2Point.Fabs(center); } assertEquals(sum, new S2Point(2, 2, 2)); // Check that each face has a right-handed coordinate system. for (var face = 0; face < 6; ++face) { assertEquals( S2Point.CrossProd(S2Projections.GetUAxis(face), S2Projections.GetVAxis(face)).DotProd( S2Projections.FaceUvToXyz(face, 0, 0)), 1.0); } // Check that the Hilbert curves on each face combine to form a // continuous curve over the entire cube. for (var face = 0; face < 6; ++face) { // The Hilbert curve on each face starts at (-1,-1) and terminates // at either (1,-1) (if axes not swapped) or (-1,1) (if swapped). var sign = ((face & S2.SwapMask) != 0) ? -1 : 1; assertEquals(S2Projections.FaceUvToXyz(face, sign, -sign), S2Projections.FaceUvToXyz((face + 1) % 6, -1, -1)); } }
public void testUVAxes() { // Check that axes are consistent with FaceUVtoXYZ. for (var face = 0; face < 6; ++face) { assertEquals(S2Projections.GetUAxis(face), S2Projections.FaceUvToXyz(face, 1, 0) - S2Projections.FaceUvToXyz(face, 0, 0)); assertEquals(S2Projections.GetVAxis(face), S2Projections.FaceUvToXyz(face, 0, 1) - S2Projections.FaceUvToXyz(face, 0, 0)); } }
public void testUVNorms() { // Check that GetUNorm and GetVNorm compute right-handed normals for // an edge in the increasing U or V direction. for (var face = 0; face < 6; ++face) { for (double x = -1; x <= 1; x += 1 / 1024.0) { assertDoubleNear( S2Point.CrossProd( S2Projections.FaceUvToXyz(face, x, -1), S2Projections.FaceUvToXyz(face, x, 1)) .Angle(S2Projections.GetUNorm(face, x)), 0); assertDoubleNear( S2Point.CrossProd( S2Projections.FaceUvToXyz(face, -1, x), S2Projections.FaceUvToXyz(face, 1, x)) .Angle(S2Projections.GetVNorm(face, x)), 0); } } }
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)); } } }