Skip to content

Commit 2201262

Browse files
authored
Update H3 to 3.7.1 & add new functions (#70)
1 parent b808586 commit 2201262

File tree

7 files changed

+267
-5
lines changed

7 files changed

+267
-5
lines changed

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66

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

9+
## [3.7.1] - 2020-10-7
10+
### Added
11+
- Area and haversine distance functions:
12+
- `cellAreaRads2`
13+
- `cellAreaKm2`
14+
- `cellAreaM2`
15+
- `pointDistRads`
16+
- `pointDistKm`
17+
- `pointDistM`
18+
- `exactEdgeLengthRads`
19+
- `exactEdgeLengthKm`
20+
- `exactEdgeLengthM`
21+
22+
### Changed
23+
- Speeds up `getH3UnidirectionalEdgeBoundary` by about 3x.
24+
25+
### Fixed
26+
- Finding invalid edge boundaries should not crash.
27+
928
## [3.6.4] - 2020-7-2
1029
### Changed
1130
- Reinstate new `polyfill` algorithm for up to 3x perf boost.

Gemfile.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
h3 (3.6.4)
4+
h3 (3.7.1)
55
ffi (~> 1.9)
66
rgeo-geojson (~> 2.1)
77
zeitwerk (~> 2.1)
@@ -46,7 +46,7 @@ GEM
4646
thor (0.19.4)
4747
tins (1.20.2)
4848
yard (0.9.20)
49-
zeitwerk (2.3.1)
49+
zeitwerk (2.4.0)
5050

5151
PLATFORMS
5252
ruby
@@ -59,4 +59,4 @@ DEPENDENCIES
5959
yard (~> 0.9)
6060

6161
BUNDLED WITH
62-
1.17.3
62+
2.1.4

ext/h3/src

Submodule src updated 57 files

lib/h3/bindings/private.rb

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ module Private
5252
[GeoPolygon, Resolution],
5353
:int
5454
attach_function :max_uncompact_size, :maxUncompactSize, [H3IndexesIn, :size_t, Resolution], :int
55+
attach_function :point_distance_rads, :pointDistRads, [GeoCoord, GeoCoord], :double
56+
attach_function :point_distance_km, :pointDistKm, [GeoCoord, GeoCoord], :double
57+
attach_function :point_distance_m, :pointDistM, [GeoCoord, GeoCoord], :double
5558
attach_function :polyfill, [GeoPolygon, Resolution, H3IndexesOut], :void
5659
attach_function :res_0_indexes, :getRes0Indexes, [H3IndexesOut], :void
5760
attach_function :uncompact, [H3IndexesIn, :size_t, H3IndexesOut, :size_t, Resolution], :bool

lib/h3/miscellaneous.rb

+123
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,105 @@ module Miscellaneous
119119
# @return [Integer] The number of pentagons per resolution.
120120
attach_function :pentagon_count, :pentagonIndexCount, [], :int
121121

122+
# @!method cell_area_rads2
123+
#
124+
# Area of a given cell expressed in radians squared
125+
#
126+
# @example Return the area of the cell
127+
# H3.cell_area_rads2(617700169958293503)
128+
# 2.6952182709835757e-09
129+
#
130+
# @return [Double] Area of cell in rads2
131+
attach_function :cell_area_rads2, :cellAreaRads2, %i[h3_index], :double
132+
133+
# @!method cell_area_km2
134+
#
135+
# Area of a given cell expressed in km squared
136+
#
137+
# @example Return the area of the cell
138+
# H3.cell_area_km2(617700169958293503)
139+
# 0.10939818864648902
140+
#
141+
# @return [Double] Area of cell in km2
142+
attach_function :cell_area_km2, :cellAreaKm2, %i[h3_index], :double
143+
144+
# @!method cell_area_m2
145+
#
146+
# Area of a given cell expressed in metres squared
147+
#
148+
# @example Return the area of the cell
149+
# H3.cell_area_m2(617700169958293503)
150+
# 109398.18864648901
151+
#
152+
# @return [Double] Area of cell in metres squared
153+
attach_function :cell_area_m2, :cellAreaM2, %i[h3_index], :double
154+
155+
# @!method exact_edge_length_rads
156+
#
157+
# Exact length of edge in rads
158+
#
159+
# @example Return the edge length
160+
# H3.exact_edge_length_rads(1266218516299644927)
161+
# 3.287684056071637e-05
162+
#
163+
# @return [Double] Edge length in rads
164+
attach_function :exact_edge_length_rads, :exactEdgeLengthRads, %i[h3_index], :double
165+
166+
# @!method exact_edge_length_km
167+
#
168+
# Exact length of edge in kilometres
169+
#
170+
# @example Return the edge length
171+
# H3.exact_edge_length_km(1266218516299644927)
172+
# 3.287684056071637e-05
173+
#
174+
# @return [Double] Edge length in kilometres
175+
attach_function :exact_edge_length_km, :exactEdgeLengthKm, %i[h3_index], :double
176+
177+
# @!method exact_edge_length_m
178+
#
179+
# Exact length of edge in metres
180+
#
181+
# @example Return the edge length
182+
# H3.exact_edge_length_m(1266218516299644927)
183+
# 3.287684056071637e-05
184+
#
185+
# @return [Double] Edge length in metres
186+
attach_function :exact_edge_length_m, :exactEdgeLengthM, %i[h3_index], :double
187+
188+
# Returns the radians distance between two points.
189+
#
190+
# @example Return radians distance.
191+
# H3.point_distance_rads([41.3964809, 2.160444], [41.3870609, 2.164917])
192+
# 0.00017453024784008713
193+
#
194+
# @return [Double] Radians distance between two points.
195+
def point_distance_rads(origin, destination)
196+
Bindings::Private.point_distance_rads(*build_geocoords(origin, destination))
197+
end
198+
199+
# Returns the kilometres distance between two points.
200+
#
201+
# @example Return km distance.
202+
# H3.point_distance_km([41.3964809, 2.160444], [41.3870609, 2.164917])
203+
# 1.1119334622766763
204+
#
205+
# @return [Double] KM distance between two points.
206+
def point_distance_km(origin, destination)
207+
Bindings::Private.point_distance_km(*build_geocoords(origin, destination))
208+
end
209+
210+
# Returns the metre distance between two points.
211+
#
212+
# @example Return metre distance.
213+
# H3.point_distance_m([41.3964809, 2.160444], [41.3870609, 2.164917])
214+
# 1111.9334622766764
215+
#
216+
# @return [Double] Metre distance between two points.
217+
def point_distance_m(origin, destination)
218+
Bindings::Private.point_distance_m(*build_geocoords(origin, destination))
219+
end
220+
122221
# Returns all resolution 0 hexagons (base cells).
123222
#
124223
# @example Return all base cells.
@@ -144,5 +243,29 @@ def pentagons(resolution)
144243
Bindings::Private.get_pentagon_indexes(resolution, out)
145244
out.read
146245
end
246+
247+
private
248+
249+
def build_geocoords(origin, destination)
250+
[origin, destination].inject([]) do |acc, coords|
251+
validate_coordinate(coords)
252+
253+
geo_coord = GeoCoord.new
254+
lat, lon = coords
255+
geo_coord[:lat] = degs_to_rads(lat)
256+
geo_coord[:lon] = degs_to_rads(lon)
257+
acc << geo_coord
258+
end
259+
end
260+
261+
def validate_coordinate(coords)
262+
raise ArgumentError unless coords.is_a?(Array) && coords.count == 2
263+
264+
lat, lon = coords
265+
266+
if lat > 90 || lat < -90 || lon > 180 || lon < -180
267+
raise(ArgumentError, "Invalid coordinates")
268+
end
269+
end
147270
end
148271
end

lib/h3/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module H3
2-
VERSION = "3.6.4".freeze
2+
VERSION = "3.7.1".freeze
33
end

spec/miscellaneous_spec.rb

+117
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,121 @@
109109
expect(pentagons).to eq(expected)
110110
end
111111
end
112+
113+
describe ".cell_area_rads2" do
114+
let(:cell) { "8928308280fffff".to_i(16) }
115+
let(:expected) { 2.6952182709835757e-09 }
116+
subject(:cell_area_rads2) { H3.cell_area_rads2(cell) }
117+
118+
it "returns cell area in rads2" do
119+
expect(cell_area_rads2).to be_within(0.0001).of(expected)
120+
end
121+
end
122+
123+
describe ".cell_area_km2" do
124+
let(:cell) { "8928308280fffff".to_i(16) }
125+
let(:expected) { 0.10939818864648902 }
126+
subject(:cell_area_km2) { H3.cell_area_km2(cell) }
127+
128+
it "returns cell area in km2" do
129+
expect(cell_area_km2).to be_within(0.0001).of(expected)
130+
end
131+
end
132+
133+
describe ".cell_area_m2" do
134+
let(:cell) { "8928308280fffff".to_i(16) }
135+
let(:expected) { 109398.18864648901 }
136+
subject(:cell_area_m2) { H3.cell_area_m2(cell) }
137+
138+
it "returns cell area in m2" do
139+
expect(cell_area_m2).to be_within(0.0001).of(expected)
140+
end
141+
end
142+
143+
describe ".exact_edge_length_rads" do
144+
let(:cell) { "11928308280fffff".to_i(16) }
145+
let(:expected) { 3.287684056071637e-05 }
146+
subject(:exact_edge_length_rads) { H3.exact_edge_length_rads(cell) }
147+
148+
it "returns edge length in rads" do
149+
expect(exact_edge_length_rads).to be_within(0.0001).of(expected)
150+
end
151+
end
152+
153+
describe ".exact_edge_length_km" do
154+
let(:cell) { "11928308280fffff".to_i(16) }
155+
let(:expected) { 0.20945858729823577 }
156+
subject(:exact_edge_length_km) { H3.exact_edge_length_km(cell) }
157+
158+
it "returns edge length in km" do
159+
expect(exact_edge_length_km).to be_within(0.0001).of(expected)
160+
end
161+
end
162+
163+
describe ".exact_edge_length_m" do
164+
let(:cell) { "11928308280fffff".to_i(16) }
165+
let(:expected) { 209.45858729823578 }
166+
subject(:exact_edge_length_m) { H3.exact_edge_length_m(cell) }
167+
168+
it "returns edge length in m" do
169+
expect(exact_edge_length_m).to be_within(0.0001).of(expected)
170+
end
171+
end
172+
173+
describe ".point_distance_rads" do
174+
let(:a) { [41.3964809, 2.160444] }
175+
let(:b) { [41.3870609, 2.164917] }
176+
let(:expected) { 0.00017453024784008713 }
177+
subject(:point_distance_rads) { H3.point_distance_rads(a, b) }
178+
179+
it "returns distance between points in rads" do
180+
expect(point_distance_rads).to be_within(0.0001).of(expected)
181+
end
182+
183+
context "when the coordinates are invalid" do
184+
let(:a) { [91, -18] }
185+
186+
it "raises an argument error" do
187+
expect { point_distance_rads }.to raise_error(ArgumentError)
188+
end
189+
end
190+
end
191+
192+
describe ".point_distance_km" do
193+
let(:a) { [41.3964809, 2.160444] }
194+
let(:b) { [41.3870609, 2.164917] }
195+
let(:expected) { 1.1119334622766763 }
196+
subject(:point_distance_km) { H3.point_distance_km(a, b) }
197+
198+
it "returns distance between points in km" do
199+
expect(point_distance_km).to be_within(0.0001).of(expected)
200+
end
201+
202+
context "when the coordinates are invalid" do
203+
let(:a) { [89, -181] }
204+
205+
it "raises an argument error" do
206+
expect { point_distance_km }.to raise_error(ArgumentError)
207+
end
208+
end
209+
end
210+
211+
describe ".point_distance_m" do
212+
let(:a) { [41.3964809, 2.160444] }
213+
let(:b) { [41.3870609, 2.164917] }
214+
let(:expected) { 1111.9334622766764 }
215+
subject(:point_distance_m) { H3.point_distance_m(a, b) }
216+
217+
it "returns distance between points in m" do
218+
expect(point_distance_m).to be_within(0.0001).of(expected)
219+
end
220+
221+
context "when the coordinates are invalid" do
222+
let(:a) { "boom" }
223+
224+
it "raises an argument error" do
225+
expect { point_distance_m }.to raise_error(ArgumentError)
226+
end
227+
end
228+
end
112229
end

0 commit comments

Comments
 (0)