h3 3.6.1 → 3.6.2

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.
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