h3 3.6.1 → 3.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32f9595b2e8746f59aaef1c082fc3527a7eb3d7594d7eac1a59cb5875df6af3d
4
- data.tar.gz: 8fd9c4ed2317a0211b4d3fa6360aede580bff5db691605b7fdd33b299720ba3f
3
+ metadata.gz: c5f225736d5df411fd63eb2cad74c153ba96d6a659cf603ba781bab3497dfcc9
4
+ data.tar.gz: cc45bd99735019ae9d8442ca948df0ce64dd70aa82fa47eabfe2966ea0d76ea2
5
5
  SHA512:
6
- metadata.gz: 4e0a51a2bdcf92096406af99d3823359768b99291f96be9ac6d113363c09efb71513cf09944eca1155549b63bbab4c628e2a6f89f8d77817df4029155375072e
7
- data.tar.gz: 1c672e3d6d2262dee4bae5bf65587a870c9053b1815ec7ee34798fae228aed5bd338d57883ebb594f81b6c959006af86c460ddca473e4db401631e2400a11dcd
6
+ metadata.gz: 84d534f96a5772628a642ac773224af9d907319a4a576cbb7c772773ba8b2ea3814c9118b90e69f617834484b7e10f117da9f9f4a98be99124238ba105532767
7
+ data.tar.gz: '098daf9d6a37dfe0a1a7b4458a2d9875ff9456c1f264b61328006f7bc45ac91031f6f24aebd508c1826e884b9f0cbf457daf75691026da83031bf0312d7dd422'
@@ -6,6 +6,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  We track the MAJOR and MINOR version levels of Uber's H3 project (https://github.com/uber/h3) but maintain independent patch levels so we can make small fixes and non breaking changes.
8
8
 
9
+ ## [3.6.2] - 2020-1-8
10
+ ### Changed
11
+ - Revert new polyfill algorithm until reported issues are fixed.
12
+ - Remove deprecated methods: (#66)
13
+
14
+ ## [3.6.1] - 2019-11-23
15
+ ### Fixed
16
+ - `compact` handles zero length input correctly.
17
+ - `bboxHexRadius` scaling factor adjusted to guarantee containment for `polyfill`.
18
+ - `polyfill` new algorithm for up to 3x perf boost.
19
+ - Fix CMake targets for KML generation.
20
+
9
21
  ## [3.6.0] - 2019-8-14
10
22
  ### Added
11
23
  - `center_child` method to find center child at given resolution (#62).
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- h3 (3.6.1)
4
+ h3 (3.6.2)
5
5
  ffi (~> 1.9)
6
6
  rgeo-geojson (~> 2.1)
7
7
  zeitwerk (~> 2.1)
@@ -17,7 +17,7 @@ GEM
17
17
  tins (~> 1.6)
18
18
  diff-lcs (1.3)
19
19
  docile (1.3.1)
20
- ffi (1.11.2)
20
+ ffi (1.11.3)
21
21
  json (2.1.0)
22
22
  rake (12.3.2)
23
23
  rgeo (2.1.1)
@@ -46,7 +46,7 @@ GEM
46
46
  thor (0.19.4)
47
47
  tins (1.20.2)
48
48
  yard (0.9.20)
49
- zeitwerk (2.2.1)
49
+ zeitwerk (2.2.2)
50
50
 
51
51
  PLATFORMS
52
52
  ruby
@@ -59,4 +59,4 @@ DEPENDENCIES
59
59
  yard (~> 0.9)
60
60
 
61
61
  BUNDLED WITH
62
- 1.17.2
62
+ 1.17.3
@@ -31,7 +31,7 @@ addons:
31
31
  matrix:
32
32
  include:
33
33
  # Check that clang-format doesn't detect some files are not formatted.
34
- - env: NAME="Formatting check"
34
+ - name: "Formatting check"
35
35
  compiler: clang
36
36
  addons:
37
37
  apt:
@@ -41,7 +41,7 @@ matrix:
41
41
  - clang-format-5.0
42
42
  script: make format && git diff --exit-code
43
43
  # Submit coverage report to Coveralls.io, also test that prefixing works.
44
- - env: NAME="Coverage report"
44
+ - name: "Coverage and FOSSA report"
45
45
  compiler: gcc
46
46
  addons:
47
47
  apt:
@@ -50,12 +50,20 @@ matrix:
50
50
  install:
51
51
  - gem install coveralls-lcov
52
52
  before_script:
53
+ - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash"
53
54
  - cmake -DCMAKE_BUILD_TYPE=Debug -DWARNINGS_AS_ERRORS=ON -DH3_PREFIX=testprefix_ .
54
55
  script:
55
- - make && make coverage
56
+ - make
57
+ - make coverage
58
+ # Test building the website also - needed for FOSSA to pick up dependencies
59
+ - cd website
60
+ - npm install
61
+ - npm run build
62
+ - cd ..
63
+ - 'if [ -n "$FOSSA_API_KEY" ]; then fossa; fi'
56
64
  after_success:
57
65
  - coveralls-lcov coverage.cleaned.info
58
- - env: NAME="Valgrind test"
66
+ - name: "Valgrind test"
59
67
  compiler: gcc
60
68
  addons:
61
69
  apt:
@@ -66,9 +74,9 @@ matrix:
66
74
  script:
67
75
  - make
68
76
  - CTEST_OUTPUT_ON_FAILURE=1 make test-fast
69
- - env: NAME="Mac OSX (Xcode 8)"
77
+ - name: "Mac OSX (Xcode 8)"
70
78
  os: osx
71
- - env: NAME="binding-functions target"
79
+ - name: "binding-functions target"
72
80
  script:
73
81
  - make binding-functions
74
82
  # Check that the file exists and has contents
@@ -7,6 +7,9 @@ The public API of this library consists of the functions declared in file
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.6.2] - 2019-12-9
11
+ - Revert new `polyfill` algorithm until reported issues are fixed. (#293)
12
+
10
13
  ## [3.6.1] - 2019-11-11
11
14
  ### Fixed
12
15
  - `compact` handles zero length input correctly. (#278)
@@ -1 +1 @@
1
- 3.6.1
1
+ 3.6.2
@@ -64,13 +64,13 @@ SUITE(polyfill) {
64
64
 
65
65
  TEST(maxPolyfillSize) {
66
66
  int numHexagons = H3_EXPORT(maxPolyfillSize)(&sfGeoPolygon, 9);
67
- t_assert(numHexagons == 3457, "got expected max polyfill size");
67
+ t_assert(numHexagons == 7057, "got expected max polyfill size");
68
68
 
69
69
  numHexagons = H3_EXPORT(maxPolyfillSize)(&holeGeoPolygon, 9);
70
- t_assert(numHexagons == 3457, "got expected max polyfill size (hole)");
70
+ t_assert(numHexagons == 7057, "got expected max polyfill size (hole)");
71
71
 
72
72
  numHexagons = H3_EXPORT(maxPolyfillSize)(&emptyGeoPolygon, 9);
73
- t_assert(numHexagons == 3, "got expected max polyfill size (empty)");
73
+ t_assert(numHexagons == 1, "got expected max polyfill size (empty)");
74
74
  }
75
75
 
76
76
  TEST(polyfill) {
@@ -40,12 +40,4 @@ void h3SetToVertexGraph(const H3Index* h3Set, const int numHexes,
40
40
  // Create a LinkedGeoPolygon from a vertex graph
41
41
  void _vertexGraphToLinkedGeo(VertexGraph* graph, LinkedGeoPolygon* out);
42
42
 
43
- // Internal function for polyfill that traces a geofence with hexagons of a
44
- // specific size
45
- int _getEdgeHexagons(const Geofence* geofence, int numHexagons, int res,
46
- int* numSearchHexes, H3Index* search, H3Index* found);
47
-
48
- // The new polyfill algorithm. Separated out because it can theoretically fail
49
- int _polyfillInternal(const GeoPolygon* geoPolygon, int res, H3Index* out);
50
-
51
43
  #endif
@@ -37,8 +37,6 @@ bool bboxIsTransmeridian(const BBox* bbox);
37
37
  void bboxCenter(const BBox* bbox, GeoCoord* center);
38
38
  bool bboxContains(const BBox* bbox, const GeoCoord* point);
39
39
  bool bboxEquals(const BBox* b1, const BBox* b2);
40
- int bboxHexEstimate(const BBox* bbox, int res);
41
- int lineHexEstimate(const GeoCoord* origin, const GeoCoord* destination,
42
- int res);
40
+ int bboxHexRadius(const BBox* bbox, int res);
43
41
 
44
42
  #endif
@@ -41,7 +41,6 @@
41
41
  #define HEX_RANGE_SUCCESS 0
42
42
  #define HEX_RANGE_PENTAGON 1
43
43
  #define HEX_RANGE_K_SUBSEQUENCE 2
44
- #define MAX_ONE_RING_SIZE 7
45
44
 
46
45
  /**
47
46
  * Directions used for traversing a hexagonal ring counterclockwise around
@@ -624,8 +623,9 @@ int H3_EXPORT(hexRing)(H3Index origin, int k, H3Index* out) {
624
623
  * maxPolyfillSize returns the number of hexagons to allocate space for when
625
624
  * performing a polyfill on the given GeoJSON-like data structure.
626
625
  *
627
- * The size is the maximum of either the number of points in the geofence or the
628
- * number of hexagons in the bounding box of the geofence.
626
+ * Currently a laughably padded response, being a k-ring that wholly contains
627
+ * a bounding box of the GeoJSON, but still less wasted memory than initializing
628
+ * a Python application? ;)
629
629
  *
630
630
  * @param geoPolygon A GeoJSON-like data structure indicating the poly to fill
631
631
  * @param res Hexagon resolution (0-15)
@@ -634,18 +634,12 @@ int H3_EXPORT(hexRing)(H3Index origin, int k, H3Index* out) {
634
634
  int H3_EXPORT(maxPolyfillSize)(const GeoPolygon* geoPolygon, int res) {
635
635
  // Get the bounding box for the GeoJSON-like struct
636
636
  BBox bbox;
637
- const Geofence geofence = geoPolygon->geofence;
638
- bboxFromGeofence(&geofence, &bbox);
639
- int numHexagons = bboxHexEstimate(&bbox, res);
640
- // This algorithm assumes that the number of vertices is usually less than
641
- // the number of hexagons, but when it's wrong, this will keep it from
642
- // failing
643
- int totalVerts = geofence.numVerts;
644
- for (int i = 0; i < geoPolygon->numHoles; i++) {
645
- totalVerts += geoPolygon->holes[i].numVerts;
646
- }
647
- if (numHexagons < totalVerts) numHexagons = totalVerts;
648
- return numHexagons;
637
+ bboxFromGeofence(&geoPolygon->geofence, &bbox);
638
+ int minK = bboxHexRadius(&bbox, res);
639
+
640
+ // The total number of hexagons to allocate can now be determined by
641
+ // the k-ring hex allocation helper function.
642
+ return H3_EXPORT(maxKringSize)(minK);
649
643
  }
650
644
 
651
645
  /**
@@ -653,108 +647,15 @@ int H3_EXPORT(maxPolyfillSize)(const GeoPolygon* geoPolygon, int res) {
653
647
  * zeroed memory, and fills it with the hexagons that are contained by
654
648
  * the GeoJSON-like data structure.
655
649
  *
656
- * This implementation traces the GeoJSON geofence(s) in cartesian space with
657
- * hexagons, tests them and their neighbors to be contained by the geofence(s),
658
- * and then any newly found hexagons are used to test again until no new
659
- * hexagons are found.
650
+ * The current implementation is very primitive and slow, but correct,
651
+ * performing a point-in-poly operation on every hexagon in a k-ring defined
652
+ * around the given geofence.
660
653
  *
661
654
  * @param geoPolygon The geofence and holes defining the relevant area
662
655
  * @param res The Hexagon resolution (0-15)
663
656
  * @param out The slab of zeroed memory to write to. Assumed to be big enough.
664
657
  */
665
658
  void H3_EXPORT(polyfill)(const GeoPolygon* geoPolygon, int res, H3Index* out) {
666
- // TODO: Eliminate this wrapper with the H3 4.0.0 release
667
- int failure = _polyfillInternal(geoPolygon, res, out);
668
- // The polyfill algorithm can theoretically fail if the allocated memory is
669
- // not large enough for the polygon, but this should be impossible given the
670
- // conservative overestimation of the number of hexagons possible.
671
- // LCOV_EXCL_START
672
- if (failure) {
673
- int numHexagons = H3_EXPORT(maxPolyfillSize)(geoPolygon, res);
674
- for (int i = 0; i < numHexagons; i++) out[i] = H3_INVALID_INDEX;
675
- }
676
- // LCOV_EXCL_STOP
677
- }
678
-
679
- /**
680
- * _getEdgeHexagons takes a given geofence ring (either the main geofence or
681
- * one of the holes) and traces it with hexagons and updates the search and
682
- * found memory blocks. This is used for determining the initial hexagon set
683
- * for the polyfill algorithm to execute on.
684
- *
685
- * @param geofence The geofence (or hole) to be traced
686
- * @param numHexagons The maximum number of hexagons possible for the geofence
687
- * (also the bounds of the search and found arrays)
688
- * @param res The hexagon resolution (0-15)
689
- * @param numSearchHexes The number of hexagons found so far to be searched
690
- * @param search The block of memory containing the hexagons to search from
691
- * @param found The block of memory containing the hexagons found from the
692
- * search
693
- *
694
- * @return An error code if the hash function cannot insert a found hexagon
695
- * into the found array.
696
- */
697
- int _getEdgeHexagons(const Geofence* geofence, int numHexagons, int res,
698
- int* numSearchHexes, H3Index* search, H3Index* found) {
699
- for (int i = 0; i < geofence->numVerts; i++) {
700
- GeoCoord origin = geofence->verts[i];
701
- GeoCoord destination = i == geofence->numVerts - 1
702
- ? geofence->verts[0]
703
- : geofence->verts[i + 1];
704
- const int numHexesEstimate =
705
- lineHexEstimate(&origin, &destination, res);
706
- for (int j = 0; j < numHexesEstimate; j++) {
707
- GeoCoord interpolate;
708
- interpolate.lat =
709
- (origin.lat * (numHexesEstimate - j) / numHexesEstimate) +
710
- (destination.lat * j / numHexesEstimate);
711
- interpolate.lon =
712
- (origin.lon * (numHexesEstimate - j) / numHexesEstimate) +
713
- (destination.lon * j / numHexesEstimate);
714
- H3Index pointHex = H3_EXPORT(geoToH3)(&interpolate, res);
715
- // A simple hash to store the hexagon, or move to another place if
716
- // needed
717
- int loc = (int)(pointHex % numHexagons);
718
- int loopCount = 0;
719
- while (found[loc] != 0) {
720
- // If this conditional is reached, the `found` memory block is
721
- // too small for the given polygon. This should not happen.
722
- if (loopCount > numHexagons) return -1; // LCOV_EXCL_LINE
723
- if (found[loc] == pointHex)
724
- break; // At least two points of the geofence index to the
725
- // same cell
726
- loc = (loc + 1) % numHexagons;
727
- loopCount++;
728
- }
729
- if (found[loc] == pointHex)
730
- continue; // Skip this hex, already exists in the found hash
731
- // Otherwise, set it in the found hash for now
732
- found[loc] = pointHex;
733
-
734
- search[*numSearchHexes] = pointHex;
735
- (*numSearchHexes)++;
736
- }
737
- }
738
- return 0;
739
- }
740
-
741
- /**
742
- * _polyfillInternal traces the provided geoPolygon data structure with hexagons
743
- * and then iteratively searches through these hexagons and their immediate
744
- * neighbors to see if they are contained within the polygon or not. Those that
745
- * are found are added to the out array as well as the found array. Once all
746
- * hexagons to search are checked, the found hexagons become the new search
747
- * array and the found array is wiped and the process repeats until no new
748
- * hexagons can be found.
749
- *
750
- * @param geoPolygon The geofence and holes defining the relevant area
751
- * @param res The Hexagon resolution (0-15)
752
- * @param out The slab of zeroed memory to write to. Assumed to be big enough.
753
- *
754
- * @return An error code if any of the hash operations fails to insert a hexagon
755
- * into an array of memory.
756
- */
757
- int _polyfillInternal(const GeoPolygon* geoPolygon, int res, H3Index* out) {
758
659
  // One of the goals of the polyfill algorithm is that two adjacent polygons
759
660
  // with zero overlap have zero overlapping hexagons. That the hexagons are
760
661
  // uniquely assigned. There are a few approaches to take here, such as
@@ -776,139 +677,36 @@ int _polyfillInternal(const GeoPolygon* geoPolygon, int res, H3Index* out) {
776
677
  BBox* bboxes = malloc((geoPolygon->numHoles + 1) * sizeof(BBox));
777
678
  assert(bboxes != NULL);
778
679
  bboxesFromGeoPolygon(geoPolygon, bboxes);
779
-
780
- // Get the estimated number of hexagons and allocate some temporary memory
781
- // for the hexagons
782
- int numHexagons = H3_EXPORT(maxPolyfillSize)(geoPolygon, res);
783
- H3Index* search = calloc(numHexagons, sizeof(H3Index));
784
- H3Index* found = calloc(numHexagons, sizeof(H3Index));
785
-
786
- // Some metadata for tracking the state of the search and found memory
787
- // blocks
788
- int numSearchHexes = 0;
789
- int numFoundHexes = 0;
790
-
791
- // 1. Trace the hexagons along the polygon defining the outer geofence and
792
- // add them to the search hash. The hexagon containing the geofence point
793
- // may or may not be contained by the geofence (as the hexagon's center
794
- // point may be outside of the boundary.)
795
- const Geofence geofence = geoPolygon->geofence;
796
- int failure = _getEdgeHexagons(&geofence, numHexagons, res, &numSearchHexes,
797
- search, found);
798
- // If this branch is reached, we have exceeded the maximum number of
799
- // hexagons possible and need to clean up the allocated memory.
800
- // LCOV_EXCL_START
801
- if (failure) {
802
- free(search);
803
- free(found);
804
- free(bboxes);
805
- return failure;
806
- }
807
- // LCOV_EXCL_STOP
808
-
809
- // 2. Iterate over all holes, trace the polygons defining the holes with
810
- // hexagons and add to only the search hash. We're going to temporarily use
811
- // the `found` hash to use for dedupe purposes and then re-zero it once
812
- // we're done here, otherwise we'd have to scan the whole set on each insert
813
- // to make sure there's no duplicates, which is very inefficient.
814
- for (int i = 0; i < geoPolygon->numHoles; i++) {
815
- Geofence* hole = &(geoPolygon->holes[i]);
816
- failure = _getEdgeHexagons(hole, numHexagons, res, &numSearchHexes,
817
- search, found);
818
- // If this branch is reached, we have exceeded the maximum number of
819
- // hexagons possible and need to clean up the allocated memory.
820
- // LCOV_EXCL_START
821
- if (failure) {
822
- free(search);
823
- free(found);
824
- free(bboxes);
825
- return failure;
680
+ int minK = bboxHexRadius(&bboxes[0], res);
681
+ int numHexagons = H3_EXPORT(maxKringSize)(minK);
682
+
683
+ // Get the center hex
684
+ GeoCoord center;
685
+ bboxCenter(&bboxes[0], &center);
686
+ H3Index centerH3 = H3_EXPORT(geoToH3)(&center, res);
687
+
688
+ // From here on it works differently, first we get all potential
689
+ // hexagons inserted into the available memory
690
+ H3_EXPORT(kRing)(centerH3, minK, out);
691
+
692
+ // Next we iterate through each hexagon, and test its center point to see if
693
+ // it's contained in the GeoJSON-like struct
694
+ for (int i = 0; i < numHexagons; i++) {
695
+ // Skip records that are already zeroed
696
+ if (out[i] == 0) {
697
+ continue;
826
698
  }
827
- // LCOV_EXCL_STOP
828
- }
829
-
830
- // 3. Re-zero the found hash so it can be used in the main loop below
831
- for (int i = 0; i < numHexagons; i++) found[i] = 0;
832
-
833
- // 4. Begin main loop. While the search hash is not empty do the following
834
- while (numSearchHexes > 0) {
835
- // Iterate through all hexagons in the current search hash, then loop
836
- // through all neighbors and test Point-in-Poly, if point-in-poly
837
- // succeeds, add to out and found hashes if not already there.
838
- int currentSearchNum = 0;
839
- int i = 0;
840
- while (currentSearchNum < numSearchHexes) {
841
- H3Index ring[MAX_ONE_RING_SIZE] = {0};
842
- H3Index searchHex = search[i];
843
- H3_EXPORT(kRing)(searchHex, 1, ring);
844
- for (int j = 0; j < MAX_ONE_RING_SIZE; j++) {
845
- if (ring[j] == H3_INVALID_INDEX) {
846
- continue; // Skip if this was a pentagon and only had 5
847
- // neighbors
848
- }
849
-
850
- H3Index hex = ring[j];
851
-
852
- // A simple hash to store the hexagon, or move to another place
853
- // if needed. This MUST be done before the point-in-poly check
854
- // since that's far more expensive
855
- int loc = (int)(hex % numHexagons);
856
- int loopCount = 0;
857
- while (out[loc] != 0) {
858
- // If this branch is reached, we have exceeded the maximum
859
- // number of hexagons possible and need to clean up the
860
- // allocated memory.
861
- // LCOV_EXCL_START
862
- if (loopCount > numHexagons) {
863
- free(search);
864
- free(found);
865
- free(bboxes);
866
- return -1;
867
- }
868
- // LCOV_EXCL_STOP
869
- if (out[loc] == hex) break; // Skip duplicates found
870
- loc = (loc + 1) % numHexagons;
871
- loopCount++;
872
- }
873
- if (out[loc] == hex) {
874
- continue; // Skip this hex, already exists in the out hash
875
- }
876
-
877
- // Check if the hexagon is in the polygon or not
878
- GeoCoord hexCenter;
879
- H3_EXPORT(h3ToGeo)(hex, &hexCenter);
880
-
881
- // If not, skip
882
- if (!pointInsidePolygon(geoPolygon, bboxes, &hexCenter)) {
883
- continue;
884
- }
885
-
886
- // Otherwise set it in the output array
887
- out[loc] = hex;
888
-
889
- // Set the hexagon in the found hash
890
- found[numFoundHexes] = hex;
891
- numFoundHexes++;
892
- }
893
- currentSearchNum++;
894
- i++;
699
+ // Check if hexagon is inside of polygon
700
+ GeoCoord hexCenter;
701
+ H3_EXPORT(h3ToGeo)(out[i], &hexCenter);
702
+ hexCenter.lat = constrainLat(hexCenter.lat);
703
+ hexCenter.lon = constrainLng(hexCenter.lon);
704
+ // And remove from list if not
705
+ if (!pointInsidePolygon(geoPolygon, bboxes, &hexCenter)) {
706
+ out[i] = H3_INVALID_INDEX;
895
707
  }
896
-
897
- // Swap the search and found pointers, copy the found hex count to the
898
- // search hex count, and zero everything related to the found memory.
899
- H3Index* temp = search;
900
- search = found;
901
- found = temp;
902
- for (int j = 0; j < numSearchHexes; j++) found[j] = 0;
903
- numSearchHexes = numFoundHexes;
904
- numFoundHexes = 0;
905
- // Repeat until no new hexagons are found
906
708
  }
907
- // The out memory structure should be complete, end it here
908
709
  free(bboxes);
909
- free(search);
910
- free(found);
911
- return 0;
912
710
  }
913
711
 
914
712
  /**
@@ -88,59 +88,38 @@ double _hexRadiusKm(H3Index h3Index) {
88
88
  }
89
89
 
90
90
  /**
91
- * bboxHexEstimate returns an estimated number of hexagons that fit
92
- * within the cartesian-projected bounding box
93
- *
94
- * @param bbox the bounding box to estimate the hexagon fill level
95
- * @param res the resolution of the H3 hexagons to fill the bounding box
96
- * @return the estimated number of hexagons to fill the bounding box
91
+ * Get the radius of the bbox in hexagons - i.e. the radius of a k-ring centered
92
+ * on the bbox center and covering the entire bbox.
93
+ * @param bbox Bounding box to measure
94
+ * @param res Resolution of hexagons to use in measurement
95
+ * @return Radius in hexagons
97
96
  */
98
- int bboxHexEstimate(const BBox* bbox, int res) {
99
- // Get the area of the pentagon as the maximally-distorted area possible
100
- H3Index pentagons[12] = {0};
101
- H3_EXPORT(getPentagonIndexes)(res, pentagons);
102
- double pentagonRadiusKm = _hexRadiusKm(pentagons[0]);
103
- // Area of a regular hexagon is 3/2*sqrt(3) * r * r
104
- // The pentagon has the most distortion (smallest edges) and shares its
105
- // edges with hexagons, so the most-distorted hexagons have this area
106
- double pentagonAreaKm2 =
107
- 2.59807621135 * pentagonRadiusKm * pentagonRadiusKm;
97
+ int bboxHexRadius(const BBox* bbox, int res) {
98
+ // Determine the center of the bounding box
99
+ GeoCoord center;
100
+ bboxCenter(bbox, &center);
108
101
 
109
- // Then get the area of the bounding box of the geofence in question
110
- GeoCoord p1, p2;
111
- p1.lat = bbox->north;
112
- p1.lon = bbox->east;
113
- p2.lat = bbox->south;
114
- p2.lon = bbox->east;
115
- double h = _geoDistKm(&p1, &p2);
116
- p2.lat = bbox->north;
117
- p2.lon = bbox->west;
118
- double w = _geoDistKm(&p1, &p2);
102
+ // Use a vertex on the side closest to the equator, to ensure the longest
103
+ // radius in cases with significant distortion. East/west is arbitrary.
104
+ double lat =
105
+ fabs(bbox->north) > fabs(bbox->south) ? bbox->south : bbox->north;
106
+ GeoCoord vertex = {lat, bbox->east};
119
107
 
120
- // Divide the two to get an estimate of the number of hexagons needed
121
- int estimate = (int)ceil(w * h / pentagonAreaKm2);
122
- if (estimate == 0) estimate = 1;
123
- return estimate;
124
- }
108
+ // Determine the length of the bounding box "radius" to then use
109
+ // as a circle on the earth that the k-rings must be greater than
110
+ double bboxRadiusKm = _geoDistKm(&center, &vertex);
125
111
 
126
- /**
127
- * lineHexEstimate returns an estimated number of hexagons that trace
128
- * the cartesian-projected line
129
- *
130
- * @param origin the origin coordinates
131
- * @param destination the destination coordinates
132
- * @param res the resolution of the H3 hexagons to trace the line
133
- * @return the estimated number of hexagons required to trace the line
134
- */
135
- int lineHexEstimate(const GeoCoord* origin, const GeoCoord* destination,
136
- int res) {
137
- // Get the area of the pentagon as the maximally-distorted area possible
138
- H3Index pentagons[12] = {0};
139
- H3_EXPORT(getPentagonIndexes)(res, pentagons);
140
- double pentagonRadiusKm = _hexRadiusKm(pentagons[0]);
112
+ // Determine the radius of the center hexagon
113
+ double centerHexRadiusKm = _hexRadiusKm(H3_EXPORT(geoToH3)(&center, res));
141
114
 
142
- double dist = _geoDistKm(origin, destination);
143
- int estimate = (int)ceil(dist / (2 * pentagonRadiusKm));
144
- if (estimate == 0) estimate = 1;
145
- return estimate;
115
+ // We use centerHexRadiusKm un-scaled and rounded *up* to guarantee
116
+ // containment ot the bbox. Ideal, undistorted hexagons could scale
117
+ // centerHexRadiusKm by a factor of up to 1.5, reducing bboxHexRadius.
118
+ // This is because the closest point along an undistorted hexagon drawn
119
+ // through the center points of a k-ring aggregation is exactly 1.5 radii
120
+ // of the hexagon. But there is distortion near pentagons, and for those
121
+ // cases, the scaling needs to be less than 1.5. Using the un-scaled value
122
+ // conservatively guarantees containment for all cases, at the expense of a
123
+ // larger bboxHexRadius.
124
+ return (int)ceil(bboxRadiusKm / centerHexRadiusKm);
146
125
  }
@@ -12,11 +12,21 @@ module H3
12
12
  base.include Types
13
13
  base.ffi_lib ["#{lib_path}/libh3.dylib", "#{lib_path}/libh3.so"]
14
14
  base.typedef :ulong_long, :h3_index
15
- base.typedef :int, :size
16
15
  base.typedef :int, :k_distance
17
- base.typedef :pointer, :h3_set
18
- base.typedef :pointer, :output_buffer
19
- base.const_set("H3_INDEX", :ulong_long)
16
+ end
17
+
18
+ def attach_predicate_function(name, *args)
19
+ stripped_name = name.to_s.gsub("?", "")
20
+ attach_function(stripped_name, *args).tap do
21
+ rename_function stripped_name, name
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def rename_function(from, to)
28
+ alias_method to, from
29
+ undef_method from
20
30
  end
21
31
  end
22
32
  end
@@ -7,11 +7,11 @@ module H3
7
7
  module Private
8
8
  extend H3::Bindings::Base
9
9
 
10
- attach_function :compact, [H3IndexesIn, H3IndexesOut, :size], :bool
10
+ attach_function :compact, [H3IndexesIn, H3IndexesOut, :size_t], :bool
11
11
  attach_function :destroy_linked_polygon, :destroyLinkedPolygon, [LinkedGeoPolygon], :void
12
12
  attach_function :geo_to_h3, :geoToH3, [GeoCoord, Resolution], :h3_index
13
13
  attach_function :get_pentagon_indexes, :getPentagonIndexes, [:int, H3IndexesOut], :void
14
- attach_function :h3_faces, :h3GetFaces, %i[h3_index output_buffer], :void
14
+ attach_function :h3_faces, :h3GetFaces, %i[h3_index buffer_out], :void
15
15
  attach_function :h3_indexes_from_unidirectional_edge,
16
16
  :getH3IndexesFromUnidirectionalEdge,
17
17
  [:h3_index, H3IndexesOut], :void
@@ -21,11 +21,11 @@ module H3
21
21
  [:h3_index, H3IndexesOut], :void
22
22
  attach_function :h3_set_to_linked_geo,
23
23
  :h3SetToLinkedGeo,
24
- [H3IndexesIn, :size, LinkedGeoPolygon],
24
+ [H3IndexesIn, :size_t, LinkedGeoPolygon],
25
25
  :void
26
26
  attach_function :h3_to_children, :h3ToChildren, [:h3_index, Resolution, H3IndexesOut], :void
27
27
  attach_function :h3_to_geo, :h3ToGeo, [:h3_index, GeoCoord], :void
28
- attach_function :h3_to_string, :h3ToString, %i[h3_index output_buffer size], :void
28
+ attach_function :h3_to_string, :h3ToString, %i[h3_index buffer_out size_t], :void
29
29
  attach_function :h3_to_geo_boundary,
30
30
  :h3ToGeoBoundary,
31
31
  [:h3_index, GeoBoundary],
@@ -36,25 +36,25 @@ module H3
36
36
  attach_function :hex_range, :hexRange, [:h3_index, :k_distance, H3IndexesOut], :bool
37
37
  attach_function :hex_range_distances,
38
38
  :hexRangeDistances,
39
- [:h3_index, :k_distance, H3IndexesOut, :output_buffer], :bool
39
+ [:h3_index, :k_distance, H3IndexesOut, :buffer_out], :bool
40
40
  attach_function :hex_ranges,
41
41
  :hexRanges,
42
- [H3IndexesIn, :size, :k_distance, H3IndexesOut],
42
+ [H3IndexesIn, :size_t, :k_distance, H3IndexesOut],
43
43
  :bool
44
44
  attach_function :hex_ring, :hexRing, [:h3_index, :k_distance, H3IndexesOut], :bool
45
45
  attach_function :k_ring, :kRing, [:h3_index, :k_distance, H3IndexesOut], :void
46
46
  attach_function :k_ring_distances,
47
47
  :kRingDistances,
48
- [:h3_index, :k_distance, H3IndexesOut, :output_buffer],
48
+ [:h3_index, :k_distance, H3IndexesOut, :buffer_out],
49
49
  :bool
50
50
  attach_function :max_polyfill_size,
51
51
  :maxPolyfillSize,
52
52
  [GeoPolygon, Resolution],
53
53
  :int
54
- attach_function :max_uncompact_size, :maxUncompactSize, [H3IndexesIn, :size, Resolution], :int
54
+ attach_function :max_uncompact_size, :maxUncompactSize, [H3IndexesIn, :size_t, Resolution], :int
55
55
  attach_function :polyfill, [GeoPolygon, Resolution, H3IndexesOut], :void
56
56
  attach_function :res_0_indexes, :getRes0Indexes, [H3IndexesOut], :void
57
- attach_function :uncompact, [H3IndexesIn, :size, H3IndexesOut, :size, Resolution], :bool
57
+ attach_function :uncompact, [H3IndexesIn, :size_t, H3IndexesOut, :size_t, Resolution], :bool
58
58
  end
59
59
  end
60
60
  end
@@ -19,12 +19,6 @@ module H3
19
19
  # @return [Integer] H3 index of parent hexagon.
20
20
  attach_function :parent, :h3ToParent, [:h3_index, Resolution], :h3_index
21
21
 
22
- # @deprecated Please use {#parent} instead.
23
- def h3_to_parent(h3_index, resolution)
24
- parent(h3_index, resolution)
25
- end
26
- deprecate :h3_to_parent, :parent, 2020, 1
27
-
28
22
  # @!method max_children(h3_index, child_resolution)
29
23
  #
30
24
  # Derive maximum number of child hexagons possible at given resolution.
@@ -54,12 +48,6 @@ module H3
54
48
  # @return [Integer] H3 index of center child hexagon.
55
49
  attach_function :center_child, :h3ToCenterChild, [:h3_index, Resolution], :h3_index
56
50
 
57
- # @deprecated Please use {#max_children} instead.
58
- def max_h3_to_children_size(h3_index, resolution)
59
- max_children(h3_index, resolution)
60
- end
61
- deprecate :max_h3_to_children_size, :max_children, 2020, 1
62
-
63
51
  # Derive child hexagons contained within the hexagon at the given H3 index.
64
52
  #
65
53
  # @param [Integer] h3_index A valid H3 index.
@@ -80,12 +68,6 @@ module H3
80
68
  out.read
81
69
  end
82
70
 
83
- # @deprecated Please use {#children} instead.
84
- def h3_to_children(h3_index, resolution)
85
- children(h3_index, resolution)
86
- end
87
- deprecate :h3_to_children, :children, 2020, 1
88
-
89
71
  # Find the maximum uncompacted size of the given set of H3 indexes.
90
72
  #
91
73
  # @param [Array<Integer>] compacted_set An array of valid H3 indexes.
@@ -35,12 +35,6 @@ module H3
35
35
  Bindings::Private.geo_to_h3(coords, resolution)
36
36
  end
37
37
 
38
- # @deprecated Please use {#from_geo_coordinates} instead.
39
- def geo_to_h3(coords, resolution)
40
- from_geo_coordinates(coords, resolution)
41
- end
42
- deprecate :geo_to_h3, :from_geo_coordinates, 2020, 1
43
-
44
38
  # Derive coordinates for a given H3 index.
45
39
  #
46
40
  # The coordinates map to the centre of the hexagon at the given index.
@@ -58,12 +52,6 @@ module H3
58
52
  [rads_to_degs(coords[:lat]), rads_to_degs(coords[:lon])]
59
53
  end
60
54
 
61
- # @deprecated Please use {#to_geo_coordinates} instead.
62
- def h3_to_geo(h3_index)
63
- to_geo_coordinates(h3_index)
64
- end
65
- deprecate :h3_to_geo, :to_geo_coordinates, 2020, 1
66
-
67
55
  # Derive the geographical boundary as coordinates for a given H3 index.
68
56
  #
69
57
  # This will be a set of 6 coordinate pairs matching the vertexes of the
@@ -89,11 +77,5 @@ module H3
89
77
  [rads_to_degs(d[:lat]), rads_to_degs(d[:lon])]
90
78
  end
91
79
  end
92
-
93
- # @deprecated Please use {#to_boundary} instead.
94
- def h3_to_geo_boundary(h3_index)
95
- to_boundary(h3_index)
96
- end
97
- deprecate :h3_to_geo_boundary, :to_boundary, 2020, 1
98
80
  end
99
81
  end
@@ -21,12 +21,6 @@ module H3
21
21
  # @return [Integer] Resolution of H3 index
22
22
  attach_function :resolution, :h3GetResolution, %i[h3_index], Resolution
23
23
 
24
- # @deprecated Please use {#resolution} instead.
25
- def h3_resolution(h3_index)
26
- resolution(h3_index)
27
- end
28
- deprecate :h3_resolution, :resolution, 2020, 1
29
-
30
24
  # @!method base_cell(h3_index)
31
25
  #
32
26
  # Derives the base cell number of the given H3 index
@@ -40,12 +34,6 @@ module H3
40
34
  # @return [Integer] Base cell number
41
35
  attach_function :base_cell, :h3GetBaseCell, %i[h3_index], :int
42
36
 
43
- # @deprecated Please use {#base_cell} instead.
44
- def h3_base_cell(h3_index)
45
- base_cell(h3_index)
46
- end
47
- deprecate :h3_base_cell, :base_cell, 2020, 1
48
-
49
37
  # @!method from_string(h3_string)
50
38
  #
51
39
  # Derives the H3 index for a given hexadecimal string representation.
@@ -59,12 +47,6 @@ module H3
59
47
  # @return [Integer] H3 index
60
48
  attach_function :from_string, :stringToH3, %i[string], :h3_index
61
49
 
62
- # @deprecated Please use {#from_string} instead.
63
- def string_to_h3(string)
64
- from_string(string)
65
- end
66
- deprecate :string_to_h3, :from_string, 2020, 1
67
-
68
50
  # @!method pentagon?(h3_index)
69
51
  #
70
52
  # Determine whether the given H3 index is a pentagon.
@@ -76,15 +58,7 @@ module H3
76
58
  # true
77
59
  #
78
60
  # @return [Boolean] True if the H3 index is a pentagon.
79
- attach_function :pentagon, :h3IsPentagon, %i[h3_index], :bool
80
- alias_method :pentagon?, :pentagon
81
- undef_method :pentagon
82
-
83
- # @deprecated Please use {#pentagon?} instead.
84
- def h3_pentagon?(h3_index)
85
- pentagon?(h3_index)
86
- end
87
- deprecate :h3_pentagon?, :pentagon?, 2020, 1
61
+ attach_predicate_function :pentagon?, :h3IsPentagon, %i[h3_index], :bool
88
62
 
89
63
  # @!method class_3_resolution?(h3_index)
90
64
  #
@@ -98,15 +72,7 @@ module H3
98
72
  # true
99
73
  #
100
74
  # @return [Boolean] True if the H3 index has a class III resolution.
101
- attach_function :class_3_resolution, :h3IsResClassIII, %i[h3_index], :bool
102
- alias_method :class_3_resolution?, :class_3_resolution
103
- undef_method :class_3_resolution
104
-
105
- # @deprecated Please use {#class_3_resolution?} instead.
106
- def h3_res_class_3?(h3_index)
107
- class_3_resolution?(h3_index)
108
- end
109
- deprecate :h3_res_class_3?, :class_3_resolution?, 2020, 1
75
+ attach_predicate_function :class_3_resolution?, :h3IsResClassIII, %i[h3_index], :bool
110
76
 
111
77
  # @!method valid?(h3_index)
112
78
  #
@@ -119,15 +85,7 @@ module H3
119
85
  # true
120
86
  #
121
87
  # @return [Boolean] True if the H3 index is valid.
122
- attach_function :valid, :h3IsValid, %i[h3_index], :bool
123
- alias_method :valid?, :valid
124
- undef_method :valid
125
-
126
- # @deprecated Please use {#valid?} instead.
127
- def h3_valid?(h3_index)
128
- valid?(h3_index)
129
- end
130
- deprecate :h3_valid?, :valid?, 2020, 1
88
+ attach_predicate_function :valid?, :h3IsValid, %i[h3_index], :bool
131
89
 
132
90
  # Derives the hexadecimal string representation for a given H3 index.
133
91
  #
@@ -144,12 +102,6 @@ module H3
144
102
  h3_str.read_string
145
103
  end
146
104
 
147
- # @deprecated Please use {#to_string} instead.
148
- def h3_to_string(h3_index)
149
- to_string(h3_index)
150
- end
151
- deprecate :h3_to_string, :to_strings, 2020, 1
152
-
153
105
  # @!method max_face_count(h3_index)
154
106
  #
155
107
  # Returns the maximum number of icosahedron faces the given H3 index may intersect.
@@ -163,8 +115,6 @@ module H3
163
115
  # @return [Integer] Maximum possible number of faces
164
116
  attach_function :max_face_count, :maxFaceCount, %i[h3_index], :int
165
117
 
166
- # @!method faces(h3_index)
167
- #
168
118
  # Find all icosahedron faces intersected by a given H3 index.
169
119
  #
170
120
  # @param [Integer] h3_index A H3 index.
@@ -181,11 +131,5 @@ module H3
181
131
  # The C function returns a sparse array whose holes are represented by -1.
182
132
  out.read_array_of_int(max_faces).reject(&:negative?).sort
183
133
  end
184
-
185
- # @deprecated Please use {#faces} instead.
186
- def h3_faces(h3_index)
187
- faces(h3_index)
188
- end
189
- deprecate :h3_faces, :faces, 2020, 1
190
134
  end
191
135
  end
@@ -83,12 +83,6 @@ module H3
83
83
  # @return [Integer] Number of unique hexagons
84
84
  attach_function :hexagon_count, :numHexagons, [Resolution], :ulong_long
85
85
 
86
- # @deprecated Please use {#hexagon_count} instead.
87
- def num_hexagons(resolution)
88
- hexagon_count(resolution)
89
- end
90
- deprecate :num_hexagons, :hexagon_count, 2020, 1
91
-
92
86
  # @!method rads_to_degs(rads)
93
87
  #
94
88
  # Convert a number expressed in radians to its equivalent in degrees.
@@ -125,12 +119,6 @@ module H3
125
119
  # @return [Integer] The number of pentagons per resolution.
126
120
  attach_function :pentagon_count, :pentagonIndexCount, [], :int
127
121
 
128
- # @deprecated Please use {#base_cell_count} instead.
129
- def res_0_index_count
130
- base_cell_count
131
- end
132
- deprecate :res_0_index_count, :base_cell_count, 2020, 1
133
-
134
122
  # Returns all resolution 0 hexagons (base cells).
135
123
  #
136
124
  # @example Return all base cells.
@@ -156,11 +144,5 @@ module H3
156
144
  Bindings::Private.get_pentagon_indexes(resolution, out)
157
145
  out.read
158
146
  end
159
-
160
- # @deprecated Please use {#base_cells} instead.
161
- def res_0_indexes
162
- base_cells
163
- end
164
- deprecate :res_0_indexes, :base_cells, 2020, 1
165
147
  end
166
148
  end
@@ -141,6 +141,7 @@ module H3
141
141
  linked_geo_polygon = LinkedGeoPolygon.new
142
142
  Bindings::Private.h3_set_to_linked_geo(h3_set, h3_indexes.size, linked_geo_polygon)
143
143
 
144
+ # The algorithm in h3 currently only handles 1 polygon
144
145
  extract_linked_geo_polygon(linked_geo_polygon).first
145
146
  ensure
146
147
  Bindings::Private.destroy_linked_polygon(linked_geo_polygon)
@@ -154,6 +155,8 @@ module H3
154
155
  geo_polygons = [linked_geo_polygon]
155
156
 
156
157
  until linked_geo_polygon[:next].null?
158
+ # Until the h3 algorithm is updated to handle multiple polygons,
159
+ # this block will never run.
157
160
  geo_polygons << linked_geo_polygon[:next]
158
161
  linked_geo_polygon = linked_geo_polygon[:next]
159
162
  end
@@ -32,12 +32,6 @@ module H3
32
32
  # @return [Integer] Distance between indexes.
33
33
  attach_function :distance, :h3Distance, %i[h3_index h3_index], :k_distance
34
34
 
35
- # @deprecated Please use {#distance} instead.
36
- def h3_distance(origin, destination)
37
- distance(origin, destination)
38
- end
39
- deprecate :h3_distance, :distance, 2020, 1
40
-
41
35
  # @!method line_size(origin, destination)
42
36
  #
43
37
  # Derive the number of hexagons present in a line between two H3 indexes.
@@ -57,12 +51,6 @@ module H3
57
51
  # @return [Integer] Number of hexagons found between indexes.
58
52
  attach_function :line_size, :h3LineSize, %i[h3_index h3_index], :int
59
53
 
60
- # @deprecated Please use {#line_size} instead.
61
- def h3_line_size(origin, destination)
62
- line_size(origin, destination)
63
- end
64
- deprecate :h3_line_size, :line_size, 2020, 1
65
-
66
54
  # Derives H3 indexes within k distance of the origin H3 index.
67
55
  #
68
56
  # Similar to {k_ring}, except that an error is raised when one of the indexes
@@ -317,12 +305,6 @@ module H3
317
305
  hexagons.read
318
306
  end
319
307
 
320
- # @deprecated Please use {#line} instead.
321
- def h3_line(origin, destination)
322
- line(origin, destination)
323
- end
324
- deprecate :h3_line, :line, 2020, 1
325
-
326
308
  private
327
309
 
328
310
  def k_rings_for_hex_range(indexes, k)
@@ -17,16 +17,7 @@ module H3
17
17
  # true
18
18
  #
19
19
  # @return [Boolean] True if indexes are neighbors
20
- attach_function :neighbors, :h3IndexesAreNeighbors, %i[h3_index h3_index], :bool
21
- alias_method :neighbors?, :neighbors
22
- undef_method :neighbors
23
-
24
- # @deprecated Please use {#neighbors?} instead.
25
- def h3_indexes_neighbors?(origin, destination)
26
- neighbors?(origin, destination)
27
- end
28
-
29
- deprecate :h3_indexes_neighbors?, :neighbors?, 2020, 1
20
+ attach_predicate_function :neighbors?, :h3IndexesAreNeighbors, %i[h3_index h3_index], :bool
30
21
 
31
22
  # @!method unidirectional_edge_valid?(h3_index)
32
23
  #
@@ -39,19 +30,10 @@ module H3
39
30
  # true
40
31
  #
41
32
  # @return [Boolean] True if H3 index is a valid unidirectional edge
42
- attach_function :unidirectional_edge_valid,
43
- :h3UnidirectionalEdgeIsValid,
44
- %i[h3_index],
45
- :bool
46
- alias_method :unidirectional_edge_valid?, :unidirectional_edge_valid
47
- undef_method :unidirectional_edge_valid
48
-
49
- # @deprecated Please use {#unidirectional_edge_valid?} instead.
50
- def h3_unidirectional_edge_valid?(h3_index)
51
- unidirectional_edge_valid?(h3_index)
52
- end
53
-
54
- deprecate :h3_unidirectional_edge_valid?, :unidirectional_edge_valid?, 2020, 1
33
+ attach_predicate_function :unidirectional_edge_valid?,
34
+ :h3UnidirectionalEdgeIsValid,
35
+ %i[h3_index],
36
+ :bool
55
37
 
56
38
  # @!method unidirectional_edge(origin, destination)
57
39
  #
@@ -70,13 +52,6 @@ module H3
70
52
  %i[h3_index h3_index],
71
53
  :h3_index
72
54
 
73
- # @deprecated Please use {#unidirectional_edge} instead.
74
- def h3_unidirectional_edge(origin, destination)
75
- unidirectional_edge(origin, destination)
76
- end
77
-
78
- deprecate :h3_unidirectional_edge, :unidirectional_edge, 2020, 1
79
-
80
55
  # @!method destination_from_unidirectional_edge(edge)
81
56
  #
82
57
  # Derive destination H3 index from edge.
@@ -129,16 +104,6 @@ module H3
129
104
  out.read
130
105
  end
131
106
 
132
- # @deprecated Please use {#origin_and_destination_from_unidirectional_edge} instead.
133
- def h3_indexes_from_unidirectional_edge(edge)
134
- origin_and_destination_from_unidirectional_edge(edge)
135
- end
136
-
137
- deprecate :h3_indexes_from_unidirectional_edge,
138
- :origin_and_destination_from_unidirectional_edge,
139
- 2020,
140
- 1
141
-
142
107
  # Derive unidirectional edges for a H3 index.
143
108
  #
144
109
  # @param [Integer] origin H3 index
@@ -158,16 +123,6 @@ module H3
158
123
  out.read
159
124
  end
160
125
 
161
- # @deprecated Please use {#unidirectional_edges_from_hexagon} instead.
162
- def h3_unidirectional_edges_from_hexagon(origin)
163
- unidirectional_edges_from_hexagon(origin)
164
- end
165
-
166
- deprecate :h3_unidirectional_edges_from_hexagon,
167
- :unidirectional_edges_from_hexagon,
168
- 2020,
169
- 1
170
-
171
126
  # Derive coordinates for edge boundary.
172
127
  #
173
128
  # @param [Integer] edge H3 edge index
@@ -188,15 +143,5 @@ module H3
188
143
  [rads_to_degs(d[:lat]), rads_to_degs(d[:lon])]
189
144
  end
190
145
  end
191
-
192
- # @deprecated Please use {#unidirectional_edge_boundary} instead.
193
- def h3_unidirectional_edge_boundary(edge)
194
- unidirectional_edge_boundary(edge)
195
- end
196
-
197
- deprecate :h3_unidirectional_edge_boundary,
198
- :unidirectional_edge_boundary,
199
- 2020,
200
- 1
201
146
  end
202
147
  end
@@ -1,3 +1,3 @@
1
1
  module H3
2
- VERSION = "3.6.1".freeze
2
+ VERSION = "3.6.2".freeze
3
3
  end
@@ -60,6 +60,14 @@ RSpec.describe H3 do
60
60
  expect { geo_json_to_coordinates }.to raise_error(ArgumentError)
61
61
  end
62
62
  end
63
+
64
+ context "when given JSON with the wrong structure" do
65
+ let(:input) { { blah: "blah" }.to_json }
66
+
67
+ it "raises an error" do
68
+ expect { geo_json_to_coordinates }.to raise_error(ArgumentError)
69
+ end
70
+ end
63
71
  end
64
72
 
65
73
  describe ".coordinates_to_geo_json" do
@@ -42,7 +42,7 @@ RSpec.describe H3 do
42
42
  File.read(File.join(File.dirname(__FILE__), "support/fixtures/banbury.json"))
43
43
  end
44
44
  let(:resolution) { 9 }
45
- let(:expected_count) { 36_193 }
45
+ let(:expected_count) { 75_367 }
46
46
 
47
47
  subject(:max_polyfill_size) { H3.max_polyfill_size(geojson, resolution) }
48
48
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: h3
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.1
4
+ version: 3.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lachlan Laycock
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-11-23 00:00:00.000000000 Z
12
+ date: 2020-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -412,7 +412,7 @@ files:
412
412
  - spec/indexing_spec.rb
413
413
  - spec/inspection_spec.rb
414
414
  - spec/miscellaneous_spec.rb
415
- - spec/region_spec.rb
415
+ - spec/regions_spec.rb
416
416
  - spec/spec_helper.rb
417
417
  - spec/support/fixtures/australia.json
418
418
  - spec/support/fixtures/banbury.json