/** * Return the inward-facing normal of the great circle passing through the * edge from vertex k to vertex k+1 (mod 4). The normals returned by * GetEdgeRaw are not necessarily unit length. * * If this is not a leaf cell, set children[0..3] to the four children of * this cell (in traversal order) and return true. Otherwise returns false. * This method is equivalent to the following: * * for (pos=0, id=child_begin(); id != child_end(); id = id.next(), ++pos) * children[i] = S2Cell(id); * * except that it is more than two times faster. */ public bool Subdivide(IReadOnlyList <S2Cell> children) { // This function is equivalent to just iterating over the child cell ids // and calling the S2Cell constructor, but it is about 2.5 times faster. if (_cellId.IsLeaf) { return(false); } // Compute the cell midpoint in uv-space. var uvMid = CenterUv; // Create four children with the appropriate bounds. var id = _cellId.ChildBegin; for (var pos = 0; pos < 4; ++pos, id = id.Next) { var child = children[pos]; child._face = _face; child._level = (byte)(_level + 1); child._orientation = (byte)(_orientation ^ S2.PosToOrientation(pos)); child._cellId = id; var ij = S2.PosToIj(_orientation, pos); for (var d = 0; d < 2; ++d) { // The dimension 0 index (i/u) is in bit 1 of ij. var m = 1 - ((ij >> (1 - d)) & 1); child._uv[d][m] = uvMid[d]; child._uv[d][1 - m] = _uv[d][1 - m]; } } return(true); }
private static void InitLookupCell(int level, int i, int j, int origOrientation, int pos, int orientation) { if (level == LookupBits) { var ij = (i << LookupBits) + j; LookupPos[(ij << 2) + origOrientation] = (pos << 2) + orientation; LookupIj[(pos << 2) + origOrientation] = (ij << 2) + orientation; } else { level++; i <<= 1; j <<= 1; pos <<= 2; // Initialize each sub-cell recursively. for (var subPos = 0; subPos < 4; subPos++) { var ij = S2.PosToIj(orientation, subPos); var orientationMask = S2.PosToOrientation(subPos); InitLookupCell(level, i + (ij >> 1), j + (ij & 1), origOrientation, pos + subPos, orientation ^ orientationMask); } } }