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