ext/h3/src/src/h3lib/lib/h3Index.c in h3-3.4.4 vs ext/h3/src/src/h3lib/lib/h3Index.c in h3-3.5.0

- old
+ new

@@ -1,7 +1,7 @@ /* - * Copyright 2016-2018 Uber Technologies, Inc. + * Copyright 2016-2019 Uber Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * @@ -737,17 +737,16 @@ // adjust for overage if needed // a pentagon base cell with a leading 4 digit requires special handling int pentLeading4 = (_isBaseCellPentagon(baseCell) && _h3LeadingNonZeroDigit(h) == 4); - if (_adjustOverageClassII(fijk, res, pentLeading4, 0)) { + if (_adjustOverageClassII(fijk, res, pentLeading4, 0) != NO_OVERAGE) { // if the base cell is a pentagon we have the potential for secondary // overages if (_isBaseCellPentagon(baseCell)) { - while (1) { - if (!_adjustOverageClassII(fijk, res, 0, 0)) break; - } + while (_adjustOverageClassII(fijk, res, 0, 0) != NO_OVERAGE) + continue; } if (res != H3_GET_RESOLUTION(h)) _upAp7r(&fijk->coord); } else if (res != H3_GET_RESOLUTION(h)) { fijk->coord = origIJK; @@ -775,9 +774,91 @@ void H3_EXPORT(h3ToGeoBoundary)(H3Index h3, GeoBoundary* gb) { FaceIJK fijk; _h3ToFaceIjk(h3, &fijk); _faceIjkToGeoBoundary(&fijk, H3_GET_RESOLUTION(h3), H3_EXPORT(h3IsPentagon)(h3), gb); +} + +/** + * Returns the max number of possible icosahedron faces an H3 index + * may intersect. + * + * @return int count of faces + */ +int H3_EXPORT(maxFaceCount)(H3Index h3) { + // a pentagon always intersects 5 faces, a hexagon never intersects more + // than 2 (but may only intersect 1) + return H3_EXPORT(h3IsPentagon)(h3) ? 5 : 2; +} + +/** + * Find all icosahedron faces intersected by a given H3 index, represented + * as integers from 0-19. The array is sparse; since 0 is a valid value, + * invalid array values are represented as -1. It is the responsibility of + * the caller to filter out invalid values. + * + * @param h3 The H3 index + * @param out Output array. Must be of size maxFaceCount(h3). + */ +void H3_EXPORT(h3GetFaces)(H3Index h3, int* out) { + int res = H3_GET_RESOLUTION(h3); + int isPentagon = H3_EXPORT(h3IsPentagon)(h3); + + // We can't use the vertex-based approach here for class II pentagons, + // because all their vertices are on the icosahedron edges. Their + // direct child pentagons cross the same faces, so use those instead. + if (isPentagon && !isResClassIII(res)) { + // Note that this would not work for res 15, but this is only run on + // Class II pentagons, it should never be invoked for a res 15 index. + H3Index childPentagon = makeDirectChild(h3, 0); + H3_EXPORT(h3GetFaces)(childPentagon, out); + return; + } + + // convert to FaceIJK + FaceIJK fijk; + _h3ToFaceIjk(h3, &fijk); + + // Get all vertices as FaceIJK addresses. For simplicity, always + // initialize the array with 6 verts, ignoring the last one for pentagons + FaceIJK fijkVerts[NUM_HEX_VERTS]; + int vertexCount; + + if (isPentagon) { + vertexCount = NUM_PENT_VERTS; + _faceIjkPentToVerts(&fijk, &res, fijkVerts); + } else { + vertexCount = NUM_HEX_VERTS; + _faceIjkToVerts(&fijk, &res, fijkVerts); + } + + // We may not use all of the slots in the output array, + // so fill with invalid values to indicate unused slots + int faceCount = H3_EXPORT(maxFaceCount)(h3); + for (int i = 0; i < faceCount; i++) { + out[i] = INVALID_FACE; + } + + // add each vertex face, using the output array as a hash set + for (int i = 0; i < vertexCount; i++) { + FaceIJK* vert = &fijkVerts[i]; + + // Adjust overage, determining whether this vertex is + // on another face + if (isPentagon) { + _adjustPentVertOverage(vert, res); + } else { + _adjustOverageClassII(vert, res, 0, 1); + } + + // Save the face to the output array + int face = vert->face; + 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; + } } /** * Returns whether or not a resolution is a Class III grid. Note that odd * resolutions are Class III and even resolutions are Class II.