h3 3.4.4 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +2 -1
  5. data/ext/h3/Makefile +1 -1
  6. data/ext/h3/src/.gitignore +2 -1
  7. data/ext/h3/src/CHANGELOG.md +9 -0
  8. data/ext/h3/src/CMakeLists.txt +72 -45
  9. data/ext/h3/src/RELEASE.md +2 -1
  10. data/ext/h3/src/VERSION +1 -1
  11. data/ext/h3/src/docs/api/hierarchy.md +2 -0
  12. data/ext/h3/src/docs/api/indexing.md +3 -1
  13. data/ext/h3/src/docs/api/inspection.md +20 -0
  14. data/ext/h3/src/docs/api/misc.md +2 -0
  15. data/ext/h3/src/docs/api/regions.md +2 -0
  16. data/ext/h3/src/docs/api/traversal.md +2 -0
  17. data/ext/h3/src/docs/api/uniedge.md +2 -0
  18. data/ext/h3/src/docs/community/bindings.md +4 -0
  19. data/ext/h3/src/docs/community/tutorials.md +12 -0
  20. data/ext/h3/src/scripts/update_version.sh +50 -0
  21. data/ext/h3/src/src/apps/applib/include/args.h +122 -0
  22. data/ext/h3/src/src/apps/applib/include/utility.h +5 -62
  23. data/ext/h3/src/src/apps/applib/lib/args.c +216 -0
  24. data/ext/h3/src/src/apps/applib/lib/utility.c +40 -206
  25. data/ext/h3/src/src/apps/filters/geoToH3.c +7 -9
  26. data/ext/h3/src/src/apps/filters/h3ToComponents.c +50 -47
  27. data/ext/h3/src/src/apps/filters/h3ToGeo.c +7 -30
  28. data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +7 -27
  29. data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +42 -25
  30. data/ext/h3/src/src/apps/filters/hexRange.c +43 -24
  31. data/ext/h3/src/src/apps/filters/kRing.c +4 -4
  32. data/ext/h3/src/src/apps/filters/localIjToH3.c +63 -21
  33. data/ext/h3/src/src/apps/miscapps/h3ToGeoBoundaryHier.c +68 -44
  34. data/ext/h3/src/src/apps/miscapps/h3ToGeoHier.c +68 -43
  35. data/ext/h3/src/src/apps/miscapps/h3ToHier.c +48 -37
  36. data/ext/h3/src/src/apps/testapps/mkRandGeo.c +32 -27
  37. data/ext/h3/src/src/apps/testapps/mkRandGeoBoundary.c +33 -28
  38. data/ext/h3/src/src/apps/testapps/testH3GetFaces.c +136 -0
  39. data/ext/h3/src/src/h3lib/include/faceijk.h +19 -7
  40. data/ext/h3/src/src/h3lib/include/h3api.h.in +12 -1
  41. data/ext/h3/src/src/h3lib/lib/algos.c +7 -2
  42. data/ext/h3/src/src/h3lib/lib/faceijk.c +135 -103
  43. data/ext/h3/src/src/h3lib/lib/h3Index.c +86 -5
  44. data/lib/h3/bindings/private.rb +1 -0
  45. data/lib/h3/inspection.rb +34 -0
  46. data/lib/h3/version.rb +1 -1
  47. data/spec/inspection_spec.rb +33 -1
  48. metadata +6 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2016-2018 Uber Technologies, Inc.
2
+ * Copyright 2016-2019 Uber Technologies, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -394,6 +394,17 @@ int H3_EXPORT(h3IsResClassIII)(H3Index h);
394
394
  int H3_EXPORT(h3IsPentagon)(H3Index h);
395
395
  /** @} */
396
396
 
397
+ /** @defgroup h3GetFaces h3GetFaces
398
+ * Functions for h3GetFaces
399
+ * @{
400
+ */
401
+ /** @brief Max number of icosahedron faces intersected by an index */
402
+ int H3_EXPORT(maxFaceCount)(H3Index h3);
403
+
404
+ /** @brief Find all icosahedron faces intersected by a given H3 index */
405
+ void H3_EXPORT(h3GetFaces)(H3Index h3, int *out);
406
+ /** @} */
407
+
397
408
  /** @defgroup h3IndexesAreNeighbors h3IndexesAreNeighbors
398
409
  * Functions for h3IndexesAreNeighbors
399
410
  * @{
@@ -539,12 +539,17 @@ int H3_EXPORT(hexRanges)(H3Index* h3Set, int length, int k, H3Index* out) {
539
539
  }
540
540
 
541
541
  /**
542
- * Returns the hollow hexagonal ring centered at origin with sides of length k.
542
+ * Returns the "hollow" ring of hexagons at exactly grid distance k from
543
+ * the origin hexagon. In particular, k=0 returns just the origin hexagon.
544
+ *
545
+ * A nonzero failure code may be returned in some cases, for example,
546
+ * if a pentagon is encountered.
547
+ * Failure cases may be fixed in future versions.
543
548
  *
544
549
  * @param origin Origin location.
545
550
  * @param k k >= 0
546
551
  * @param out Array which must be of size 6 * k (or 1 if k == 0)
547
- * @return 0 if no pentagonal distortion was encountered.
552
+ * @return 0 if successful; nonzero otherwise.
548
553
  */
549
554
  int H3_EXPORT(hexRing)(H3Index origin, int k, H3Index* out) {
550
555
  // Short-circuit on 'identity' ring
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2016-2017 Uber Technologies, Inc.
2
+ * Copyright 2016-2019 Uber Technologies, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -502,60 +502,10 @@ void _faceIjkToGeo(const FaceIJK* h, int res, GeoCoord* g) {
502
502
  * @param g The spherical coordinates of the cell boundary.
503
503
  */
504
504
  void _faceIjkPentToGeoBoundary(const FaceIJK* h, int res, GeoBoundary* g) {
505
- // the vertexes of an origin-centered pentagon in a Class II resolution on a
506
- // substrate grid with aperture sequence 33r. The aperture 3 gets us the
507
- // vertices, and the 3r gets us back to Class II.
508
- // vertices listed ccw from the i-axes
509
- CoordIJK vertsCII[NUM_PENT_VERTS] = {
510
- {2, 1, 0}, // 0
511
- {1, 2, 0}, // 1
512
- {0, 2, 1}, // 2
513
- {0, 1, 2}, // 3
514
- {1, 0, 2}, // 4
515
- };
516
-
517
- // the vertexes of an origin-centered pentagon in a Class III resolution on
518
- // a substrate grid with aperture sequence 33r7r. The aperture 3 gets us the
519
- // vertices, and the 3r7r gets us to Class II. vertices listed ccw from the
520
- // i-axes
521
- CoordIJK vertsCIII[NUM_PENT_VERTS] = {
522
- {5, 4, 0}, // 0
523
- {1, 5, 0}, // 1
524
- {0, 5, 4}, // 2
525
- {0, 1, 5}, // 3
526
- {4, 0, 5}, // 4
527
- };
528
-
529
- // get the correct set of substrate vertices for this resolution
530
- CoordIJK* verts;
531
- if (isResClassIII(res))
532
- verts = vertsCIII;
533
- else
534
- verts = vertsCII;
535
-
536
- // adjust the center point to be in an aperture 33r substrate grid
537
- // these should be composed for speed
538
- FaceIJK centerIJK = *h;
539
- _downAp3(&centerIJK.coord);
540
- _downAp3r(&centerIJK.coord);
541
-
542
- // if res is Class III we need to add a cw aperture 7 to get to
543
- // icosahedral Class II
544
505
  int adjRes = res;
545
- if (isResClassIII(res)) {
546
- _downAp7r(&centerIJK.coord);
547
- adjRes++;
548
- }
549
-
550
- // The center point is now in the same substrate grid as the origin
551
- // cell vertices. Add the center point substate coordinates
552
- // to each vertex to translate the vertices to that cell.
506
+ FaceIJK centerIJK = *h;
553
507
  FaceIJK fijkVerts[NUM_PENT_VERTS];
554
- for (int v = 0; v < NUM_PENT_VERTS; v++) {
555
- fijkVerts[v].face = centerIJK.face;
556
- _ijkAdd(&centerIJK.coord, &verts[v], &fijkVerts[v].coord);
557
- _ijkNormalize(&fijkVerts[v].coord);
558
- }
508
+ _faceIjkPentToVerts(&centerIJK, &adjRes, fijkVerts);
559
509
 
560
510
  // convert each vertex to lat/lon
561
511
  // adjust the face of each vertex as appropriate and introduce
@@ -567,16 +517,7 @@ void _faceIjkPentToGeoBoundary(const FaceIJK* h, int res, GeoBoundary* g) {
567
517
 
568
518
  FaceIJK fijk = fijkVerts[v];
569
519
 
570
- int pentLeading4 = 0;
571
- int overage = _adjustOverageClassII(&fijk, adjRes, pentLeading4, 1);
572
- if (overage == 2) // in a different triangle
573
- {
574
- while (1) {
575
- overage = _adjustOverageClassII(&fijk, adjRes, pentLeading4, 1);
576
- if (overage != 2) // not in a different triangle
577
- break;
578
- }
579
- }
520
+ _adjustPentVertOverage(&fijk, adjRes);
580
521
 
581
522
  // all Class III pentagon edges cross icosa edges
582
523
  // note that Class II pentagons have vertices on the edge,
@@ -656,77 +597,87 @@ void _faceIjkPentToGeoBoundary(const FaceIJK* h, int res, GeoBoundary* g) {
656
597
  }
657
598
 
658
599
  /**
659
- * Generates the cell boundary in spherical coordinates for a cell given by a
660
- * FaceIJK address at a specified resolution.
600
+ * Get the vertices of a pentagon cell as substrate FaceIJK addresses
661
601
  *
662
- * @param h The FaceIJK address of the cell.
663
- * @param res The H3 resolution of the cell.
664
- * @param isPentagon Whether or not the cell is a pentagon.
665
- * @param g The spherical coordinates of the cell boundary.
602
+ * @param fijk The FaceIJK address of the cell.
603
+ * @param res The H3 resolution of the cell. This may be adjusted if
604
+ * necessary for the substrate grid resolution.
605
+ * @param fijkVerts Output array for the vertices
666
606
  */
667
- void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
668
- GeoBoundary* g) {
669
- if (isPentagon) {
670
- _faceIjkPentToGeoBoundary(h, res, g);
671
- return;
672
- }
673
-
674
- // the vertexes of an origin-centered cell in a Class II resolution on a
607
+ void _faceIjkPentToVerts(FaceIJK* fijk, int* res, FaceIJK* fijkVerts) {
608
+ // the vertexes of an origin-centered pentagon in a Class II resolution on a
675
609
  // substrate grid with aperture sequence 33r. The aperture 3 gets us the
676
610
  // vertices, and the 3r gets us back to Class II.
677
611
  // vertices listed ccw from the i-axes
678
- CoordIJK vertsCII[NUM_HEX_VERTS] = {
612
+ CoordIJK vertsCII[NUM_PENT_VERTS] = {
679
613
  {2, 1, 0}, // 0
680
614
  {1, 2, 0}, // 1
681
615
  {0, 2, 1}, // 2
682
616
  {0, 1, 2}, // 3
683
617
  {1, 0, 2}, // 4
684
- {2, 0, 1} // 5
685
618
  };
686
619
 
687
- // the vertexes of an origin-centered cell in a Class III resolution on a
688
- // substrate grid with aperture sequence 33r7r. The aperture 3 gets us the
689
- // vertices, and the 3r7r gets us to Class II.
690
- // vertices listed ccw from the i-axes
691
- CoordIJK vertsCIII[NUM_HEX_VERTS] = {
620
+ // the vertexes of an origin-centered pentagon in a Class III resolution on
621
+ // a substrate grid with aperture sequence 33r7r. The aperture 3 gets us the
622
+ // vertices, and the 3r7r gets us to Class II. vertices listed ccw from the
623
+ // i-axes
624
+ CoordIJK vertsCIII[NUM_PENT_VERTS] = {
692
625
  {5, 4, 0}, // 0
693
626
  {1, 5, 0}, // 1
694
627
  {0, 5, 4}, // 2
695
628
  {0, 1, 5}, // 3
696
629
  {4, 0, 5}, // 4
697
- {5, 0, 1} // 5
698
630
  };
699
631
 
700
632
  // get the correct set of substrate vertices for this resolution
701
633
  CoordIJK* verts;
702
- if (isResClassIII(res))
634
+ if (isResClassIII(*res))
703
635
  verts = vertsCIII;
704
636
  else
705
637
  verts = vertsCII;
706
638
 
707
639
  // adjust the center point to be in an aperture 33r substrate grid
708
640
  // these should be composed for speed
709
- FaceIJK centerIJK = *h;
710
- _downAp3(&centerIJK.coord);
711
- _downAp3r(&centerIJK.coord);
641
+ _downAp3(&fijk->coord);
642
+ _downAp3r(&fijk->coord);
712
643
 
713
644
  // if res is Class III we need to add a cw aperture 7 to get to
714
645
  // icosahedral Class II
715
- int adjRes = res;
716
- if (isResClassIII(res)) {
717
- _downAp7r(&centerIJK.coord);
718
- adjRes++;
646
+ if (isResClassIII(*res)) {
647
+ _downAp7r(&fijk->coord);
648
+ *res += 1;
719
649
  }
720
650
 
721
651
  // The center point is now in the same substrate grid as the origin
722
652
  // cell vertices. Add the center point substate coordinates
723
653
  // to each vertex to translate the vertices to that cell.
724
- FaceIJK fijkVerts[NUM_HEX_VERTS];
725
- for (int v = 0; v < NUM_HEX_VERTS; v++) {
726
- fijkVerts[v].face = centerIJK.face;
727
- _ijkAdd(&centerIJK.coord, &verts[v], &fijkVerts[v].coord);
654
+ for (int v = 0; v < NUM_PENT_VERTS; v++) {
655
+ fijkVerts[v].face = fijk->face;
656
+ _ijkAdd(&fijk->coord, &verts[v], &fijkVerts[v].coord);
728
657
  _ijkNormalize(&fijkVerts[v].coord);
729
658
  }
659
+ }
660
+
661
+ /**
662
+ * Generates the cell boundary in spherical coordinates for a cell given by a
663
+ * FaceIJK address at a specified resolution.
664
+ *
665
+ * @param h The FaceIJK address of the cell.
666
+ * @param res The H3 resolution of the cell.
667
+ * @param isPentagon Whether or not the cell is a pentagon.
668
+ * @param g The spherical coordinates of the cell boundary.
669
+ */
670
+ void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
671
+ GeoBoundary* g) {
672
+ if (isPentagon) {
673
+ _faceIjkPentToGeoBoundary(h, res, g);
674
+ return;
675
+ }
676
+
677
+ int adjRes = res;
678
+ FaceIJK centerIJK = *h;
679
+ FaceIJK fijkVerts[NUM_HEX_VERTS];
680
+ _faceIjkToVerts(&centerIJK, &adjRes, fijkVerts);
730
681
 
731
682
  // convert each vertex to lat/lon
732
683
  // adjust the face of each vertex as appropriate and introduce
@@ -819,6 +770,70 @@ void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
819
770
  }
820
771
  }
821
772
 
773
+ /**
774
+ * Get the vertices of a cell as substrate FaceIJK addresses
775
+ *
776
+ * @param fijk The FaceIJK address of the cell.
777
+ * @param res The H3 resolution of the cell. This may be adjusted if
778
+ * necessary for the substrate grid resolution.
779
+ * @param fijkVerts Output array for the vertices
780
+ */
781
+ void _faceIjkToVerts(FaceIJK* fijk, int* res, FaceIJK* fijkVerts) {
782
+ // the vertexes of an origin-centered cell in a Class II resolution on a
783
+ // substrate grid with aperture sequence 33r. The aperture 3 gets us the
784
+ // vertices, and the 3r gets us back to Class II.
785
+ // vertices listed ccw from the i-axes
786
+ CoordIJK vertsCII[NUM_HEX_VERTS] = {
787
+ {2, 1, 0}, // 0
788
+ {1, 2, 0}, // 1
789
+ {0, 2, 1}, // 2
790
+ {0, 1, 2}, // 3
791
+ {1, 0, 2}, // 4
792
+ {2, 0, 1} // 5
793
+ };
794
+
795
+ // the vertexes of an origin-centered cell in a Class III resolution on a
796
+ // substrate grid with aperture sequence 33r7r. The aperture 3 gets us the
797
+ // vertices, and the 3r7r gets us to Class II.
798
+ // vertices listed ccw from the i-axes
799
+ CoordIJK vertsCIII[NUM_HEX_VERTS] = {
800
+ {5, 4, 0}, // 0
801
+ {1, 5, 0}, // 1
802
+ {0, 5, 4}, // 2
803
+ {0, 1, 5}, // 3
804
+ {4, 0, 5}, // 4
805
+ {5, 0, 1} // 5
806
+ };
807
+
808
+ // get the correct set of substrate vertices for this resolution
809
+ CoordIJK* verts;
810
+ if (isResClassIII(*res))
811
+ verts = vertsCIII;
812
+ else
813
+ verts = vertsCII;
814
+
815
+ // adjust the center point to be in an aperture 33r substrate grid
816
+ // these should be composed for speed
817
+ _downAp3(&fijk->coord);
818
+ _downAp3r(&fijk->coord);
819
+
820
+ // if res is Class III we need to add a cw aperture 7 to get to
821
+ // icosahedral Class II
822
+ if (isResClassIII(*res)) {
823
+ _downAp7r(&fijk->coord);
824
+ *res += 1;
825
+ }
826
+
827
+ // The center point is now in the same substrate grid as the origin
828
+ // cell vertices. Add the center point substate coordinates
829
+ // to each vertex to translate the vertices to that cell.
830
+ for (int v = 0; v < NUM_HEX_VERTS; v++) {
831
+ fijkVerts[v].face = fijk->face;
832
+ _ijkAdd(&fijk->coord, &verts[v], &fijkVerts[v].coord);
833
+ _ijkNormalize(&fijkVerts[v].coord);
834
+ }
835
+ }
836
+
822
837
  /**
823
838
  * Adjusts a FaceIJK address in place so that the resulting cell address is
824
839
  * relative to the correct icosahedral face.
@@ -831,9 +846,9 @@ void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
831
846
  * @return 0 if on original face (no overage); 1 if on face edge (only occurs
832
847
  * on substrate grids); 2 if overage on new face interior
833
848
  */
834
- int _adjustOverageClassII(FaceIJK* fijk, int res, int pentLeading4,
835
- int substrate) {
836
- int overage = 0;
849
+ Overage _adjustOverageClassII(FaceIJK* fijk, int res, int pentLeading4,
850
+ int substrate) {
851
+ Overage overage = NO_OVERAGE;
837
852
 
838
853
  CoordIJK* ijk = &fijk->coord;
839
854
 
@@ -843,10 +858,10 @@ int _adjustOverageClassII(FaceIJK* fijk, int res, int pentLeading4,
843
858
 
844
859
  // check for overage
845
860
  if (substrate && ijk->i + ijk->j + ijk->k == maxDim) // on edge
846
- overage = 1;
861
+ overage = FACE_EDGE;
847
862
  else if (ijk->i + ijk->j + ijk->k > maxDim) // overage
848
863
  {
849
- overage = 2;
864
+ overage = NEW_FACE;
850
865
 
851
866
  const FaceOrientIJK* fijkOrient;
852
867
  if (ijk->k > 0) {
@@ -886,8 +901,25 @@ int _adjustOverageClassII(FaceIJK* fijk, int res, int pentLeading4,
886
901
 
887
902
  // overage points on pentagon boundaries can end up on edges
888
903
  if (substrate && ijk->i + ijk->j + ijk->k == maxDim) // on edge
889
- overage = 1;
904
+ overage = FACE_EDGE;
890
905
  }
891
906
 
892
907
  return overage;
893
908
  }
909
+
910
+ /**
911
+ * Adjusts a FaceIJK address for a pentagon vertex in a substrate grid in
912
+ * place so that the resulting cell address is relative to the correct
913
+ * icosahedral face.
914
+ *
915
+ * @param fijk The FaceIJK address of the cell.
916
+ * @param res The H3 resolution of the cell.
917
+ */
918
+ Overage _adjustPentVertOverage(FaceIJK* fijk, int res) {
919
+ int pentLeading4 = 0;
920
+ Overage overage;
921
+ do {
922
+ overage = _adjustOverageClassII(fijk, res, pentLeading4, 1);
923
+ } while (overage == NEW_FACE);
924
+ return overage;
925
+ }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2016-2018 Uber Technologies, Inc.
2
+ * Copyright 2016-2019 Uber Technologies, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -739,13 +739,12 @@ void _h3ToFaceIjk(H3Index h, FaceIJK* fijk) {
739
739
  // a pentagon base cell with a leading 4 digit requires special handling
740
740
  int pentLeading4 =
741
741
  (_isBaseCellPentagon(baseCell) && _h3LeadingNonZeroDigit(h) == 4);
742
- if (_adjustOverageClassII(fijk, res, pentLeading4, 0)) {
742
+ if (_adjustOverageClassII(fijk, res, pentLeading4, 0) != NO_OVERAGE) {
743
743
  // if the base cell is a pentagon we have the potential for secondary
744
744
  // overages
745
745
  if (_isBaseCellPentagon(baseCell)) {
746
- while (1) {
747
- if (!_adjustOverageClassII(fijk, res, 0, 0)) break;
748
- }
746
+ while (_adjustOverageClassII(fijk, res, 0, 0) != NO_OVERAGE)
747
+ continue;
749
748
  }
750
749
 
751
750
  if (res != H3_GET_RESOLUTION(h)) _upAp7r(&fijk->coord);
@@ -779,6 +778,88 @@ void H3_EXPORT(h3ToGeoBoundary)(H3Index h3, GeoBoundary* gb) {
779
778
  H3_EXPORT(h3IsPentagon)(h3), gb);
780
779
  }
781
780
 
781
+ /**
782
+ * Returns the max number of possible icosahedron faces an H3 index
783
+ * may intersect.
784
+ *
785
+ * @return int count of faces
786
+ */
787
+ int H3_EXPORT(maxFaceCount)(H3Index h3) {
788
+ // a pentagon always intersects 5 faces, a hexagon never intersects more
789
+ // than 2 (but may only intersect 1)
790
+ return H3_EXPORT(h3IsPentagon)(h3) ? 5 : 2;
791
+ }
792
+
793
+ /**
794
+ * Find all icosahedron faces intersected by a given H3 index, represented
795
+ * as integers from 0-19. The array is sparse; since 0 is a valid value,
796
+ * invalid array values are represented as -1. It is the responsibility of
797
+ * the caller to filter out invalid values.
798
+ *
799
+ * @param h3 The H3 index
800
+ * @param out Output array. Must be of size maxFaceCount(h3).
801
+ */
802
+ void H3_EXPORT(h3GetFaces)(H3Index h3, int* out) {
803
+ int res = H3_GET_RESOLUTION(h3);
804
+ int isPentagon = H3_EXPORT(h3IsPentagon)(h3);
805
+
806
+ // We can't use the vertex-based approach here for class II pentagons,
807
+ // because all their vertices are on the icosahedron edges. Their
808
+ // direct child pentagons cross the same faces, so use those instead.
809
+ if (isPentagon && !isResClassIII(res)) {
810
+ // Note that this would not work for res 15, but this is only run on
811
+ // Class II pentagons, it should never be invoked for a res 15 index.
812
+ H3Index childPentagon = makeDirectChild(h3, 0);
813
+ H3_EXPORT(h3GetFaces)(childPentagon, out);
814
+ return;
815
+ }
816
+
817
+ // convert to FaceIJK
818
+ FaceIJK fijk;
819
+ _h3ToFaceIjk(h3, &fijk);
820
+
821
+ // Get all vertices as FaceIJK addresses. For simplicity, always
822
+ // initialize the array with 6 verts, ignoring the last one for pentagons
823
+ FaceIJK fijkVerts[NUM_HEX_VERTS];
824
+ int vertexCount;
825
+
826
+ if (isPentagon) {
827
+ vertexCount = NUM_PENT_VERTS;
828
+ _faceIjkPentToVerts(&fijk, &res, fijkVerts);
829
+ } else {
830
+ vertexCount = NUM_HEX_VERTS;
831
+ _faceIjkToVerts(&fijk, &res, fijkVerts);
832
+ }
833
+
834
+ // We may not use all of the slots in the output array,
835
+ // so fill with invalid values to indicate unused slots
836
+ int faceCount = H3_EXPORT(maxFaceCount)(h3);
837
+ for (int i = 0; i < faceCount; i++) {
838
+ out[i] = INVALID_FACE;
839
+ }
840
+
841
+ // add each vertex face, using the output array as a hash set
842
+ for (int i = 0; i < vertexCount; i++) {
843
+ FaceIJK* vert = &fijkVerts[i];
844
+
845
+ // Adjust overage, determining whether this vertex is
846
+ // on another face
847
+ if (isPentagon) {
848
+ _adjustPentVertOverage(vert, res);
849
+ } else {
850
+ _adjustOverageClassII(vert, res, 0, 1);
851
+ }
852
+
853
+ // Save the face to the output array
854
+ int face = vert->face;
855
+ int pos = 0;
856
+ // Find the first empty output position, or the first position
857
+ // matching the current face
858
+ while (out[pos] != INVALID_FACE && out[pos] != face) pos++;
859
+ out[pos] = face;
860
+ }
861
+ }
862
+
782
863
  /**
783
864
  * Returns whether or not a resolution is a Class III grid. Note that odd
784
865
  * resolutions are Class III and even resolutions are Class II.