h3 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +19 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.rubocop.yml +255 -0
- data/.travis.yml +19 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -0
- data/LICENSE.md +21 -0
- data/README.md +51 -0
- data/Rakefile +3 -0
- data/h3.gemspec +21 -0
- data/lib/h3.rb +36 -0
- data/lib/h3/bindings.rb +12 -0
- data/lib/h3/bindings/base.rb +15 -0
- data/lib/h3/bindings/private.rb +32 -0
- data/lib/h3/bindings/structs.rb +59 -0
- data/lib/h3/geo_json.rb +169 -0
- data/lib/h3/hierarchy.rb +160 -0
- data/lib/h3/indexing.rb +80 -0
- data/lib/h3/inspection.rb +105 -0
- data/lib/h3/miscellaneous.rb +99 -0
- data/lib/h3/regions.rb +239 -0
- data/lib/h3/traversal.rb +287 -0
- data/lib/h3/unidirectional_edges.rb +146 -0
- data/lib/h3/version.rb +3 -0
- data/spec/geo_json_spec.rb +118 -0
- data/spec/hierarchy_spec.rb +159 -0
- data/spec/indexing_spec.rb +92 -0
- data/spec/inspection_spec.rb +90 -0
- data/spec/miscellaneous_spec.rb +75 -0
- data/spec/region_spec.rb +71 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/support/fixtures/australia.json +1 -0
- data/spec/support/fixtures/banbury.json +1 -0
- data/spec/support/fixtures/banbury_feature.json +93 -0
- data/spec/support/fixtures/banbury_feature_collection.json +98 -0
- data/spec/support/fixtures/banbury_out.json +1 -0
- data/spec/support/fixtures/banbury_without_holes.json +1 -0
- data/spec/support/shared_contexts/constants.rb +4 -0
- data/spec/traversal_spec.rb +343 -0
- data/spec/unidirectional_edges_spec.rb +119 -0
- metadata +155 -0
data/lib/h3/traversal.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
module H3
|
2
|
+
# Grid traversal functions
|
3
|
+
#
|
4
|
+
# @see https://uber.github.io/h3/#/documentation/api-reference/traversal
|
5
|
+
module Traversal
|
6
|
+
extend H3::Bindings::Base
|
7
|
+
|
8
|
+
# @!method max_kring_size(k)
|
9
|
+
#
|
10
|
+
# Derive the maximum k-ring size for distance k.
|
11
|
+
#
|
12
|
+
# @param [Integer] k K value.
|
13
|
+
#
|
14
|
+
# @example Derive the maximum k-ring size for k=5
|
15
|
+
# H3.max_kring_size(5)
|
16
|
+
# 91
|
17
|
+
#
|
18
|
+
# @return [Integer] Maximum k-ring size.
|
19
|
+
attach_function :max_kring_size, :maxKringSize, [ :int ], :int
|
20
|
+
|
21
|
+
# @!method h3_distance(origin, h3_index)
|
22
|
+
#
|
23
|
+
# Derive the distance between two H3 indexes.
|
24
|
+
#
|
25
|
+
# @param [Integer] origin Origin H3 index
|
26
|
+
# @param [Integer] h3_index H3 index
|
27
|
+
#
|
28
|
+
# @example Derive the distance between two H3 indexes.
|
29
|
+
# H3.h3_distance(617700169983721471, 617700169959866367)
|
30
|
+
# 5
|
31
|
+
#
|
32
|
+
# @return [Integer] Distance between indexes.
|
33
|
+
attach_function :h3_distance, :h3Distance, [ :h3_index, :h3_index], :int
|
34
|
+
|
35
|
+
# Derives H3 indexes within k distance of the origin H3 index.
|
36
|
+
#
|
37
|
+
# Similar to {k_ring}, except that an error is raised when one of the indexes
|
38
|
+
# returned is a pentagon or is in the pentagon distortion area.
|
39
|
+
#
|
40
|
+
# k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0
|
41
|
+
# and all neighboring indexes, and so on.
|
42
|
+
#
|
43
|
+
# Output is inserted into the array in order of increasing distance from the origin.
|
44
|
+
#
|
45
|
+
# @param [Integer] origin Origin H3 index
|
46
|
+
# @param [Integer] k K distance.
|
47
|
+
#
|
48
|
+
# @example Derive the hex range for a given H3 index with k of 0.
|
49
|
+
# H3.hex_range(617700169983721471, 0)
|
50
|
+
# [617700169983721471]
|
51
|
+
#
|
52
|
+
# @example Derive the hex range for a given H3 index with k of 1.
|
53
|
+
# H3.hex_range(617700169983721471, 1)
|
54
|
+
# [
|
55
|
+
# 617700169983721471, 617700170047946751, 617700169984245759,
|
56
|
+
# 617700169982672895, 617700169983983615, 617700170044276735,
|
57
|
+
# 617700170044014591
|
58
|
+
# ]
|
59
|
+
#
|
60
|
+
# @raise [ArgumentError] Raised if the range contains a pentagon.
|
61
|
+
#
|
62
|
+
# @return [Array<Integer>] Array of H3 indexes within the k-range.
|
63
|
+
def hex_range(origin, k)
|
64
|
+
max_hexagons = max_kring_size(k)
|
65
|
+
hexagons = FFI::MemoryPointer.new(:ulong_long, max_hexagons)
|
66
|
+
pentagonal_distortion = Bindings::Private.hex_range(origin, k, hexagons)
|
67
|
+
raise(ArgumentError, "Specified hexagon range contains a pentagon") if pentagonal_distortion
|
68
|
+
hexagons.read_array_of_ulong_long(max_hexagons).reject(&:zero?)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Derives H3 indexes within k distance of the origin H3 index.
|
72
|
+
#
|
73
|
+
# k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0
|
74
|
+
# and all neighboring indexes, and so on.
|
75
|
+
#
|
76
|
+
# @param [Integer] origin Origin H3 index
|
77
|
+
# @param [Integer] k K distance.
|
78
|
+
#
|
79
|
+
# @example Derive the k-ring for a given H3 index with k of 0.
|
80
|
+
# H3.k_ring(617700169983721471, 0)
|
81
|
+
# [617700169983721471]
|
82
|
+
#
|
83
|
+
# @example Derive the k-ring for a given H3 index with k of 1.
|
84
|
+
# H3.k_ring(617700169983721471, 1)
|
85
|
+
# [
|
86
|
+
# 617700169983721471, 617700170047946751, 617700169984245759,
|
87
|
+
# 617700169982672895, 617700169983983615, 617700170044276735,
|
88
|
+
# 617700170044014591
|
89
|
+
# ]
|
90
|
+
#
|
91
|
+
# @return [Array<Integer>] Array of H3 indexes within the k-range.
|
92
|
+
def k_ring(origin, k)
|
93
|
+
max_hexagons = max_kring_size(k)
|
94
|
+
hexagons = FFI::MemoryPointer.new(:ulong_long, max_hexagons)
|
95
|
+
Bindings::Private.k_ring(origin, k, hexagons)
|
96
|
+
hexagons.read_array_of_ulong_long(max_hexagons).reject(&:zero?)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Derives the hollow hexagonal ring centered at origin with sides of length k.
|
100
|
+
#
|
101
|
+
# An error is raised when one of the indexes returned is a pentagon or is
|
102
|
+
# in the pentagon distortion area.
|
103
|
+
#
|
104
|
+
# @param [Integer] origin Origin H3 index.
|
105
|
+
# @param [Integer] k K distance.
|
106
|
+
#
|
107
|
+
# @example Derive the hex ring for the H3 index at k = 1
|
108
|
+
# H3.hex_ring(617700169983721471, 1)
|
109
|
+
# [
|
110
|
+
# 617700170044014591, 617700170047946751, 617700169984245759,
|
111
|
+
# 617700169982672895, 617700169983983615, 617700170044276735
|
112
|
+
# ]
|
113
|
+
#
|
114
|
+
# @raise [ArgumentError] Raised if the hex ring contains a pentagon.
|
115
|
+
#
|
116
|
+
# @return [Array<Integer>] Array of H3 indexes within the hex ring.
|
117
|
+
def hex_ring(origin, k)
|
118
|
+
max_hexagons = max_hex_ring_size(k)
|
119
|
+
hexagons = FFI::MemoryPointer.new(:ulong_long, max_hexagons)
|
120
|
+
pentagonal_distortion = Bindings::Private.hex_ring(origin, k, hexagons)
|
121
|
+
raise(ArgumentError, "The hex ring contains a pentagon") if pentagonal_distortion
|
122
|
+
hexagons.read_array_of_ulong_long(max_hexagons).reject(&:zero?)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Derive the maximum hex ring size for a given distance k.
|
126
|
+
#
|
127
|
+
# NOTE: This method is not part of the H3 API and is added to this binding for convenience.
|
128
|
+
#
|
129
|
+
# @param [Integer] k K distance.
|
130
|
+
#
|
131
|
+
# @example Derive maximum hex ring size for k distance 6.
|
132
|
+
# H3.max_hex_ring_size(6)
|
133
|
+
# 36
|
134
|
+
#
|
135
|
+
# @return [Integer] Maximum hex ring size.
|
136
|
+
def max_hex_ring_size(k)
|
137
|
+
k.zero? ? 1 : 6 * k
|
138
|
+
end
|
139
|
+
|
140
|
+
# Derives H3 indexes within k distance for each H3 index in the set.
|
141
|
+
#
|
142
|
+
# @param [Array<Integer>] h3_set Set of H3 indexes
|
143
|
+
# @param [Integer] k K distance.
|
144
|
+
# @param [Boolean] grouped Whether to group the output. Default true.
|
145
|
+
#
|
146
|
+
# @example Derive the hex ranges for a given H3 set with k of 0.
|
147
|
+
# H3.hex_ranges([617700169983721471, 617700169982672895], 1)
|
148
|
+
# {
|
149
|
+
# 617700169983721471 => [
|
150
|
+
# [617700169983721471],
|
151
|
+
# [
|
152
|
+
# 617700170047946751, 617700169984245759, 617700169982672895,
|
153
|
+
# 617700169983983615, 617700170044276735, 617700170044014591
|
154
|
+
# ]
|
155
|
+
# ],
|
156
|
+
# 617700169982672895 = > [
|
157
|
+
# [617700169982672895],
|
158
|
+
# [
|
159
|
+
# 617700169984245759, 617700169983197183, 617700169983459327,
|
160
|
+
# 617700169982935039, 617700169983983615, 617700169983721471
|
161
|
+
# ]
|
162
|
+
# ]
|
163
|
+
# }
|
164
|
+
#
|
165
|
+
# @example Derive the hex ranges for a given H3 set with k of 0 ungrouped.
|
166
|
+
# H3.hex_ranges([617700169983721471, 617700169982672895], 1, grouped: false)
|
167
|
+
# [
|
168
|
+
# 617700169983721471, 617700170047946751, 617700169984245759,
|
169
|
+
# 617700169982672895, 617700169983983615, 617700170044276735,
|
170
|
+
# 617700170044014591, 617700169982672895, 617700169984245759,
|
171
|
+
# 617700169983197183, 617700169983459327, 617700169982935039,
|
172
|
+
# 617700169983983615, 617700169983721471
|
173
|
+
# ]
|
174
|
+
#
|
175
|
+
# @raise [ArgumentError] Raised if any of the ranges contains a pentagon.
|
176
|
+
#
|
177
|
+
# @see #hex_range
|
178
|
+
#
|
179
|
+
# @return [Hash] Hash of H3 index keys, with array values grouped by k-ring.
|
180
|
+
def hex_ranges(h3_set, k, grouped: true)
|
181
|
+
h3_range_indexes = hex_ranges_ungrouped(h3_set, k)
|
182
|
+
return h3_range_indexes unless grouped
|
183
|
+
out = {}
|
184
|
+
h3_range_indexes.each_slice(max_kring_size(k)).each do |indexes|
|
185
|
+
h3_index = indexes.first
|
186
|
+
|
187
|
+
out[h3_index] = 0.upto(k).map do |j|
|
188
|
+
start = j == 0 ? 0 : max_kring_size(j-1)
|
189
|
+
length = max_hex_ring_size(j)
|
190
|
+
indexes.slice(start, length)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
out
|
194
|
+
end
|
195
|
+
|
196
|
+
# Derives the hex range for the given origin at k distance, sub-grouped by distance.
|
197
|
+
#
|
198
|
+
# @param [Integer] origin Origin H3 index.
|
199
|
+
# @param [Integer] k K distance.
|
200
|
+
#
|
201
|
+
# @example Derive hex range at distance 2
|
202
|
+
# H3.hex_range_distances(617700169983721471, 2)
|
203
|
+
# {
|
204
|
+
# 0 => [617700169983721471],
|
205
|
+
# 1 = >[
|
206
|
+
# 617700170047946751, 617700169984245759, 617700169982672895,
|
207
|
+
# 617700169983983615, 617700170044276735, 617700170044014591
|
208
|
+
# ],
|
209
|
+
# 2 => [
|
210
|
+
# 617700170048995327, 617700170047684607, 617700170048471039,
|
211
|
+
# 617700169988177919, 617700169983197183, 617700169983459327,
|
212
|
+
# 617700169982935039, 617700175096053759, 617700175097102335,
|
213
|
+
# 617700170043752447, 617700170043490303, 617700170045063167
|
214
|
+
# ]
|
215
|
+
# }
|
216
|
+
#
|
217
|
+
# @raise [ArgumentError] Raised when the hex range contains a pentagon.
|
218
|
+
#
|
219
|
+
# @return [Hash] Hex range grouped by distance.
|
220
|
+
def hex_range_distances(origin, k)
|
221
|
+
max_out_size = max_kring_size(k)
|
222
|
+
out = FFI::MemoryPointer.new(H3_INDEX, max_out_size)
|
223
|
+
distances = FFI::MemoryPointer.new(:int, max_out_size)
|
224
|
+
pentagonal_distortion = Bindings::Private.hex_range_distances(origin, k, out, distances)
|
225
|
+
raise(ArgumentError, "Specified hexagon range contains a pentagon") if pentagonal_distortion
|
226
|
+
|
227
|
+
hexagons = out.read_array_of_ulong_long(max_out_size)
|
228
|
+
distances = distances.read_array_of_int(max_out_size)
|
229
|
+
|
230
|
+
Hash[
|
231
|
+
distances.zip(hexagons).group_by(&:first).map { |d, hs| [d, hs.map(&:last)] }
|
232
|
+
]
|
233
|
+
end
|
234
|
+
|
235
|
+
# Derives the k-ring for the given origin at k distance, sub-grouped by distance.
|
236
|
+
#
|
237
|
+
# @param [Integer] origin Origin H3 index.
|
238
|
+
# @param [Integer] k K distance.
|
239
|
+
#
|
240
|
+
# @example Derive k-ring at distance 2
|
241
|
+
# H3.k_ring_distances(617700169983721471, 2)
|
242
|
+
# {
|
243
|
+
# 0 => [617700169983721471],
|
244
|
+
# 1 = >[
|
245
|
+
# 617700170047946751, 617700169984245759, 617700169982672895,
|
246
|
+
# 617700169983983615, 617700170044276735, 617700170044014591
|
247
|
+
# ],
|
248
|
+
# 2 => [
|
249
|
+
# 617700170048995327, 617700170047684607, 617700170048471039,
|
250
|
+
# 617700169988177919, 617700169983197183, 617700169983459327,
|
251
|
+
# 617700169982935039, 617700175096053759, 617700175097102335,
|
252
|
+
# 617700170043752447, 617700170043490303, 617700170045063167
|
253
|
+
# ]
|
254
|
+
# }
|
255
|
+
#
|
256
|
+
# @return [Hash] Hash of k-ring distances grouped by distance.
|
257
|
+
def k_ring_distances(origin, k)
|
258
|
+
max_out_size = max_kring_size(k)
|
259
|
+
out = FFI::MemoryPointer.new(H3_INDEX, max_out_size)
|
260
|
+
distances = FFI::MemoryPointer.new(:int, max_out_size)
|
261
|
+
Bindings::Private.k_ring_distances(origin, k, out, distances)
|
262
|
+
|
263
|
+
hexagons = out.read_array_of_ulong_long(max_out_size)
|
264
|
+
distances = distances.read_array_of_int(max_out_size)
|
265
|
+
|
266
|
+
Hash[
|
267
|
+
distances.zip(hexagons).group_by(&:first).map { |d, hs| [d, hs.map(&:last)] }
|
268
|
+
]
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
|
273
|
+
def hex_ranges_ungrouped(h3_set, k)
|
274
|
+
h3_set = h3_set.uniq
|
275
|
+
max_out_size = h3_set.size * max_kring_size(k)
|
276
|
+
out = FFI::MemoryPointer.new(H3_INDEX, max_out_size)
|
277
|
+
pentagonal_distortion = false
|
278
|
+
FFI::MemoryPointer.new(H3_INDEX, h3_set.size) do |h3_set_ptr|
|
279
|
+
h3_set_ptr.write_array_of_ulong_long(h3_set)
|
280
|
+
pentagonal_distortion = Bindings::Private.hex_ranges(h3_set_ptr, h3_set.size, k, out)
|
281
|
+
end
|
282
|
+
raise(ArgumentError, "One of the specified hexagon ranges contains a pentagon") if pentagonal_distortion
|
283
|
+
|
284
|
+
out.read_array_of_ulong_long(max_out_size)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module H3
|
2
|
+
# Unidirectional edge functions
|
3
|
+
#
|
4
|
+
# @see https://uber.github.io/h3/#/documentation/api-reference/unidirectional-edges
|
5
|
+
module UnidirectionalEdges
|
6
|
+
extend H3::Bindings::Base
|
7
|
+
|
8
|
+
# @!method h3_indexes_neighbors?(origin, destination)
|
9
|
+
#
|
10
|
+
# Determine whether two H3 indexes are neighbors.
|
11
|
+
#
|
12
|
+
# @param [Integer] origin Origin H3 index
|
13
|
+
# @param [Integer] destination Destination H3 index
|
14
|
+
#
|
15
|
+
# @example Check two H3 indexes
|
16
|
+
# H3.h3_indexes_neighbors?(617700169958293503, 617700169958031359)
|
17
|
+
# true
|
18
|
+
#
|
19
|
+
# @return [Boolean] True if indexes are neighbors
|
20
|
+
attach_function :h3_indexes_neighbors, :h3IndexesAreNeighbors, [ :h3_index, :h3_index ], :bool
|
21
|
+
|
22
|
+
# @!method h3_unidirectional_edge_valid?(h3_index)
|
23
|
+
#
|
24
|
+
# Determine whether the given H3 index represents an edge.
|
25
|
+
#
|
26
|
+
# @param [Integer] h3_index H3 index
|
27
|
+
#
|
28
|
+
# @example Check if H3 index is a valid unidirectional edge.
|
29
|
+
# H3.h3_unidirectional_edge_valid?(1266218516299644927)
|
30
|
+
# true
|
31
|
+
#
|
32
|
+
# @return [Boolean] True if H3 index is a valid unidirectional edge
|
33
|
+
attach_function :h3_unidirectional_edge_valid,
|
34
|
+
:h3UnidirectionalEdgeIsValid,
|
35
|
+
[ :h3_index ],
|
36
|
+
:bool
|
37
|
+
|
38
|
+
# @!method h3_unidirectional_edge(origin, destination)
|
39
|
+
#
|
40
|
+
# Derives the H3 index of the edge from the given H3 indexes.
|
41
|
+
#
|
42
|
+
# @param [Integer] origin H3 index
|
43
|
+
# @param [Integer] destination H3 index
|
44
|
+
#
|
45
|
+
# @example Derive the H3 edge index between two H3 indexes
|
46
|
+
# H3.h3_unidirectional_edge(617700169958293503, 617700169958031359)
|
47
|
+
# 1626506486489284607
|
48
|
+
#
|
49
|
+
# @return [Integer] H3 edge index
|
50
|
+
attach_function :h3_unidirectional_edge,
|
51
|
+
:getH3UnidirectionalEdge,
|
52
|
+
[ :h3_index, :h3_index ],
|
53
|
+
:h3_index
|
54
|
+
|
55
|
+
# @!method destination_from_unidirectional_edge(edge)
|
56
|
+
#
|
57
|
+
# Derive destination H3 index from edge.
|
58
|
+
#
|
59
|
+
# @param [Integer] edge H3 edge index
|
60
|
+
#
|
61
|
+
# @example Get destination index from edge
|
62
|
+
# H3.destination_from_unidirectional_edge(1266218516299644927)
|
63
|
+
# 617700169961177087
|
64
|
+
#
|
65
|
+
# @return [Integer] H3 index
|
66
|
+
attach_function :destination_from_unidirectional_edge,
|
67
|
+
:getDestinationH3IndexFromUnidirectionalEdge,
|
68
|
+
[ :h3_index ],
|
69
|
+
:h3_index
|
70
|
+
|
71
|
+
# @!method origin_from_unidirectional_edge(edge)
|
72
|
+
#
|
73
|
+
# Derive origin H3 index from edge.
|
74
|
+
#
|
75
|
+
# @param [Integer] edge H3 edge index
|
76
|
+
#
|
77
|
+
# @example Get origin index from edge
|
78
|
+
# H3.origin_from_unidirectional_edge(1266218516299644927)
|
79
|
+
# 617700169958293503
|
80
|
+
#
|
81
|
+
# @return [Integer] H3 index
|
82
|
+
attach_function :origin_from_unidirectional_edge,
|
83
|
+
:getOriginH3IndexFromUnidirectionalEdge,
|
84
|
+
[ :h3_index ],
|
85
|
+
:h3_index
|
86
|
+
|
87
|
+
# Derive origin and destination H3 indexes from edge.
|
88
|
+
#
|
89
|
+
# Returned in the form
|
90
|
+
#
|
91
|
+
# [origin, destination]
|
92
|
+
#
|
93
|
+
# @param [Integer] edge H3 edge index
|
94
|
+
#
|
95
|
+
# @example Get origin and destination indexes from edge
|
96
|
+
# H3.h3_indexes_from_unidirectional_edge(1266218516299644927)
|
97
|
+
# [617700169958293503, 617700169961177087]
|
98
|
+
#
|
99
|
+
# @return [Array<Integer>] H3 index array.
|
100
|
+
def h3_indexes_from_unidirectional_edge(edge)
|
101
|
+
max_hexagons = 2
|
102
|
+
origin_destination = FFI::MemoryPointer.new(:ulong_long, max_hexagons)
|
103
|
+
Bindings::Private.h3_indexes_from_unidirectional_edge(edge, origin_destination)
|
104
|
+
origin_destination.read_array_of_ulong_long(max_hexagons).reject(&:zero?)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Derive unidirectional edges for a H3 index.
|
108
|
+
#
|
109
|
+
# @param [Integer] origin H3 index
|
110
|
+
#
|
111
|
+
# @example Get unidirectional indexes from hexagon
|
112
|
+
# H3.h3_unidirectional_edges_from_hexagon(1266218516299644927)
|
113
|
+
# [
|
114
|
+
# 1266218516299644927, 1338276110337572863, 1410333704375500799,
|
115
|
+
# 1482391298413428735, 1554448892451356671, 1626506486489284607
|
116
|
+
# ]
|
117
|
+
#
|
118
|
+
# @return [Array<Integer>] H3 index array.
|
119
|
+
def h3_unidirectional_edges_from_hexagon(origin)
|
120
|
+
max_edges = 6
|
121
|
+
edges = FFI::MemoryPointer.new(:ulong_long, max_edges)
|
122
|
+
Bindings::Private.h3_unidirectional_edges_from_hexagon(origin, edges)
|
123
|
+
edges.read_array_of_ulong_long(max_edges).reject(&:zero?)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Derive coordinates for edge boundary.
|
127
|
+
#
|
128
|
+
# @param [Integer] edge H3 edge index
|
129
|
+
#
|
130
|
+
# @example
|
131
|
+
# H3.h3_unidirectional_edge_boundary(1266218516299644927)
|
132
|
+
# [
|
133
|
+
# [37.77820687262237, -122.41971895414808],
|
134
|
+
# [37.77652420699321, -122.42079024541876]
|
135
|
+
# ]
|
136
|
+
#
|
137
|
+
# @return [Array<Array<Float>>] Edge boundary coordinates for a hexagon
|
138
|
+
def h3_unidirectional_edge_boundary(edge)
|
139
|
+
geo_boundary = Bindings::Structs::GeoBoundary.new
|
140
|
+
Bindings::Private.h3_unidirectional_edge_boundary(edge, geo_boundary)
|
141
|
+
geo_boundary[:verts].take(geo_boundary[:num_verts] * 2).map do |d|
|
142
|
+
rads_to_degs(d)
|
143
|
+
end.each_slice(2).to_a
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/h3/version.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
RSpec.describe H3 do
|
2
|
+
# http://geojson.io is helpful for setting up test fixtures
|
3
|
+
describe ".geo_json_to_coordinates" do
|
4
|
+
let(:input) do
|
5
|
+
File.read(File.join(File.dirname(__FILE__), "support/fixtures/banbury.json"))
|
6
|
+
end
|
7
|
+
let(:coordinates) do
|
8
|
+
[
|
9
|
+
[
|
10
|
+
[52.24630137198303, -1.7358398437499998],
|
11
|
+
[52.05249047600099, -1.8923950195312498],
|
12
|
+
[51.891749018068246, -1.56829833984375],
|
13
|
+
[51.91208502557545, -1.27716064453125],
|
14
|
+
[52.032218104145294, -1.19476318359375],
|
15
|
+
[52.19413974159753, -1.24420166015625],
|
16
|
+
[52.24125614966341, -1.5902709960937498],
|
17
|
+
[52.24630137198303, -1.7358398437499998]
|
18
|
+
],
|
19
|
+
[
|
20
|
+
[52.12590076522272, -1.58203125],
|
21
|
+
[52.12590076522272, -1.476287841796875],
|
22
|
+
[52.075285904832334, -1.46392822265625],
|
23
|
+
[52.06937709602395, -1.58203125],
|
24
|
+
[52.12590076522272, -1.58203125]
|
25
|
+
],
|
26
|
+
[
|
27
|
+
[52.01531743663362, -1.4556884765625],
|
28
|
+
[51.97642166216334, -1.483154296875],
|
29
|
+
[51.96626938051444, -1.3677978515625],
|
30
|
+
[52.0102459910103, -1.3568115234375],
|
31
|
+
[52.01531743663362, -1.4556884765625]
|
32
|
+
]
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
subject(:geo_json_to_coordinates) { H3.geo_json_to_coordinates(input) }
|
37
|
+
|
38
|
+
it { is_expected.to eq coordinates }
|
39
|
+
|
40
|
+
context "when given a feature" do
|
41
|
+
let(:input) do
|
42
|
+
File.read(File.join(File.dirname(__FILE__), "support/fixtures/banbury_feature.json"))
|
43
|
+
end
|
44
|
+
|
45
|
+
it { is_expected.to eq coordinates }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when given a feature collection" do
|
49
|
+
let(:input) do
|
50
|
+
File.read(File.join(File.dirname(__FILE__), "support/fixtures/banbury_feature_collection.json"))
|
51
|
+
end
|
52
|
+
|
53
|
+
it { is_expected.to eq coordinates }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when given bad input" do
|
57
|
+
let(:input) { "blah" }
|
58
|
+
|
59
|
+
it "raises an error" do
|
60
|
+
expect { geo_json_to_coordinates }.to raise_error(ArgumentError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ".coordinates_to_geo_json" do
|
66
|
+
let(:input) do
|
67
|
+
[
|
68
|
+
[
|
69
|
+
[52.24630137198303, -1.7358398437499998],
|
70
|
+
[52.05249047600099, -1.8923950195312498],
|
71
|
+
[51.891749018068246, -1.56829833984375],
|
72
|
+
[51.91208502557545, -1.27716064453125],
|
73
|
+
[52.032218104145294, -1.19476318359375],
|
74
|
+
[52.19413974159753, -1.24420166015625],
|
75
|
+
[52.24125614966341, -1.5902709960937498],
|
76
|
+
[52.24630137198303, -1.7358398437499998]
|
77
|
+
],
|
78
|
+
[
|
79
|
+
[52.12590076522272, -1.58203125],
|
80
|
+
[52.12590076522272, -1.476287841796875],
|
81
|
+
[52.075285904832334, -1.46392822265625],
|
82
|
+
[52.06937709602395, -1.58203125],
|
83
|
+
[52.12590076522272, -1.58203125]
|
84
|
+
],
|
85
|
+
[
|
86
|
+
[52.01531743663362, -1.4556884765625],
|
87
|
+
[51.97642166216334, -1.483154296875],
|
88
|
+
[51.96626938051444, -1.3677978515625],
|
89
|
+
[52.0102459910103, -1.3568115234375],
|
90
|
+
[52.01531743663362, -1.4556884765625]
|
91
|
+
]
|
92
|
+
]
|
93
|
+
end
|
94
|
+
let(:geojson) do
|
95
|
+
File.read(File.join(File.dirname(__FILE__), "support/fixtures/banbury.json"))
|
96
|
+
end
|
97
|
+
|
98
|
+
subject(:coordinates_to_geo_json) { H3.coordinates_to_geo_json(input) }
|
99
|
+
|
100
|
+
it { is_expected.to eq geojson }
|
101
|
+
|
102
|
+
context "when given bad input" do
|
103
|
+
let(:input) { "blah" }
|
104
|
+
|
105
|
+
it "raises an error" do
|
106
|
+
expect { coordinates_to_geo_json }.to raise_error(ArgumentError)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when given nested bad input" do
|
111
|
+
let(:input) { [[],[[[[]]]]] }
|
112
|
+
|
113
|
+
it "raises an error" do
|
114
|
+
expect { coordinates_to_geo_json }.to raise_error(ArgumentError)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|