ext/h3/src/src/h3lib/lib/h3Index.c in h3-3.5.1 vs ext/h3/src/src/h3lib/lib/h3Index.c in h3-3.6.0

- old
+ new

@@ -144,10 +144,26 @@ } return parentH; } /** + * Determines whether one resolution is a valid child resolution of another. + * Each resolution is considered a valid child resolution of itself. + * + * @param parentRes int resolution of the parent + * @param childRes int resolution of the child + * + * @return The validity of the child resolution + */ +static bool _isValidChildRes(int parentRes, int childRes) { + if (childRes < parentRes || childRes > MAX_H3_RES) { + return false; + } + return true; +} + +/** * maxH3ToChildrenSize returns the maximum number of children possible for a * given child level. * * @param h H3Index to find the number of children of * @param childRes The resolution of the child level you're interested in @@ -155,11 +171,11 @@ * @return int count of maximum number of children (equal for hexagons, less for * pentagons */ int H3_EXPORT(maxH3ToChildrenSize)(H3Index h, int childRes) { int parentRes = H3_GET_RESOLUTION(h); - if (parentRes > childRes) { + if (!_isValidChildRes(parentRes, childRes)) { return 0; } return _ipow(7, (childRes - parentRes)); } @@ -189,11 +205,11 @@ * @param childRes int the child level to produce * @param children H3Index* the memory to store the resulting addresses in */ void H3_EXPORT(h3ToChildren)(H3Index h, int childRes, H3Index* children) { int parentRes = H3_GET_RESOLUTION(h); - if (parentRes > childRes) { + if (!_isValidChildRes(parentRes, childRes)) { return; } else if (parentRes == childRes) { *children = h; return; } @@ -213,10 +229,33 @@ } } } /** + * h3ToCenterChild produces the center child index for a given H3 index at + * the specified resolution + * + * @param h H3Index to find center child of + * @param childRes The resolution to switch to + * + * @return H3Index of the center child, or 0 if you actually asked for a parent + */ +H3Index H3_EXPORT(h3ToCenterChild)(H3Index h, int childRes) { + int parentRes = H3_GET_RESOLUTION(h); + if (!_isValidChildRes(parentRes, childRes)) { + return H3_INVALID_INDEX; + } else if (childRes == parentRes) { + return h; + } + H3Index child = H3_SET_RESOLUTION(h, childRes); + for (int i = parentRes + 1; i <= childRes; i++) { + H3_SET_INDEX_DIGIT(child, i, 0); + } + return child; +} + +/** * compact takes a set of hexagons all at the same resolution and compresses * them by pruning full child branches to the parent level. This is also done * for all parents recursively to get the minimum number of hex addresses that * perfectly cover the defined space. * @param h3Set Set of hexagons @@ -252,11 +291,11 @@ H3Index parent = H3_EXPORT(h3ToParent)(currIndex, parentRes); // Modulus hash the parent into the temp array int loc = (int)(parent % numRemainingHexes); int loopCount = 0; while (hashSetArray[loc] != 0) { - if (loopCount > numRemainingHexes) { + if (loopCount > numRemainingHexes) { // LCOV_EXCL_BR_LINE // LCOV_EXCL_START // This case should not be possible because at most one // index is placed into hashSetArray per // numRemainingHexes. free(remainingHexes); @@ -328,11 +367,11 @@ // the compactableHexes array int loc = (int)(parent % numRemainingHexes); int loopCount = 0; bool isUncompactable = true; do { - if (loopCount > numRemainingHexes) { + if (loopCount > numRemainingHexes) { // LCOV_EXCL_BR_LINE // LCOV_EXCL_START // This case should not be possible because at most one // index is placed into hashSetArray per input hexagon. free(compactableHexes); free(remainingHexes); @@ -391,11 +430,11 @@ if (outOffset >= maxHexes) { // We went too far, abort! return -1; } int currentRes = H3_GET_RESOLUTION(compactedSet[i]); - if (currentRes > res) { + if (!_isValidChildRes(currentRes, res)) { // Nonsensical. Abort. return -2; } if (currentRes == res) { // Just copy and move along @@ -429,11 +468,11 @@ const int res) { int maxNumHexagons = 0; for (int i = 0; i < numHexes; i++) { if (compactedSet[i] == 0) continue; int currentRes = H3_GET_RESOLUTION(compactedSet[i]); - if (currentRes > res) { + if (!_isValidChildRes(currentRes, res)) { // Nonsensical. Abort. return -1; } if (currentRes == res) { maxNumHexagons++; @@ -855,9 +894,33 @@ int pos = 0; // Find the first empty output position, or the first position // matching the current face while (out[pos] != INVALID_FACE && out[pos] != face) pos++; out[pos] = face; + } +} + +/** + * pentagonIndexCount returns the number of pentagons (same at any resolution) + * + * @return int count of pentagon indexes + */ +int H3_EXPORT(pentagonIndexCount)() { return NUM_PENTAGONS; } + +/** + * Generates all pentagons at the specified resolution + * + * @param res The resolution to produce pentagons at. + * @param out Output array. Must be of size pentagonIndexCount(). + */ +void H3_EXPORT(getPentagonIndexes)(int res, H3Index* out) { + int i = 0; + for (int bc = 0; bc < NUM_BASE_CELLS; bc++) { + if (_isBaseCellPentagon(bc)) { + H3Index pentagon; + setH3Index(&pentagon, res, bc, 0); + out[i++] = pentagon; + } } } /** * Returns whether or not a resolution is a Class III grid. Note that odd