public void Test_FaceUVtoXYZ() { // Check that each face appears exactly once. S2Point sum = S2Point.Empty; for (int face = 0; face < 6; ++face) { S2Point center = S2.FaceUVtoXYZ(face, 0, 0); Assert.Equal(S2.GetNorm(face), center); Assert.Equal(1, Math.Abs(center[center.LargestAbsComponent()])); sum += center.Fabs(); } Assert.Equal(sum, new S2Point(2, 2, 2)); // Check that each face has a right-handed coordinate system. for (int face = 0; face < 6; ++face) { Assert.Equal(1, S2.GetUAxis(face).CrossProd(S2.GetVAxis(face)) .DotProd(S2.FaceUVtoXYZ(face, 0, 0))); } // Check that the Hilbert curves on each face combine to form a // continuous curve over the entire cube. for (int 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). int sign = ((face & S2.kSwapMask) != 0) ? -1 : 1; Assert.Equal(S2.FaceUVtoXYZ(face, sign, -sign), S2.FaceUVtoXYZ((face + 1) % 6, -1, -1)); } }
public void Test_FaceXYZtoUVW() { for (int face = 0; face < 6; ++face) { Assert.Equal(new S2Point(0, 0, 0), S2.FaceXYZtoUVW(face, S2Point.Empty)); Assert.Equal(new S2Point(1, 0, 0), S2.FaceXYZtoUVW(face, S2.GetUAxis(face))); Assert.Equal(new S2Point(-1, 0, 0), S2.FaceXYZtoUVW(face, -S2.GetUAxis(face))); Assert.Equal(new S2Point(0, 1, 0), S2.FaceXYZtoUVW(face, S2.GetVAxis(face))); Assert.Equal(new S2Point(0, -1, 0), S2.FaceXYZtoUVW(face, -S2.GetVAxis(face))); Assert.Equal(new S2Point(0, 0, 1), S2.FaceXYZtoUVW(face, S2.GetNorm(face))); Assert.Equal(new S2Point(0, 0, -1), S2.FaceXYZtoUVW(face, -S2.GetNorm(face))); } }
public void Test_GetCrossingCandidates_PerturbedCubeFaceAxes() { List <(S2Point, S2Point)> edges = new(); for (int iter = 0; iter < 5; ++iter) { int face = S2Testing.Random.Uniform(6); double scale = Math.Pow(S2.DoubleError, S2Testing.Random.RandDouble()); S2Point axis = S2.GetUVWAxis(face, S2Testing.Random.Uniform(2)); S2Point a0 = scale * axis + S2.GetNorm(face); S2Point b0 = scale * axis - S2.GetNorm(face); GetPerturbedSubEdges(a0, b0, 30, edges); TestAllCrossings(edges); } }
public void Test_GetCrossingCandidates_PerturbedCubeEdges() { List <(S2Point, S2Point)> edges = new(); for (int iter = 0; iter < 10; ++iter) { int face = S2Testing.Random.Uniform(6); double scale = Math.Pow(S2.DoubleError, S2Testing.Random.RandDouble()); R2Point uv = new(2 * S2Testing.Random.Uniform(2) - 1, 2 * S2Testing.Random.Uniform(2) - 1); // vertex S2Point a0 = S2.FaceUVtoXYZ(face, scale * uv); S2Point b0 = a0 - 2 * S2.GetNorm(face); // TODO(ericv): This test is currently slow because *every* crossing test // needs to invoke S2Pred.ExpensiveSign(). GetPerturbedSubEdges(a0, b0, 30, edges); TestAllCrossings(edges); } }
public void Test_UVWAxis() { for (int face = 0; face < 6; ++face) { // Check that axes are consistent with FaceUVtoXYZ. Assert.Equal(S2.FaceUVtoXYZ(face, 1, 0) - S2.FaceUVtoXYZ(face, 0, 0), S2.GetUAxis(face)); Assert.Equal(S2.FaceUVtoXYZ(face, 0, 1) - S2.FaceUVtoXYZ(face, 0, 0), S2.GetVAxis(face)); Assert.Equal(S2.FaceUVtoXYZ(face, 0, 0), S2.GetNorm(face)); // Check that every face coordinate frame is right-handed. Assert.Equal(1, S2.GetUAxis(face).CrossProd(S2.GetVAxis(face)) .DotProd(S2.GetNorm(face))); // Check that GetUVWAxis is consistent with GetUAxis, GetVAxis, GetNorm. Assert.Equal(S2.GetUAxis(face), S2.GetUVWAxis(face, 0)); Assert.Equal(S2.GetVAxis(face), S2.GetUVWAxis(face, 1)); Assert.Equal(S2.GetNorm(face), S2.GetUVWAxis(face, 2)); } }
public void Test_S2Cap_S2CellMethods() { // 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. for (var face = 0; face < 6; ++face) { // The cell consisting of the entire face. S2Cell root_cell = S2Cell.FromFace(face); // A leaf cell at the midpoint of the v=1 edge. S2Cell edge_cell = new(S2.FaceUVtoXYZ(face, 0, 1 - kEps)); // A leaf cell at the u=1, v=1 corner. S2Cell corner_cell = new(S2.FaceUVtoXYZ(face, 1 - kEps, 1 - kEps)); // Quick check for full and empty caps. Assert.True(S2Cap.Full.Contains(root_cell)); Assert.False(S2Cap.Empty.MayIntersect(root_cell)); // 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. S2CellId first = corner_cell.Id.Advance(-3); S2CellId last = corner_cell.Id.Advance(4); for (S2CellId id = first; id < last; id = id.Next()) { S2Cell cell = new(id); Assert.Equal(id == corner_cell.Id, cell.GetCapBound().Contains(corner_cell)); Assert.Equal(id.Parent().Contains(corner_cell.Id), cell.GetCapBound().MayIntersect(corner_cell)); } var anti_face = (face + 3) % 6; // Opposite face. for (var cap_face = 0; cap_face < 6; ++cap_face) { // A cap that barely contains all of 'cap_face'. S2Point center = S2.GetNorm(cap_face); S2Cap covering = new(center, S1Angle.FromRadians(kFaceRadius + kEps)); Assert.Equal(cap_face == face, covering.Contains(root_cell)); Assert.Equal(cap_face != anti_face, covering.MayIntersect(root_cell)); Assert.Equal(center.DotProd(edge_cell.Center()) > 0.1, covering.Contains(edge_cell)); Assert.Equal(covering.MayIntersect(edge_cell), covering.Contains(edge_cell)); Assert.Equal(cap_face == face, covering.Contains(corner_cell)); Assert.Equal(center.DotProd(corner_cell.Center()) > 0, covering.MayIntersect(corner_cell)); // A cap that barely intersects the edges of 'cap_face'. S2Cap bulging = new(center, S1Angle.FromRadians(S2.M_PI_4 + kEps)); Assert.False(bulging.Contains(root_cell)); Assert.Equal(cap_face != anti_face, bulging.MayIntersect(root_cell)); Assert.Equal(cap_face == face, bulging.Contains(edge_cell)); Assert.Equal(center.DotProd(edge_cell.Center()) > 0.1, bulging.MayIntersect(edge_cell)); Assert.False(bulging.Contains(corner_cell)); Assert.False(bulging.MayIntersect(corner_cell)); // A singleton cap. S2Cap singleton = new(center, S1Angle.Zero); Assert.Equal(cap_face == face, singleton.MayIntersect(root_cell)); Assert.False(singleton.MayIntersect(edge_cell)); Assert.False(singleton.MayIntersect(corner_cell)); } } }