geos-extensions 1.0.0 → 2.0.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 +4 -4
- data/.travis.yml +17 -0
- data/MIT-LICENSE +1 -1
- data/Rakefile +2 -0
- data/lib/geos-extensions.rb +6 -0
- data/lib/geos/coordinate_sequence.rb +290 -12
- data/lib/geos/extensions/exceptions.rb +2 -0
- data/lib/geos/extensions/version.rb +3 -1
- data/lib/geos/geometry.rb +3 -1
- data/lib/geos/geometry_collection.rb +52 -0
- data/lib/geos/geos_helper.rb +2 -0
- data/lib/geos/google_maps.rb +2 -0
- data/lib/geos/google_maps/api_2.rb +2 -0
- data/lib/geos/google_maps/api_3.rb +2 -0
- data/lib/geos/google_maps/api_common.rb +2 -0
- data/lib/geos/google_maps/polyline_encoder.rb +2 -0
- data/lib/geos/line_string.rb +123 -0
- data/lib/geos/multi_line_string.rb +2 -0
- data/lib/geos/multi_point.rb +2 -0
- data/lib/geos/multi_polygon.rb +2 -0
- data/lib/geos/point.rb +59 -0
- data/lib/geos/polygon.rb +97 -0
- data/lib/geos/yaml.rb +1 -0
- data/lib/geos/yaml/psych.rb +1 -0
- data/lib/geos/yaml/syck.rb +1 -0
- data/lib/geos_extensions.rb +2 -0
- data/test/coordinate_sequence_tests.rb +256 -0
- data/test/geometry_collection_tests.rb +429 -0
- data/test/geometry_tests.rb +57 -0
- data/test/google_maps_api_2_tests.rb +2 -0
- data/test/google_maps_api_3_tests.rb +2 -0
- data/test/google_maps_api_common_tests.rb +2 -0
- data/test/google_maps_polyline_encoder_tests.rb +2 -0
- data/test/helper_tests.rb +2 -0
- data/test/line_string_tests.rb +211 -0
- data/test/misc_tests.rb +2 -0
- data/test/point_tests.rb +173 -0
- data/test/polygon_tests.rb +329 -0
- data/test/reader_tests.rb +2 -0
- data/test/test_helper.rb +73 -3
- data/test/writer_tests.rb +2 -0
- data/test/yaml_tests.rb +1 -0
- metadata +16 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 376ec274e23a76e893dfe82e9a129328b8c22802
|
4
|
+
data.tar.gz: b9b7638b716febc1f4cf5f073ae33d3f11a79e02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06d9bb0eaabeb674ed1e6569894e06bb928f932326143e821772e2732486fb82822feada9db361b727321398fa351a3fc899ba6951f8e789897eb0cc5429ab01
|
7
|
+
data.tar.gz: 57d7ef96672139403b437f3c755d32280a20ac2c34e79b8eb3e36f5961d0f9867fe989475a4ce62f7f3423289a0808c16c2589e14069026f569ff27811681169
|
data/.travis.yml
ADDED
data/MIT-LICENSE
CHANGED
data/Rakefile
CHANGED
data/lib/geos-extensions.rb
CHANGED
@@ -1,18 +1,8 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
|
2
4
|
module Geos
|
3
5
|
class CoordinateSequence
|
4
|
-
# Returns a Ruby Array of Arrays of coordinates within the
|
5
|
-
# CoordinateSequence in the form [ x, y, z ].
|
6
|
-
def to_a
|
7
|
-
(0...self.length).to_a.collect do |p|
|
8
|
-
[
|
9
|
-
self.get_x(p),
|
10
|
-
(self.dimensions >= 2 ? self.get_y(p) : nil),
|
11
|
-
(self.dimensions >= 3 && self.get_z(p) > 1.7e-306 ? self.get_z(p) : nil)
|
12
|
-
].compact
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
6
|
# Build some XmlMarkup for KML. You can set various KML options like
|
17
7
|
# tessellate, altitudeMode, etc. Use Rails/Ruby-style code and it
|
18
8
|
# will be converted automatically, i.e. :altitudeMode, not
|
@@ -87,6 +77,294 @@ module Geos
|
|
87
77
|
def to_geojson(options = {})
|
88
78
|
self.to_geojsonable(options).to_json
|
89
79
|
end
|
80
|
+
|
81
|
+
%w{ x y z }.each do |m|
|
82
|
+
class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
83
|
+
def #{m}_max
|
84
|
+
ret = nil
|
85
|
+
self.length.times do |i|
|
86
|
+
value = self.get_#{m}(i)
|
87
|
+
ret = value if !ret || value >= ret
|
88
|
+
end
|
89
|
+
ret
|
90
|
+
end
|
91
|
+
|
92
|
+
def #{m}_min
|
93
|
+
ret = nil
|
94
|
+
self.length.times do |i|
|
95
|
+
value = self.get_#{m}(i)
|
96
|
+
ret = value if !ret || value <= ret
|
97
|
+
end
|
98
|
+
ret
|
99
|
+
end
|
100
|
+
EOF
|
101
|
+
end
|
102
|
+
|
103
|
+
def snap_to_grid!(*args)
|
104
|
+
grid = {
|
105
|
+
:offset_x => 0, # 1
|
106
|
+
:offset_y => 0, # 2
|
107
|
+
:offset_z => 0, # -
|
108
|
+
:size_x => 0, # 3
|
109
|
+
:size_y => 0, # 4
|
110
|
+
:size_z => 0 # -
|
111
|
+
}
|
112
|
+
|
113
|
+
if args.length == 1 && args[0].is_a?(Numeric)
|
114
|
+
grid[:size_x] = grid[:size_y] = grid[:size_z] = args[0]
|
115
|
+
elsif args[0].is_a?(Hash)
|
116
|
+
grid.merge!(args[0])
|
117
|
+
end
|
118
|
+
|
119
|
+
if grid[:size]
|
120
|
+
grid[:size_x] = grid[:size_y] = grid[:size_z] = grid[:size]
|
121
|
+
end
|
122
|
+
|
123
|
+
if grid[:offset]
|
124
|
+
case grid[:offset]
|
125
|
+
when Geos::Geometry
|
126
|
+
point = grid[:offset].centroid
|
127
|
+
|
128
|
+
grid[:offset_x] = point.x
|
129
|
+
grid[:offset_y] = point.y
|
130
|
+
grid[:offset_z] = point.z
|
131
|
+
when Array
|
132
|
+
grid[:offset_x], grid[:offset_y], grid[:offset_z] = grid[:offset]
|
133
|
+
else
|
134
|
+
raise ArgumentError.new("Expected :offset option to be a Geos::Point")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
self.length.times do |i|
|
139
|
+
if grid[:size_x] != 0
|
140
|
+
self.x[i] = ((self.x[i] - grid[:offset_x]) / grid[:size_x]).round * grid[:size_x] + grid[:offset_x]
|
141
|
+
end
|
142
|
+
|
143
|
+
if grid[:size_y] != 0
|
144
|
+
self.y[i] = ((self.y[i] - grid[:offset_y]) / grid[:size_y]).round * grid[:size_y] + grid[:offset_y]
|
145
|
+
end
|
146
|
+
|
147
|
+
if self.has_z? && grid[:size_z] != 0
|
148
|
+
self.z[i] = ((self.z[i] - grid[:offset_z]) / grid[:size_z]).round * grid[:size_z] + grid[:offset_z]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
cs = self.remove_duplicate_coords
|
153
|
+
@ptr = cs.ptr
|
154
|
+
|
155
|
+
self
|
156
|
+
end
|
157
|
+
|
158
|
+
def snap_to_grid(*args)
|
159
|
+
self.dup.snap_to_grid!(*args)
|
160
|
+
end
|
161
|
+
|
162
|
+
def remove_duplicate_coords
|
163
|
+
Geos::CoordinateSequence.new(self.to_a.inject([]) { |memo, v|
|
164
|
+
memo << v unless memo.last == v
|
165
|
+
memo
|
166
|
+
})
|
167
|
+
end
|
168
|
+
|
169
|
+
def affine!(options)
|
170
|
+
options.default = 0.0
|
171
|
+
|
172
|
+
if self.has_z?
|
173
|
+
self.length.times do |i|
|
174
|
+
x, y, z = self.x[i], self.y[i], self.z[i]
|
175
|
+
|
176
|
+
self.x[i] = options[:afac] * x + options[:bfac] * y + options[:cfac] * z + options[:xoff]
|
177
|
+
self.y[i] = options[:dfac] * x + options[:efac] * y + options[:ffac] * z + options[:yoff]
|
178
|
+
self.z[i] = options[:gfac] * x + options[:hfac] * y + options[:ifac] * z + options[:zoff]
|
179
|
+
end
|
180
|
+
else
|
181
|
+
self.length.times do |i|
|
182
|
+
x, y = self.x[i], self.y[i]
|
183
|
+
|
184
|
+
self.x[i] = options[:afac] * x + options[:bfac] * y + options[:xoff]
|
185
|
+
self.y[i] = options[:dfac] * x + options[:efac] * y + options[:yoff]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
self
|
190
|
+
end
|
191
|
+
|
192
|
+
def affine(options)
|
193
|
+
self.dup.affine!(options)
|
194
|
+
end
|
195
|
+
|
196
|
+
def rotate!(radians, origin = [ 0.0, 0.0 ])
|
197
|
+
origin = case origin
|
198
|
+
when Array
|
199
|
+
origin
|
200
|
+
when Geos::Geometry
|
201
|
+
center = origin.centroid
|
202
|
+
[ center.x, center.y ]
|
203
|
+
else
|
204
|
+
raise ArgumentError.new("Expected an Array or a Geos::Geometry for the origin")
|
205
|
+
end
|
206
|
+
|
207
|
+
self.affine!({
|
208
|
+
:afac => Math.cos(radians),
|
209
|
+
:bfac => -Math.sin(radians),
|
210
|
+
:cfac => 0,
|
211
|
+
:dfac => Math.sin(radians),
|
212
|
+
:efac => Math.cos(radians),
|
213
|
+
:ffac => 0,
|
214
|
+
:gfac => 0,
|
215
|
+
:hfac => 0,
|
216
|
+
:ifac => 1,
|
217
|
+
:xoff => origin[0] - Math.cos(radians) * origin[0] + Math.sin(radians) * origin[1],
|
218
|
+
:yoff => origin[1] - Math.sin(radians) * origin[0] - Math.cos(radians) * origin[1],
|
219
|
+
:zoff => 0
|
220
|
+
})
|
221
|
+
end
|
222
|
+
|
223
|
+
def rotate(radians, origin = [ 0.0, 0.0 ])
|
224
|
+
self.dup.rotate!(radians, origin)
|
225
|
+
end
|
226
|
+
|
227
|
+
def rotate_x!(radians)
|
228
|
+
self.affine!({
|
229
|
+
:afac => 1,
|
230
|
+
:bfac => 0,
|
231
|
+
:cfac => 0,
|
232
|
+
:dfac => 0,
|
233
|
+
:efac => Math.cos(radians),
|
234
|
+
:ffac => -Math.sin(radians),
|
235
|
+
:gfac => 0,
|
236
|
+
:hfac => Math.sin(radians),
|
237
|
+
:ifac => Math.cos(radians),
|
238
|
+
:xoff => 0,
|
239
|
+
:yoff => 0,
|
240
|
+
:zoff => 0
|
241
|
+
})
|
242
|
+
end
|
243
|
+
|
244
|
+
def rotate_x(radians)
|
245
|
+
self.dup.rotate_x!(radians)
|
246
|
+
end
|
247
|
+
|
248
|
+
def rotate_y!(radians)
|
249
|
+
self.affine!({
|
250
|
+
:afac => Math.cos(radians),
|
251
|
+
:bfac => 0,
|
252
|
+
:cfac => Math.sin(radians),
|
253
|
+
:dfac => 0,
|
254
|
+
:efac => 1,
|
255
|
+
:ffac => 0,
|
256
|
+
:gfac => -Math.sin(radians),
|
257
|
+
:hfac => 0,
|
258
|
+
:ifac => Math.cos(radians),
|
259
|
+
:xoff => 0,
|
260
|
+
:yoff => 0,
|
261
|
+
:zoff => 0
|
262
|
+
})
|
263
|
+
end
|
264
|
+
|
265
|
+
def rotate_y(radians)
|
266
|
+
self.dup.rotate_y!(radians)
|
267
|
+
end
|
268
|
+
|
269
|
+
def rotate_z!(radians)
|
270
|
+
self.rotate!(radians)
|
271
|
+
end
|
272
|
+
|
273
|
+
def rotate_z(radians)
|
274
|
+
self.dup.rotate!(radians)
|
275
|
+
end
|
276
|
+
|
277
|
+
def scale!(*args)
|
278
|
+
x, y, z = if args.length == 1 && args[0].is_a?(Hash)
|
279
|
+
args[0].values_at(:x, :y, :z)
|
280
|
+
elsif args.length.between?(1, 3)
|
281
|
+
args.values_at(0...3)
|
282
|
+
else
|
283
|
+
raise ArgumentError.new("Wrong number of arguments #{args.length} for 1-3")
|
284
|
+
end
|
285
|
+
|
286
|
+
self.affine!({
|
287
|
+
:afac => x || 1,
|
288
|
+
:bfac => 0,
|
289
|
+
:cfac => 0,
|
290
|
+
:dfac => 0,
|
291
|
+
:efac => y || 1,
|
292
|
+
:ffac => 0,
|
293
|
+
:gfac => 0,
|
294
|
+
:hfac => 0,
|
295
|
+
:ifac => z || 1,
|
296
|
+
:xoff => 0,
|
297
|
+
:yoff => 0,
|
298
|
+
:zoff => 0
|
299
|
+
})
|
300
|
+
end
|
301
|
+
|
302
|
+
def scale(*args)
|
303
|
+
self.dup.scale!(*args)
|
304
|
+
end
|
305
|
+
|
306
|
+
def trans_scale!(*args)
|
307
|
+
delta_x, delta_y, x_factor, y_factor = if args.length == 1 && args[0].is_a?(Hash)
|
308
|
+
args[0].values_at(:delta_x, :delta_y, :x_factor, :y_factor)
|
309
|
+
elsif args.length.between?(1, 4)
|
310
|
+
args.values_at(0...4)
|
311
|
+
else
|
312
|
+
raise ArgumentError.new("Wrong number of arguments #{args.length} for 1-4")
|
313
|
+
end
|
314
|
+
|
315
|
+
x_factor ||= 1
|
316
|
+
y_factor ||= 1
|
317
|
+
delta_x ||= 0
|
318
|
+
delta_y ||= 0
|
319
|
+
|
320
|
+
self.affine!({
|
321
|
+
:afac => x_factor,
|
322
|
+
:bfac => 0,
|
323
|
+
:cfac => 0,
|
324
|
+
:dfac => 0,
|
325
|
+
:efac => y_factor,
|
326
|
+
:ffac => 0,
|
327
|
+
:gfac => 0,
|
328
|
+
:hfac => 0,
|
329
|
+
:ifac => 1,
|
330
|
+
:xoff => delta_x * x_factor,
|
331
|
+
:yoff => delta_y * y_factor,
|
332
|
+
:zoff => 0
|
333
|
+
})
|
334
|
+
end
|
335
|
+
|
336
|
+
def trans_scale(*args)
|
337
|
+
self.dup.trans_scale!(*args)
|
338
|
+
end
|
339
|
+
|
340
|
+
def translate!(*args)
|
341
|
+
x, y, z = if args.length == 1 && args[0].is_a?(Hash)
|
342
|
+
args[0].values_at(:x, :y, :z)
|
343
|
+
elsif args.length.between?(1, 3)
|
344
|
+
args.values_at(0...3)
|
345
|
+
else
|
346
|
+
raise ArgumentError.new("Wrong number of arguments #{args.length} for 1-3")
|
347
|
+
end
|
348
|
+
|
349
|
+
self.affine!({
|
350
|
+
:afac => 1,
|
351
|
+
:bfac => 0,
|
352
|
+
:cfac => 0,
|
353
|
+
:dfac => 0,
|
354
|
+
:efac => 1,
|
355
|
+
:ffac => 0,
|
356
|
+
:gfac => 0,
|
357
|
+
:hfac => 0,
|
358
|
+
:ifac => 1,
|
359
|
+
:xoff => x || 0,
|
360
|
+
:yoff => y || 0,
|
361
|
+
:zoff => z || 1
|
362
|
+
})
|
363
|
+
end
|
364
|
+
|
365
|
+
def translate(*args)
|
366
|
+
self.dup.translate!(*args)
|
367
|
+
end
|
90
368
|
end
|
91
369
|
end
|
92
370
|
|
data/lib/geos/geometry.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
|
2
4
|
module Geos
|
3
5
|
# This is our base module that we use for some generic methods used all
|
@@ -60,7 +62,7 @@ module Geos
|
|
60
62
|
[]
|
61
63
|
end
|
62
64
|
|
63
|
-
ret = ''
|
65
|
+
ret = ''.dup
|
64
66
|
|
65
67
|
if options[:include_srid]
|
66
68
|
srid = if options[:srid]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
|
2
4
|
module Geos
|
3
5
|
class GeometryCollection
|
@@ -55,6 +57,56 @@ module Geos
|
|
55
57
|
}
|
56
58
|
end
|
57
59
|
alias_method :to_geojsonable, :as_geojson
|
60
|
+
|
61
|
+
# Dumps points similarly to the PostGIS `ST_DumpPoints` function.
|
62
|
+
def dump_points(cur_path = [])
|
63
|
+
self.each do |geom|
|
64
|
+
cur_path << geom.dump_points
|
65
|
+
end
|
66
|
+
cur_path
|
67
|
+
end
|
68
|
+
|
69
|
+
%w{ x y z }.each do |dimension|
|
70
|
+
%w{ max min }.each do |op|
|
71
|
+
self.class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
72
|
+
def #{dimension}_#{op}
|
73
|
+
unless self.empty?
|
74
|
+
self.collect(&:#{dimension}_#{op}).#{op}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
EOF
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
%w{
|
82
|
+
affine
|
83
|
+
rotate
|
84
|
+
rotate_x
|
85
|
+
rotate_y
|
86
|
+
rotate_z
|
87
|
+
scale
|
88
|
+
snap_to_grid
|
89
|
+
trans_scale
|
90
|
+
translate
|
91
|
+
}.each do |m|
|
92
|
+
self.class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
93
|
+
def #{m}!(*args)
|
94
|
+
unless self.empty?
|
95
|
+
self.num_geometries.times do |i|
|
96
|
+
self[i].#{m}!(*args)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
def #{m}(*args)
|
104
|
+
ret = self.dup.#{m}!(*args)
|
105
|
+
ret.srid = pick_srid_according_to_policy(self.srid)
|
106
|
+
ret
|
107
|
+
end
|
108
|
+
EOF
|
109
|
+
end
|
58
110
|
end
|
59
111
|
end
|
60
112
|
|