h3 3.4.4 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.