/** * Return the leaf cell containing the given {@link S2Point} (a direction vector, not necessarily * unit length). */ public static S2CellId fromPoint(S2Point p) { int face = S2Projections.xyzToFace(p); R2Vector uv = S2Projections.validFaceXyzToUv(face, p); int i = stToIJ(S2Projections.uvToST(uv.x())); int j = stToIJ(S2Projections.uvToST(uv.y())); return fromFaceIJ(face, i, j); }
/** * 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(MAX_SIZE, i)); j = Math.max(-1, Math.min(MAX_SIZE, j)); // Find the (s,t) coordinates corresponding to (i,j). At least one // of these coordinates will be just outside the range [0, 1]. final double kScale = 1.0 / MAX_SIZE; double s = kScale * ((i << 1) + 1 - MAX_SIZE); double t = kScale * ((j << 1) + 1 - MAX_SIZE); // Find the leaf cell coordinates on the adjacent face, and convert // them to a cell id at the appropriate level. S2Point p = S2Projections.faceUvToXyz(face, s, t); face = S2Projections.xyzToFace(p); R2Vector st = S2Projections.validFaceXyzToUv(face, p); return fromFaceIJ(face, stToIJ(st.x()), stToIJ(st.y())); }