ext/h3/src/src/apps/applib/lib/utility.c in h3-3.6.2 vs ext/h3/src/src/apps/applib/lib/utility.c in h3-3.7.1
- old
+ new
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 Uber Technologies, Inc.
+ * Copyright 2016-2020 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
*
@@ -16,16 +16,18 @@
/** @file utility.c
* @brief Miscellaneous useful functions.
*/
#include "utility.h"
+
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+
#include "coordijk.h"
#include "h3Index.h"
#include "h3api.h"
void error(const char* msg) {
@@ -174,10 +176,126 @@
return 0;
}
/**
+ * Move nonzero elements to the front of array `a` of length `n`.
+ *
+ * Loop invariant: Everything *before* `i` or *after* `j` is "done".
+ * Move `i` and `j` inwards until they equal, and exit.
+ * You can move `i` forward until there's a zero in front of it.
+ * You can move `j` backward until there's a nonzero to the left of it.
+ * Anything to the right of `j` is "junk" that can be reallocated.
+ *
+ * Before:
+ * | a | b | 0 | c | d | ... |
+ * ^ ^
+ * i j
+ * After:
+ * | a | b | d | c | d | ... |
+ * ^ ^
+ * i j
+ *
+ * todo: should this function be in the public API?
+ * todo: add tests for this function
+ *
+ * @param a H3Index array to whose elements will be moved
+ * @param n length of the input array
+ * @return number of nonzero elements (length of new array); can reallocate
+ * memory after this point
+ */
+size_t packNonzeros(H3Index* a, size_t n) {
+ size_t i = 0;
+ size_t j = n;
+
+ while (i < j) {
+ // move j to the left until the first nonzero
+ if (a[j - 1] == 0) {
+ j -= 1;
+ continue;
+ }
+
+ // move i to the right until the first zero
+ if (a[i] != 0) {
+ i += 1;
+ continue;
+ }
+
+ // if we get to this point, we know:
+ // a[i] == 0
+ // a[j-1] != 0
+ // i < j
+ // so we can swap! (actually, move a[j-1] -> a[i])
+ a[i] = a[j - 1];
+ j -= 1;
+ }
+
+ return i;
+}
+
+/**
+ * Array of all cells at a given resolution.
+ *
+ * @param res resolution
+ *
+ * @return array of H3 cells at resolution res
+ */
+H3Index* getCellsAtRes(int res) {
+ int num0 = H3_EXPORT(res0IndexCount)();
+ H3Index* cells0 = calloc(num0, sizeof(H3Index));
+ H3_EXPORT(getRes0Indexes)(cells0);
+
+ int numRes = H3_EXPORT(maxUncompactSize)(cells0, num0, res);
+
+ H3Index* cellsRes = calloc(numRes, sizeof(H3Index));
+ H3_EXPORT(uncompact)(cells0, num0, cellsRes, numRes, res);
+
+ free(cells0);
+
+ numRes = packNonzeros(cellsRes, numRes);
+ cellsRes = realloc(cellsRes, numRes * sizeof(H3Index));
+
+ return cellsRes;
+}
+
+/**
+ * Apply callback to every cell for a given resolution, and sum the results.
+ */
+double mapSumAllCells_double(int res, double (*callback)(H3Index)) {
+ H3Index* cells = getCellsAtRes(res);
+ int N = H3_EXPORT(numHexagons)(res);
+
+ double total = 0.0;
+ for (int i = 0; i < N; i++) {
+ total += (*callback)(cells[i]);
+ }
+ free(cells);
+
+ return total;
+}
+
+/**
+ * Apply callback for every unidirectional edge at the given resolution.
+ */
+void iterateAllUnidirectionalEdgesAtRes(int res, void (*callback)(H3Index)) {
+ H3Index* cells = getCellsAtRes(res);
+ int N = H3_EXPORT(numHexagons)(res);
+
+ for (int i = 0; i < N; i++) {
+ H3Index edges[6] = {H3_NULL};
+ int isPentagon = H3_EXPORT(h3IsPentagon)(cells[i]);
+ H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(cells[i], edges);
+
+ for (int j = 0; j < 6; j++) {
+ if (isPentagon && j == 0) continue;
+ (*callback)(edges[j]);
+ }
+ }
+ free(cells);
+}
+
+/**
* Call the callback for every index at the given resolution.
*/
void iterateAllIndexesAtRes(int res, void (*callback)(H3Index)) {
iterateAllIndexesAtResPartial(res, callback, NUM_BASE_CELLS);
}
@@ -205,11 +323,11 @@
int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
H3Index* children = calloc(childrenSz, sizeof(H3Index));
H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
for (int j = 0; j < childrenSz; j++) {
- if (children[j] == 0) {
+ if (children[j] == H3_NULL) {
continue;
}
(*callback)(children[j]);
}
@@ -230,6 +348,19 @@
}
g->lat = H3_EXPORT(degsToRads)(
(((float)rand() / (float)(RAND_MAX)) * 180.0) - 90.0);
g->lon = H3_EXPORT(degsToRads)((float)rand() / (float)(RAND_MAX)) * 360.0;
+}
+
+/**
+ * Returns the number of non-invalid indexes in the array.
+ */
+int countActualHexagons(H3Index* hexagons, int numHexagons) {
+ int actualNumHexagons = 0;
+ for (int i = 0; i < numHexagons; i++) {
+ if (hexagons[i] != H3_NULL) {
+ actualNumHexagons++;
+ }
+ }
+ return actualNumHexagons;
}