Skip to content

Commit

Permalink
Merge 5d818aa into 11b4a82
Browse files Browse the repository at this point in the history
  • Loading branch information
dfellis committed Jan 22, 2018
2 parents 11b4a82 + 5d818aa commit 6e0ae41
Show file tree
Hide file tree
Showing 24 changed files with 338 additions and 803 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@ if(ENABLE_TESTS)
add_h3_test(testH3ToChildren src/apps/testapps/testH3ToChildren.c)
add_h3_test(testMaxH3ToChildrenSize src/apps/testapps/testMaxH3ToChildrenSize.c)
add_h3_test(testH3Index src/apps/testapps/testH3Index.c)
add_h3_test(testH3IndexFat src/apps/testapps/testH3IndexFat.c)
add_h3_test(testH3Api src/apps/testapps/testH3Api.c)
add_h3_test(testH3SetToLinkedGeo src/apps/testapps/testH3SetToLinkedGeo.c)
add_h3_test(testH3SetToVertexGraph src/apps/testapps/testH3SetToVertexGraph.c)
Expand Down
4 changes: 1 addition & 3 deletions docs/doxyfiles/geoToH3desc.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ The conversion is performed as a series of coordinate system conversions describ

1. The input latitude/longitude coordinate is first converted into the containing icosahedron face and a _Hex2d_ coordinate on that face using function ::\_geoToHex2d, which determines the correct face and then performs a face-centered gnomonic projection into face-centered polar coordinates. These polar coordinates are then scaled appropriately to a _Hex2d_ coordinate on the input grid resolution _r_.
2. The _Hex2d_ coordinate is converted into resolution _r_ normalized _ijk_ coordinates using function ::\_hex2dToCoordIJK.
3. The face and face-centered _ijk_ coordinates are then converted into an `H3IndexFat` representation using the following steps:
3. The face and face-centered _ijk_ coordinates are then converted into an `H3Index` representation using the following steps:

* the _H3_ index digits are calculated from resolution _r_ up to 0, adjusting the _ijk_ coordinates at each successively coarser resolution.
* when resolution 0 is reached, if the remaining _ijk_ coordinates are (0,0,0) then the base cell centered on the face is chosen for the index
* if the remaining resolution 0 _ijk_ coordinates are not (0,0,0), then a lookup operation is performed to find the appropriate base cell and the required rotation (if any) to orient the cell in that base cell's coordinate system. The index is then translated and rotated into the coordinate system centered on the new base cell.

4. The `H3FatIndex` representation is converted into an `H3Index` representation using function ::h3FatToH3.
1 change: 0 additions & 1 deletion docs/doxyfiles/h3ToGeoBoundaryDesc.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ This operation is performed by function ::h3ToGeoBoundary. See the comments in t

The conversion is performed as a series of coordinate system conversions described below. See the page <a href="./md_doxyfiles_coordsystems.html">Coordinate Systems used by the __H3 Core Library__</a> for more information on each of these coordinate systems.

* The `H3Index` representation is converted into an `H3FatIndex` representation using function ::h3ToH3Fat.
* We note that the cell vertices are the center points of cells in an aperture 3 grid one resolution finer than the cell resolution, which we term a _substrate_ grid. We precalculate the substrate _ijk_ coordinates of a cell with _ijk_ coordinates (0,0,0), adding additional aperture 3 and aperture 7 (if required, by Class III cell grid) substrate grid resolutions as required to transform the vertex coordinates into a Class II substrate grid.

\image html substrate3.png
Expand Down
3 changes: 1 addition & 2 deletions docs/doxyfiles/h3ToGeoDesc.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ This operation is performed by function ::h3ToGeo. See the comments in the funct

The conversion is performed as a series of coordinate system conversions described below. See the page <a href="./md_doxyfiles_coordsystems.html">Coordinate Systems used by the __H3 Core Library__</a> for more information on each of these coordinate systems.

* The `H3Index` representation is converted into an `H3FatIndex` representation using function ::h3ToH3Fat.
* The function ::\_h3FatToFaceIjk then converts the _H3_ index to the appropriate icosahedron face number and normalized _ijk_ coordinate's on that face's coordinate system as follows:
* The function ::\_h3ToFaceIjk then converts the _H3_ index to the appropriate icosahedron face number and normalized _ijk_ coordinate's on that face's coordinate system as follows:
* We start by assuming that the cell center point falls on the same icosahedron face as its base cell.
* It is possible that the the cell center point lies on an adjacent face (termed an _overage_ in the code), in which case we would need to use a projection centered on that adjacent face instead. We recall that normalized _ijk_ coordinates have at most two non-zero components, and that in a face-centered Class II system the sum of those components is a resolution-specific constant value for cells that lie on the edge of that icosahedral face.
We determine whether an overage exists by taking the sum of the _ijk_ components, and if there is an overage the positive _ijk_ components indicate which adjacent face the cell center lies on. A lookup operation is then performed to find the appropriate rotation and translation to transform the _ijk_ coordinates into the adjacent face-centered _ijk_ system.
Expand Down
5 changes: 0 additions & 5 deletions docs/doxyfiles/h3indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,3 @@ The layout of an __H3Index__ is shown below in table form. The interpretation of
<td colspan="3">Digit 15</td>
</tr>
</table>

H3IndexFat Representation
---

The __H3 Core Library__ sometimes manipulates __H3__ indexes internally in the form of the structure type __H3IndexFat__. This heavyweight representation stores an integer mode, base cell and resolution, along with an array of integer digits. It is not meant to be used outside of the C library.
1 change: 0 additions & 1 deletion src/apps/filters/h3ToGeoBoundary.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
#include "coordijk.h"
#include "geoCoord.h"
#include "h3Index.h"
#include "h3IndexFat.h"
#include "h3api.h"
#include "kml.h"
#include "utility.h"
Expand Down
1 change: 0 additions & 1 deletion src/apps/miscapps/generateBaseCellNeighbors.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
*/

#include <baseCells.h>
#include <h3IndexFat.h>
#include <stdlib.h>

const int NUM_DIRS = 6;
Expand Down
40 changes: 20 additions & 20 deletions src/apps/miscapps/h3ToGeoBoundaryHier.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,12 @@
#include "coordijk.h"
#include "geoCoord.h"
#include "h3Index.h"
#include "h3IndexFat.h"
#include "h3api.h"
#include "kml.h"
#include "utility.h"
#include "vec2d.h"

void doCell(const H3IndexFat* hf, int isKmlOut) {
H3Index h = h3FatToH3(hf);

void doCell(H3Index h, int isKmlOut) {
GeoBoundary b;
H3_EXPORT(h3ToGeoBoundary)(h, &b);

Expand All @@ -77,19 +74,22 @@ void doCell(const H3IndexFat* hf, int isKmlOut) {
}
}

void recursiveH3IndexToGeo(H3IndexFat* c, int res, int isKmlOut) {
void recursiveH3IndexToGeo(H3Index h, int res, int isKmlOut) {
for (int d = 0; d < 7; d++) {
c->index[res - 1] = d;
H3_SET_INDEX_DIGIT(h, res, d);

// skip the pentagonal deleted subsequence

if (_isBaseCellPentagon(c->baseCell) && _leadingNonZeroDigit(c) == 1)
if (_isBaseCellPentagon(H3_GET_BASE_CELL(h)) &&
_h3LeadingNonZeroDigit(h) == 1) {
continue;
}

if (res == c->res)
doCell(c, isKmlOut);
else
recursiveH3IndexToGeo(c, res + 1, isKmlOut);
if (res == H3_GET_RESOLUTION(h)) {
doCell(h, isKmlOut);
} else {
recursiveH3IndexToGeo(h, res + 1, isKmlOut);
}
}
}

Expand All @@ -101,10 +101,11 @@ int main(int argc, char* argv[]) {
}

H3Index rootCell = H3_EXPORT(stringToH3)(argv[1]);
H3IndexFat rootCellHf;
h3ToH3Fat(rootCell, &rootCellHf);
if (rootCellHf.baseCell < 0 || rootCellHf.baseCell >= NUM_BASE_CELLS)
int baseCell = H3_GET_BASE_CELL(rootCell);
int rootRes = H3_GET_RESOLUTION(rootCell);
if (baseCell < 0 || baseCell >= NUM_BASE_CELLS) {
error("invalid base cell number");
}

int res = 0;
int isKmlOut = 0;
Expand All @@ -129,7 +130,7 @@ int main(int argc, char* argv[]) {

H3_EXPORT(h3ToString)(rootCell, index, BUFF_SIZE);
sprintf(name, "Cell %s Res %d", index,
((res <= rootCellHf.res) ? rootCellHf.res : res));
((res <= rootRes) ? rootRes : res));
sprintf(desc, "cell boundary");

kmlBoundaryHeader(name, desc);
Expand All @@ -139,12 +140,11 @@ int main(int argc, char* argv[]) {

// generate the points

if (res <= rootCellHf.res) {
doCell(&rootCellHf, isKmlOut);
if (res <= rootRes) {
doCell(rootCell, isKmlOut);
} else {
int rootRes = rootCellHf.res;
rootCellHf.res = res;
recursiveH3IndexToGeo(&rootCellHf, rootRes + 1, isKmlOut);
H3_SET_RESOLUTION(rootCell, res);
recursiveH3IndexToGeo(rootCell, rootRes + 1, isKmlOut);
}

if (isKmlOut) kmlBoundaryFooter();
Expand Down
42 changes: 21 additions & 21 deletions src/apps/miscapps/h3ToGeoHier.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,12 @@
#include "coordijk.h"
#include "geoCoord.h"
#include "h3Index.h"
#include "h3IndexFat.h"
#include "h3api.h"
#include "kml.h"
#include "utility.h"
#include "vec2d.h"

void doCell(const H3IndexFat* hf, int isKmlOut) {
H3Index h = h3FatToH3(hf);

void doCell(H3Index h, int isKmlOut) {
GeoCoord g;
H3_EXPORT(h3ToGeo)(h, &g);

Expand All @@ -78,19 +75,22 @@ void doCell(const H3IndexFat* hf, int isKmlOut) {
}
}

void recursiveH3IndexToGeo(H3IndexFat* c, int res, int isKmlOut) {
void recursiveH3IndexToGeo(H3Index h, int res, int isKmlOut) {
for (int d = 0; d < 7; d++) {
c->index[res - 1] = d;
H3_SET_INDEX_DIGIT(h, res, d);

// skip the pentagonal deleted subsequence

if (_isBaseCellPentagon(c->baseCell) && _leadingNonZeroDigit(c) == 1)
if (_isBaseCellPentagon(H3_GET_BASE_CELL(h)) &&
_h3LeadingNonZeroDigit(h) == 1) {
continue;
}

if (res == c->res)
doCell(c, isKmlOut);
else
recursiveH3IndexToGeo(c, res + 1, isKmlOut);
if (res == H3_GET_RESOLUTION(h)) {
doCell(h, isKmlOut);
} else {
recursiveH3IndexToGeo(h, res + 1, isKmlOut);
}
}
}

Expand All @@ -102,10 +102,11 @@ int main(int argc, char* argv[]) {
}

H3Index rootCell = H3_EXPORT(stringToH3)(argv[1]);
H3IndexFat rootCellHf;
h3ToH3Fat(rootCell, &rootCellHf);
if (rootCellHf.baseCell < 0 || rootCellHf.baseCell >= NUM_BASE_CELLS)
int baseCell = H3_GET_BASE_CELL(rootCell);
int rootRes = H3_GET_RESOLUTION(rootCell);
if (baseCell < 0 || baseCell >= NUM_BASE_CELLS) {
error("invalid base cell number");
}

int res = 0;
int isKmlOut = 0;
Expand All @@ -130,7 +131,7 @@ int main(int argc, char* argv[]) {

H3_EXPORT(h3ToString)(rootCell, index, BUFF_SIZE);
sprintf(name, "Cell %s Res %d", index,
((res <= rootCellHf.res) ? rootCellHf.res : res));
((res <= rootRes) ? rootRes : res));
sprintf(desc, "cell boundary");

kmlBoundaryHeader(name, desc);
Expand All @@ -140,12 +141,11 @@ int main(int argc, char* argv[]) {

// generate the points

if (res <= rootCellHf.res)
doCell(&rootCellHf, isKmlOut);
else {
int rootRes = rootCellHf.res;
rootCellHf.res = res;
recursiveH3IndexToGeo(&rootCellHf, rootRes + 1, isKmlOut);
if (res <= rootRes) {
doCell(rootCell, isKmlOut);
} else {
H3_SET_RESOLUTION(rootCell, res);
recursiveH3IndexToGeo(rootCell, rootRes + 1, isKmlOut);
}

if (isKmlOut) kmlBoundaryFooter();
Expand Down
1 change: 1 addition & 0 deletions src/apps/testapps/testCompact.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include <stdlib.h>
#include "constants.h"
#include "h3Index.h"
#include "test.h"

Expand Down
23 changes: 23 additions & 0 deletions src/apps/testapps/testH3Index.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "constants.h"
#include "h3Index.h"
#include "test.h"
#include "utility.h"
Expand All @@ -47,6 +48,28 @@ TEST(h3IsValidDigits) {
"h3IsValid failed on invalid unused digits");
}

TEST(h3IsValidBaseCell) {
for (int i = 0; i < NUM_BASE_CELLS; i++) {
H3Index h = H3_INIT;
H3_SET_MODE(h, H3_HEXAGON_MODE);
H3_SET_BASE_CELL(h, i);
char failureMessage[BUFF_SIZE];
sprintf(failureMessage, "h3IsValid failed on base cell %d", i);
t_assert(h3IsValid(h), failureMessage);

t_assert(H3_EXPORT(h3GetBaseCell)(h) == i,
"failed to recover base cell");
}
}

TEST(h3FatIsValidBaseCellInvalid) {
H3Index hWrongBaseCell = H3_INIT;
H3_SET_MODE(hWrongBaseCell, H3_HEXAGON_MODE);
H3_SET_BASE_CELL(hWrongBaseCell, NUM_BASE_CELLS);
t_assert(!h3IsValid(hWrongBaseCell),
"h3IsValid failed on invalid base cell");
}

TEST(h3ToString) {
const size_t bufSz = 17;
char buf[17] = {0};
Expand Down
Loading

0 comments on commit 6e0ae41

Please sign in to comment.