// Return the center of this cell. public S2Point GetCenter() { var ij_size = S2CellId.SizeIJ(Level); var si = (uint)(2 * ij_lo_[0] + ij_size); var ti = (uint)(2 * ij_lo_[1] + ij_size); return(S2.FaceSiTitoXYZ((int)Id.Face(), si, ti).Normalize()); }
public void Test_XYZToFaceSiTi() { // Check the conversion of random cells to center points and back. for (int level = 0; level <= S2.kMaxCellLevel; ++level) { for (int i = 0; i < 1000; ++i) { S2CellId id = S2Testing.GetRandomCellId(level); int actual_level = S2.XYZtoFaceSiTi(id.ToPoint(), out var face, out var si, out var ti); Assert.Equal(level, actual_level); S2CellId actual_id = S2CellId.FromFaceIJ(face, (int)(si / 2), (int)(ti / 2)).Parent(level); Assert.Equal(id, actual_id); // Now test a point near the cell center but not equal to it. S2Point p_moved = id.ToPoint() + new S2Point(1e-13, 1e-13, 1e-13); actual_level = S2.XYZtoFaceSiTi(p_moved, out var face_moved, out var si_moved, out var ti_moved); Assert.Equal(-1, actual_level); Assert.Equal(face, face_moved); Assert.Equal(si, si_moved); Assert.Equal(ti, ti_moved); // Finally, test some random (si,ti) values that may be at different // levels, or not at a valid level at all (for example, si == 0). int face_random = S2Testing.Random.Uniform(S2CellId.kNumFaces); uint si_random, ti_random; uint mask = ~0U << (S2.kMaxCellLevel - level); do { si_random = S2Testing.Random.Rand32() & mask; ti_random = S2Testing.Random.Rand32() & mask; } while (si_random > S2.kMaxSiTi || ti_random > S2.kMaxSiTi); S2Point p_random = S2.FaceSiTitoXYZ(face_random, si_random, ti_random); actual_level = S2.XYZtoFaceSiTi(p_random, out face, out si, out ti); if (face != face_random) { // The chosen point is on the edge of a top-level face cell. Assert.Equal(-1, actual_level); Assert.True(si == 0 || si == S2.kMaxSiTi || ti == 0 || ti == S2.kMaxSiTi); } else { Assert.Equal(si_random, si); Assert.Equal(ti_random, ti); if (actual_level >= 0) { Assert.Equal(p_random, S2CellId.FromFaceIJ(face, (int)(si / 2), (int)(ti / 2)).Parent(actual_level).ToPoint()); } } } } }
// Return the vertex where the S2 space-filling curve enters this cell. public S2Point GetEntryVertex() { // The curve enters at the (0,0) vertex unless the axis directions are // reversed, in which case it enters at the (1,1) vertex. uint i = (uint)ij_lo_[0]; uint j = (uint)ij_lo_[1]; if ((orientation_ & S2.kInvertMask) != 0) { int ij_size = S2CellId.SizeIJ(Level); i = (uint)(i + ij_size); j = (uint)(j + ij_size); } return(S2.FaceSiTitoXYZ((int)Id.Face(), 2 * i, 2 * j).Normalize()); }
// Return the vertex where the S2 space-filling curve exits this cell. public S2Point GetExitVertex() { // The curve exits at the (1,0) vertex unless the axes are swapped or // inverted but not both, in which case it exits at the (0,1) vertex. uint i = (uint)ij_lo_[0]; uint j = (uint)ij_lo_[1]; int ij_size = S2CellId.SizeIJ(Level); if (orientation_ == 0 || orientation_ == S2.kSwapMask + S2.kInvertMask) { i = (uint)(i + ij_size); } else { j = (uint)(j + ij_size); } return(S2.FaceSiTitoXYZ((int)Id.Face(), 2 * i, 2 * j).Normalize()); }