// The point 'p' does not need to be normalized. private void Init(S2CellId id) { _cellId = id; var ij = new int[2]; int?mOrientation = 0; for (var d = 0; d < 2; ++d) { ij[d] = 0; } _face = (byte)id.ToFaceIjOrientation(ref ij[0], ref ij[1], ref mOrientation); _orientation = (byte)mOrientation.Value; // Compress int to a byte. _level = (byte)id.Level; var cellSize = 1 << (S2CellId.MaxLevel - _level); for (var d = 0; d < 2; ++d) { // Compute the cell bounds in scaled (i,j) coordinates. var sijLo = (ij[d] & -cellSize) * 2 - MaxCellSize; var sijHi = sijLo + cellSize * 2; _uv[d][0] = S2Projections.StToUv((1.0 / MaxCellSize) * sijLo); _uv[d][1] = S2Projections.StToUv((1.0 / MaxCellSize) * sijHi); } }
/** * Convert (face, si, ti) coordinates (see s2.h) to a direction vector (not * necessarily unit length). */ private static S2Point FaceSiTiToXyz(int face, int si, int ti) { const double kScale = 1.0 / MaxSize; var u = S2Projections.StToUv(kScale * si); var v = S2Projections.StToUv(kScale * ti); return(S2Projections.FaceUvToXyz(face, u, v)); }
/** * Return the leaf cell containing the given point (a direction vector, not * necessarily unit length). */ public static S2CellId FromPoint(S2Point p) { var face = S2Projections.XyzToFace(p); var uv = S2Projections.ValidFaceXyzToUv(face, p); var i = StToIj(S2Projections.UvToSt(uv.X)); var j = StToIj(S2Projections.UvToSt(uv.Y)); return(FromFaceIj(face, i, j)); }
public bool Contains(S2Point p) { // We can't just call XYZtoFaceUV, because for points that lie on the // boundary between two faces (i.e. u or v is +1/-1) we need to return // true for both adjacent cells. var uvPoint = S2Projections.FaceXyzToUv(_face, p); if (uvPoint == null) { return(false); } return(uvPoint.Value.X >= _uv[0][0] && uvPoint.Value.X <= _uv[0][1] && uvPoint.Value.Y >= _uv[1][0] && uvPoint.Value.Y <= _uv[1][1]); }
public S2Point GetEdgeRaw(int k) { switch (k) { case 0: return(S2Projections.GetVNorm(_face, _uv[1][0])); // South case 1: return(S2Projections.GetUNorm(_face, _uv[0][1])); // East case 2: return(-S2Projections.GetVNorm(_face, _uv[1][1])); // North default: return(-S2Projections.GetUNorm(_face, _uv[0][0])); // West } }
/** * Given (i, j) coordinates that may be out of bounds, normalize them by * returning the corresponding neighbor cell on an adjacent face. */ private static S2CellId FromFaceIjWrap(int face, int i, int j) { // Convert i and j to the coordinates of a leaf cell just beyond the // boundary of this face. This prevents 32-bit overflow in the case // of finding the neighbors of a face cell, and also means that we // don't need to worry about the distinction between (s,t) and (u,v). i = Math.Max(-1, Math.Min(MaxSize, i)); j = Math.Max(-1, Math.Min(MaxSize, j)); // Find the (s,t) coordinates corresponding to (i,j). At least one // of these coordinates will be just outside the range [0, 1]. const double kScale = 1.0 / MaxSize; var s = kScale * ((i << 1) + 1 - MaxSize); var t = kScale * ((j << 1) + 1 - MaxSize); // Find the leaf cell coordinates on the adjacent face, and convert // them to a cell id at the appropriate level. var p = S2Projections.FaceUvToXyz(face, s, t); face = S2Projections.XyzToFace(p); var st = S2Projections.ValidFaceXyzToUv(face, p); return(FromFaceIj(face, StToIj(st.X), StToIj(st.Y))); }
private double GetLongitude(int i, int j) { var p = S2Projections.FaceUvToXyz(_face, _uv[0][i], _uv[1][j]); return(Math.Atan2(p.Y, p.X)); }
// Internal method that does the actual work in the constructors. private double GetLatitude(int i, int j) { var p = S2Projections.FaceUvToXyz(_face, _uv[0][i], _uv[1][j]); return(Math.Atan2(p.Z, Math.Sqrt(p.X * p.X + p.Y * p.Y))); }
/** * Return the k-th vertex of the cell (k = 0,1,2,3). Vertices are returned in * CCW order. The points returned by GetVertexRaw are not necessarily unit * length. */ public S2Point GetVertexRaw(int k) { // Vertices are returned in the order SW, SE, NE, NW. return(S2Projections.FaceUvToXyz(_face, _uv[0][(k >> 1) ^ (k & 1)], _uv[1][k >> 1])); }