rgeo-shapefile 0.3.0 → 0.4.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/README.md +10 -16
- data/lib/rgeo-shapefile.rb +1 -1
- data/lib/rgeo/shapefile.rb +3 -9
- data/lib/rgeo/shapefile/reader.rb +80 -127
- data/lib/rgeo/shapefile/version.rb +1 -5
- data/test/basic_test.rb +5 -18
- data/test/shapelib_cases_test.rb +446 -466
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5a5aafda1242e8363bb7fa480767f84af18ed6f
|
4
|
+
data.tar.gz: 5e2a04bf415526a1614b01a3484f892b350ff72b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88cd189943f7d41623ac032b652dde5b5c228def9673887d8cba97ee005a418f8c3c85546a6e0a6cb18649fd183f097477fe7eba6616d036c25e0f56e2476f04
|
7
|
+
data.tar.gz: 99d24dfa29fb82cfb0ea8672c240c0ab47c01a649a3bee5217e20fec28e2dcc4c4028e889a22c8b24fec60376a56f5652061b611a04e8c39d224b0937f576c94
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](http://badge.fury.io/rb/rgeo-shapefile)
|
4
4
|
[](https://travis-ci.org/rgeo/rgeo-shapefile)
|
5
5
|
|
6
|
-
`RGeo::Shapefile` is an optional module for [RGeo](
|
6
|
+
`RGeo::Shapefile` is an optional module for [RGeo](https://github.com/rgeo/rgeo)
|
7
7
|
for reading geospatial data from ESRI shapefiles.
|
8
8
|
|
9
9
|
## Summary
|
@@ -13,7 +13,7 @@ Ruby programming language. At its core is an implementation of the
|
|
13
13
|
industry standard OGC Simple Features Specification, which provides data
|
14
14
|
representations of geometric objects such as points, lines, and polygons,
|
15
15
|
along with a set of geometric analysis operations. See the README for the
|
16
|
-
|
16
|
+
`rgeo` gem for more information.
|
17
17
|
|
18
18
|
`RGeo::Shapefile` is an optional RGeo add-on module for reading geospatial
|
19
19
|
data from ESRI shapefiles. The shapefile format is a common file format
|
@@ -42,9 +42,9 @@ end
|
|
42
42
|
|
43
43
|
`RGeo::Shapefile` has the following requirements:
|
44
44
|
|
45
|
-
* Ruby
|
45
|
+
* Ruby 2.0.0 or later
|
46
46
|
* rgeo 0.3.13 or later.
|
47
|
-
* dbf
|
47
|
+
* dbf 3.0 or later.
|
48
48
|
|
49
49
|
Include in your bundle:
|
50
50
|
|
@@ -55,7 +55,6 @@ gem 'rgeo-shapefile'
|
|
55
55
|
Install `RGeo::Shapefile` as a gem:
|
56
56
|
|
57
57
|
```sh
|
58
|
-
gem install rgeo
|
59
58
|
gem install rgeo-shapefile
|
60
59
|
```
|
61
60
|
|
@@ -63,24 +62,21 @@ See the README for the "rgeo" gem, a required dependency, for further installati
|
|
63
62
|
|
64
63
|
If you are using Ruby 1.8, use version `0.2.x` of this gem.
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
* Improve test case coverage.
|
69
|
-
* Support for writing shapefiles.
|
65
|
+
If you are using Ruby 1.9, use version `0.3.x` of this gem.
|
70
66
|
|
71
67
|
## Development and support
|
72
68
|
|
73
69
|
Documentation is available at http://rdoc.info/gems/rgeo-shapefile
|
74
70
|
|
75
|
-
Source code is hosted on Github at
|
71
|
+
Source code is hosted on Github at https://github.com/rgeo/rgeo-shapefile
|
76
72
|
|
77
73
|
Contributions are welcome. Fork the project on Github.
|
78
74
|
|
79
|
-
Report bugs on Github issues at
|
75
|
+
Report bugs on Github issues at https://github.com/rgeo/rgeo-shapefile/issues
|
80
76
|
|
81
77
|
## Acknowledgments
|
82
78
|
|
83
|
-
|
79
|
+
`rgeo-shapefile` was orginally written by Daniel Azuma (http://www.daniel-azuma.com).
|
84
80
|
|
85
81
|
Development is supported by:
|
86
82
|
|
@@ -90,10 +86,8 @@ Development is supported by:
|
|
90
86
|
Although we don't use shapelib (http://shapelib.maptools.org) to read
|
91
87
|
ESRI shapefiles, we did borrow a bunch of their test cases.
|
92
88
|
|
93
|
-
|
94
|
-
|
95
|
-
Copyright 2014 Daniel Azuma
|
89
|
+
## License
|
96
90
|
|
97
|
-
Copyright
|
91
|
+
Copyright Daniel Azuma, Tee Parham
|
98
92
|
|
99
93
|
https://github.com/rgeo/rgeo-shapefile/blob/master/LICENSE.txt
|
data/lib/rgeo-shapefile.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "rgeo/shapefile"
|
data/lib/rgeo/shapefile.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require "rgeo"
|
3
2
|
|
4
3
|
# RGeo is a spatial data library for Ruby, provided by the "rgeo" gem.
|
5
4
|
#
|
@@ -7,8 +6,6 @@ require 'rgeo'
|
|
7
6
|
# ESRI shapefiles.
|
8
7
|
|
9
8
|
module RGeo
|
10
|
-
|
11
|
-
|
12
9
|
# This module contains an implementation of ESRI Shapefiles.
|
13
10
|
# Use the Shapefile::Reader class to read a shapefile, extracting
|
14
11
|
# geometry and attribute data from it.
|
@@ -16,11 +13,8 @@ module RGeo
|
|
16
13
|
|
17
14
|
module Shapefile
|
18
15
|
end
|
19
|
-
|
20
|
-
|
21
16
|
end
|
22
17
|
|
23
|
-
|
24
18
|
# Implementation files
|
25
|
-
require
|
26
|
-
require
|
19
|
+
require "rgeo/shapefile/version"
|
20
|
+
require "rgeo/shapefile/reader"
|
@@ -1,11 +1,7 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require "dbf"
|
3
2
|
|
4
3
|
module RGeo
|
5
|
-
|
6
4
|
module Shapefile
|
7
|
-
|
8
|
-
|
9
5
|
# Represents a shapefile that is open for reading.
|
10
6
|
#
|
11
7
|
# You can use this object to read a shapefile straight through,
|
@@ -94,13 +90,10 @@ module RGeo
|
|
94
90
|
# a GeometryCollection instead of a MultiPolygon.
|
95
91
|
|
96
92
|
class Reader
|
97
|
-
|
98
|
-
|
99
93
|
# Values less than this value are considered "no value" in the
|
100
94
|
# shapefile format specification.
|
101
95
|
NODATA_LIMIT = -1e38
|
102
96
|
|
103
|
-
|
104
97
|
# Create a new shapefile reader. You must pass the path for the
|
105
98
|
# main shapefile (e.g. "path/to/file.shp"). You may also omit the
|
106
99
|
# ".shp" extension from the path. All three files that make up the
|
@@ -115,6 +108,7 @@ module RGeo
|
|
115
108
|
#
|
116
109
|
# If you provide a block, the shapefile reader will be yielded to
|
117
110
|
# the block, and automatically closed at the end of the block.
|
111
|
+
# In this instance, File.open returns the value of the block.
|
118
112
|
# If you do not provide a block, the shapefile reader will be
|
119
113
|
# returned from this call. It is then the caller's responsibility
|
120
114
|
# to close the reader when it is done.
|
@@ -161,7 +155,7 @@ module RGeo
|
|
161
155
|
# a platform without GEOS, you have no choice but to turn on this
|
162
156
|
# switch and make this assumption about your input shapefiles.
|
163
157
|
|
164
|
-
def self.open(path_, opts_={}, &block_)
|
158
|
+
def self.open(path_, opts_ = {}, &block_)
|
165
159
|
file_ = new(path_, opts_)
|
166
160
|
if block_
|
167
161
|
begin
|
@@ -169,31 +163,27 @@ module RGeo
|
|
169
163
|
ensure
|
170
164
|
file_.close
|
171
165
|
end
|
172
|
-
nil
|
173
166
|
else
|
174
167
|
file_
|
175
168
|
end
|
176
169
|
end
|
177
170
|
|
178
|
-
|
179
171
|
# Low-level creation of a Reader. The arguments are the same as
|
180
172
|
# those passed to Reader::open, except that this doesn't take a
|
181
173
|
# block. You should use Reader::open instead.
|
182
174
|
|
183
|
-
def initialize(path_, opts_={})
|
184
|
-
path_ = path_.sub(/\.shp$/,
|
175
|
+
def initialize(path_, opts_ = {}) # :nodoc:
|
176
|
+
path_ = path_.sub(/\.shp$/, "")
|
185
177
|
@base_path = path_
|
186
178
|
@opened = true
|
187
|
-
@main_file = ::File.open(path_+
|
188
|
-
@index_file = ::File.open(path_+
|
189
|
-
if ::File.file?(path_+
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
@main_length, @shape_type_code, @xmin, @ymin, @xmax, @ymax, @zmin, @zmax, @mmin, @mmax = @main_file.read(100).unpack('x24Nx4VE8')
|
179
|
+
@main_file = ::File.open(path_ + ".shp", "rb:ascii-8bit")
|
180
|
+
@index_file = ::File.open(path_ + ".shx", "rb:ascii-8bit")
|
181
|
+
@attr_dbf = if ::File.file?(path_ + ".dbf") && ::File.readable?(path_ + ".dbf")
|
182
|
+
::DBF::Table.new(path_ + ".dbf")
|
183
|
+
end
|
184
|
+
@main_length, @shape_type_code, @xmin, @ymin, @xmax, @ymax, @zmin, @zmax, @mmin, @mmax = @main_file.read(100).unpack("x24Nx4VE8")
|
195
185
|
@main_length *= 2
|
196
|
-
index_length_ = @index_file.read(100).unpack(
|
186
|
+
index_length_ = @index_file.read(100).unpack("x24Nx72").first
|
197
187
|
@num_records = (index_length_ - 50) / 4
|
198
188
|
@cur_record_index = 0
|
199
189
|
|
@@ -216,7 +206,7 @@ module RGeo
|
|
216
206
|
end
|
217
207
|
|
218
208
|
@factory = opts_[:factory_generator] || opts_[:factory] || Cartesian.method(:preferred_factory)
|
219
|
-
unless @factory.
|
209
|
+
unless @factory.is_a?(Feature::Factory::Instance)
|
220
210
|
factory_config_ = {}
|
221
211
|
factory_config_[:srid] = opts_[:srid] if opts_[:srid]
|
222
212
|
unless @zmin.nil?
|
@@ -233,21 +223,18 @@ module RGeo
|
|
233
223
|
@assume_inner_follows_outer = opts_[:assume_inner_follows_outer]
|
234
224
|
end
|
235
225
|
|
236
|
-
|
237
226
|
# Close the shapefile.
|
238
227
|
# You should not use this Reader after it has been closed.
|
239
228
|
# Most methods will return nil.
|
240
229
|
|
241
230
|
def close
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
end
|
231
|
+
return unless @opened
|
232
|
+
@main_file.close
|
233
|
+
@index_file.close
|
234
|
+
@attr_dbf.close if @attr_dbf
|
235
|
+
@opened = false
|
248
236
|
end
|
249
237
|
|
250
|
-
|
251
238
|
# Returns true if this Reader is still open, or false if it has
|
252
239
|
# been closed.
|
253
240
|
|
@@ -255,7 +242,6 @@ module RGeo
|
|
255
242
|
@opened
|
256
243
|
end
|
257
244
|
|
258
|
-
|
259
245
|
# Returns true if attributes are available. This may be false
|
260
246
|
# because there is no ".dbf" file or because the dbf gem is not
|
261
247
|
# available.
|
@@ -264,21 +250,18 @@ module RGeo
|
|
264
250
|
@opened ? (@attr_dbf ? true : false) : nil
|
265
251
|
end
|
266
252
|
|
267
|
-
|
268
253
|
# Returns the factory used by this reader.
|
269
254
|
|
270
255
|
def factory
|
271
256
|
@opened ? @factory : nil
|
272
257
|
end
|
273
258
|
|
274
|
-
|
275
259
|
# Returns the number of records in the shapefile.
|
276
260
|
|
277
261
|
def num_records
|
278
262
|
@opened ? @num_records : nil
|
279
263
|
end
|
280
|
-
|
281
|
-
|
264
|
+
alias size num_records
|
282
265
|
|
283
266
|
# Returns the shape type code.
|
284
267
|
|
@@ -286,63 +269,54 @@ module RGeo
|
|
286
269
|
@opened ? @shape_type_code : nil
|
287
270
|
end
|
288
271
|
|
289
|
-
|
290
272
|
# Returns the minimum x.
|
291
273
|
|
292
274
|
def xmin
|
293
275
|
@opened ? @xmin : nil
|
294
276
|
end
|
295
277
|
|
296
|
-
|
297
278
|
# Returns the maximum x.
|
298
279
|
|
299
280
|
def xmax
|
300
281
|
@opened ? @xmax : nil
|
301
282
|
end
|
302
283
|
|
303
|
-
|
304
284
|
# Returns the minimum y.
|
305
285
|
|
306
286
|
def ymin
|
307
287
|
@opened ? @ymin : nil
|
308
288
|
end
|
309
289
|
|
310
|
-
|
311
290
|
# Returns the maximum y.
|
312
291
|
|
313
292
|
def ymax
|
314
293
|
@opened ? @ymax : nil
|
315
294
|
end
|
316
295
|
|
317
|
-
|
318
296
|
# Returns the minimum z, or nil if the shapefile does not contain z.
|
319
297
|
|
320
298
|
def zmin
|
321
299
|
@opened ? @zmin : nil
|
322
300
|
end
|
323
301
|
|
324
|
-
|
325
302
|
# Returns the maximum z, or nil if the shapefile does not contain z.
|
326
303
|
|
327
304
|
def zmax
|
328
305
|
@opened ? @zmax : nil
|
329
306
|
end
|
330
307
|
|
331
|
-
|
332
308
|
# Returns the minimum m, or nil if the shapefile does not contain m.
|
333
309
|
|
334
310
|
def mmin
|
335
311
|
@opened ? @mmin : nil
|
336
312
|
end
|
337
313
|
|
338
|
-
|
339
314
|
# Returns the maximum m, or nil if the shapefile does not contain m.
|
340
315
|
|
341
316
|
def mmax
|
342
317
|
@opened ? @mmax : nil
|
343
318
|
end
|
344
319
|
|
345
|
-
|
346
320
|
# Returns the current file pointer as a record index (0-based).
|
347
321
|
# This is the record number that will be read when Reader#next
|
348
322
|
# is called.
|
@@ -351,32 +325,28 @@ module RGeo
|
|
351
325
|
@opened ? @cur_record_index : nil
|
352
326
|
end
|
353
327
|
|
354
|
-
|
355
328
|
# Read and return the next record as a Reader::Record.
|
356
329
|
|
357
330
|
def next
|
358
331
|
@opened && @cur_record_index < @num_records ? _read_next_record : nil
|
359
332
|
end
|
360
333
|
|
361
|
-
|
362
334
|
# Read the remaining records starting with the current record index,
|
363
335
|
# and yield the Reader::Record for each one.
|
364
336
|
|
365
337
|
def each
|
366
|
-
|
367
|
-
|
368
|
-
end if @opened
|
338
|
+
return unless @opened
|
339
|
+
yield _read_next_record while @cur_record_index < @num_records
|
369
340
|
end
|
370
341
|
|
371
|
-
|
372
342
|
# Seek to the given record index.
|
373
343
|
|
374
344
|
def seek_index(index_)
|
375
345
|
if @opened && index_ >= 0 && index_ <= @num_records
|
376
346
|
if index_ < @num_records && index_ != @cur_record_index
|
377
|
-
@index_file.seek(100+8*index_)
|
378
|
-
offset_ = @index_file.read(4).unpack(
|
379
|
-
@main_file.seek(offset_*2)
|
347
|
+
@index_file.seek(100 + 8 * index_)
|
348
|
+
offset_ = @index_file.read(4).unpack("N").first
|
349
|
+
@main_file.seek(offset_ * 2)
|
380
350
|
end
|
381
351
|
@cur_record_index = index_
|
382
352
|
true
|
@@ -385,7 +355,6 @@ module RGeo
|
|
385
355
|
end
|
386
356
|
end
|
387
357
|
|
388
|
-
|
389
358
|
# Rewind to the beginning of the file.
|
390
359
|
# Equivalent to seek_index(0).
|
391
360
|
|
@@ -393,20 +362,18 @@ module RGeo
|
|
393
362
|
seek_index(0)
|
394
363
|
end
|
395
364
|
|
396
|
-
|
397
365
|
# Get the given record number. Equivalent to seeking to that index
|
398
366
|
# and calling next.
|
399
367
|
|
400
368
|
def get(index_)
|
401
369
|
seek_index(index_) ? self.next : nil
|
402
370
|
end
|
403
|
-
|
404
|
-
|
371
|
+
alias [] get
|
405
372
|
|
406
|
-
def _read_next_record
|
407
|
-
length_ = @main_file.read(8).unpack(
|
373
|
+
def _read_next_record # :nodoc:
|
374
|
+
length_ = @main_file.read(8).unpack("NN")[1]
|
408
375
|
data_ = @main_file.read(length_ * 2)
|
409
|
-
shape_type_ = data_[0,4].unpack(
|
376
|
+
shape_type_ = data_[0, 4].unpack("V").first
|
410
377
|
geometry_ =
|
411
378
|
case shape_type_
|
412
379
|
when 1 then _read_point(data_)
|
@@ -422,7 +389,6 @@ module RGeo
|
|
422
389
|
when 25 then _read_polygon(data_, :m)
|
423
390
|
when 28 then _read_multipoint(data_, :m)
|
424
391
|
when 31 then _read_multipatch(data_)
|
425
|
-
else nil
|
426
392
|
end
|
427
393
|
attrs_ = {}
|
428
394
|
if @attr_dbf
|
@@ -437,17 +403,16 @@ module RGeo
|
|
437
403
|
result_
|
438
404
|
end
|
439
405
|
|
440
|
-
|
441
|
-
def _read_point(data_, opt_=nil) # :nodoc:
|
406
|
+
def _read_point(data_, opt_ = nil) # :nodoc:
|
442
407
|
case opt_
|
443
408
|
when :z
|
444
|
-
x_, y_, z_, m_ = data_[4,32].unpack(
|
409
|
+
x_, y_, z_, m_ = data_[4, 32].unpack("EEEE")
|
445
410
|
m_ = 0 if m_.nil? || m_ < NODATA_LIMIT
|
446
411
|
when :m
|
447
|
-
x_, y_, m_ = data_[4,24].unpack(
|
412
|
+
x_, y_, m_ = data_[4, 24].unpack("EEE")
|
448
413
|
z_ = 0
|
449
414
|
else
|
450
|
-
x_, y_ = data_[4,16].unpack(
|
415
|
+
x_, y_ = data_[4, 16].unpack("EE")
|
451
416
|
z_ = m_ = 0
|
452
417
|
end
|
453
418
|
extras_ = []
|
@@ -456,19 +421,18 @@ module RGeo
|
|
456
421
|
@factory.point(x_, y_, *extras_)
|
457
422
|
end
|
458
423
|
|
459
|
-
|
460
|
-
def _read_multipoint(data_, opt_=nil) # :nodoc:
|
424
|
+
def _read_multipoint(data_, opt_ = nil) # :nodoc:
|
461
425
|
# Read number of points
|
462
|
-
num_points_ = data_[36,4].unpack(
|
426
|
+
num_points_ = data_[36, 4].unpack("V").first
|
463
427
|
|
464
428
|
# Read remaining data
|
465
|
-
size_ = num_points_*16
|
466
|
-
size_ += 16 + num_points_*8 if opt_
|
467
|
-
size_ += 16 + num_points_*8 if opt_ == :z
|
468
|
-
values_ = data_[40, size_].unpack(
|
429
|
+
size_ = num_points_ * 16
|
430
|
+
size_ += 16 + num_points_ * 8 if opt_
|
431
|
+
size_ += 16 + num_points_ * 8 if opt_ == :z
|
432
|
+
values_ = data_[40, size_].unpack("E*")
|
469
433
|
|
470
434
|
# Extract XY, Z, and M values
|
471
|
-
xys_ = values_.slice!(0, num_points_*2)
|
435
|
+
xys_ = values_.slice!(0, num_points_ * 2)
|
472
436
|
ms_ = nil
|
473
437
|
zs_ = nil
|
474
438
|
if opt_
|
@@ -476,38 +440,37 @@ module RGeo
|
|
476
440
|
if opt_ == :z
|
477
441
|
zs_ = ms_
|
478
442
|
ms_ = values_.slice!(4, num_points_)
|
479
|
-
ms_.map!{ |val_| val_ < NODATA_LIMIT ? 0 : val_ } if ms_
|
443
|
+
ms_.map! { |val_| val_ < NODATA_LIMIT ? 0 : val_ } if ms_
|
480
444
|
end
|
481
445
|
end
|
482
446
|
|
483
447
|
# Generate points
|
484
|
-
points_ = (0..num_points_-1).map do |i_|
|
448
|
+
points_ = (0..num_points_ - 1).map do |i_|
|
485
449
|
extras_ = []
|
486
450
|
extras_ << zs_[i_] if zs_ && @factory_supports_z
|
487
451
|
extras_ << ms_[i_] if ms_ && @factory_supports_m
|
488
|
-
@factory.point(xys_[i_*2], xys_[i_*2+1], *extras_)
|
452
|
+
@factory.point(xys_[i_ * 2], xys_[i_ * 2 + 1], *extras_)
|
489
453
|
end
|
490
454
|
|
491
455
|
# Return a MultiPoint
|
492
456
|
@factory.multi_point(points_)
|
493
457
|
end
|
494
458
|
|
495
|
-
|
496
|
-
def _read_polyline(data_, opt_=nil) # :nodoc:
|
459
|
+
def _read_polyline(data_, opt_ = nil) # :nodoc:
|
497
460
|
# Read counts
|
498
|
-
num_parts_, num_points_ = data_[36,8].unpack(
|
461
|
+
num_parts_, num_points_ = data_[36, 8].unpack("VV")
|
499
462
|
|
500
463
|
# Read remaining data
|
501
|
-
size_ = num_parts_*4 + num_points_*16
|
502
|
-
size_ += 16 + num_points_*8 if opt_
|
503
|
-
size_ += 16 + num_points_*8 if opt_ == :z
|
464
|
+
size_ = num_parts_ * 4 + num_points_ * 16
|
465
|
+
size_ += 16 + num_points_ * 8 if opt_
|
466
|
+
size_ += 16 + num_points_ * 8 if opt_ == :z
|
504
467
|
values_ = data_[44, size_].unpack("V#{num_parts_}E*")
|
505
468
|
|
506
469
|
# Parts array
|
507
470
|
part_indexes_ = values_.slice!(0, num_parts_) + [num_points_]
|
508
471
|
|
509
472
|
# Extract XY, Z, and M values
|
510
|
-
xys_ = values_.slice!(0, num_points_*2)
|
473
|
+
xys_ = values_.slice!(0, num_points_ * 2)
|
511
474
|
ms_ = nil
|
512
475
|
zs_ = nil
|
513
476
|
if opt_
|
@@ -515,43 +478,42 @@ module RGeo
|
|
515
478
|
if opt_ == :z
|
516
479
|
zs_ = ms_
|
517
480
|
ms_ = values_.slice!(4, num_points_)
|
518
|
-
ms_.map!{ |val_| val_ < NODATA_LIMIT ? 0 : val_ }
|
481
|
+
ms_.map! { |val_| val_ < NODATA_LIMIT ? 0 : val_ }
|
519
482
|
end
|
520
483
|
end
|
521
484
|
|
522
485
|
# Generate points
|
523
|
-
points_ = (0..num_points_-1).map do |i_|
|
486
|
+
points_ = (0..num_points_ - 1).map do |i_|
|
524
487
|
extras_ = []
|
525
488
|
extras_ << zs_[i_] if zs_ && @factory_supports_z
|
526
489
|
extras_ << ms_[i_] if ms_ && @factory_supports_m
|
527
|
-
@factory.point(xys_[i_*2], xys_[i_*2+1], *extras_)
|
490
|
+
@factory.point(xys_[i_ * 2], xys_[i_ * 2 + 1], *extras_)
|
528
491
|
end
|
529
492
|
|
530
493
|
# Generate LineString objects (parts)
|
531
|
-
parts_ = (0..num_parts_-1).map do |i_|
|
532
|
-
@factory.line_string(points_[part_indexes_[i_]...part_indexes_[i_+1]])
|
494
|
+
parts_ = (0..num_parts_ - 1).map do |i_|
|
495
|
+
@factory.line_string(points_[part_indexes_[i_]...part_indexes_[i_ + 1]])
|
533
496
|
end
|
534
497
|
|
535
498
|
# Generate MultiLineString
|
536
499
|
@factory.multi_line_string(parts_)
|
537
500
|
end
|
538
501
|
|
539
|
-
|
540
|
-
def _read_polygon(data_, opt_=nil) # :nodoc:
|
502
|
+
def _read_polygon(data_, opt_ = nil) # :nodoc:
|
541
503
|
# Read counts
|
542
|
-
num_parts_, num_points_ = data_[36,8].unpack(
|
504
|
+
num_parts_, num_points_ = data_[36, 8].unpack("VV")
|
543
505
|
|
544
506
|
# Read remaining data
|
545
|
-
size_ = num_parts_*4 + num_points_*16
|
546
|
-
size_ += 16 + num_points_*8 if opt_
|
547
|
-
size_ += 16 + num_points_*8 if opt_ == :z
|
507
|
+
size_ = num_parts_ * 4 + num_points_ * 16
|
508
|
+
size_ += 16 + num_points_ * 8 if opt_
|
509
|
+
size_ += 16 + num_points_ * 8 if opt_ == :z
|
548
510
|
values_ = data_[44, size_].unpack("V#{num_parts_}E*")
|
549
511
|
|
550
512
|
# Parts array
|
551
513
|
part_indexes_ = values_.slice!(0, num_parts_) + [num_points_]
|
552
514
|
|
553
515
|
# Extract XY, Z, and M values
|
554
|
-
xys_ = values_.slice!(0, num_points_*2)
|
516
|
+
xys_ = values_.slice!(0, num_points_ * 2)
|
555
517
|
ms_ = nil
|
556
518
|
zs_ = nil
|
557
519
|
if opt_
|
@@ -559,22 +521,22 @@ module RGeo
|
|
559
521
|
if opt_ == :z
|
560
522
|
zs_ = ms_
|
561
523
|
ms_ = values_.slice!(4, num_points_)
|
562
|
-
ms_.map!{ |val_| val_ < NODATA_LIMIT ? 0 : val_ } if ms_
|
524
|
+
ms_.map! { |val_| val_ < NODATA_LIMIT ? 0 : val_ } if ms_
|
563
525
|
end
|
564
526
|
end
|
565
527
|
|
566
528
|
# Generate points
|
567
|
-
points_ = (0..num_points_-1).map do |i_|
|
529
|
+
points_ = (0..num_points_ - 1).map do |i_|
|
568
530
|
extras_ = []
|
569
531
|
extras_ << zs_[i_] if zs_ && @factory_supports_z
|
570
532
|
extras_ << ms_[i_] if ms_ && @factory_supports_m
|
571
|
-
@factory.point(xys_[i_*2], xys_[i_*2+1], *extras_)
|
572
|
-
end
|
533
|
+
@factory.point(xys_[i_ * 2], xys_[i_ * 2 + 1], *extras_)
|
534
|
+
end.compact
|
573
535
|
|
574
536
|
# The parts are LinearRing objects
|
575
|
-
parts_ = (0..num_parts_-1).map do |i_|
|
576
|
-
@factory.linear_ring(points_[part_indexes_[i_]...part_indexes_[i_+1]])
|
577
|
-
end
|
537
|
+
parts_ = (0..num_parts_ - 1).map do |i_|
|
538
|
+
@factory.linear_ring(points_[part_indexes_[i_]...part_indexes_[i_ + 1]])
|
539
|
+
end.compact
|
578
540
|
|
579
541
|
# Get a GEOS factory if needed.
|
580
542
|
geos_factory_ = nil
|
@@ -670,7 +632,7 @@ module RGeo
|
|
670
632
|
# Generate the actual polygons from the collected polygon data
|
671
633
|
polygons_.map! do |poly_data_|
|
672
634
|
outer_ = poly_data_[0][0]
|
673
|
-
inner_ = poly_data_[1..-1].map{ |part_data_| part_data_[0] }
|
635
|
+
inner_ = poly_data_[1..-1].map { |part_data_| part_data_[0] }
|
674
636
|
@factory.polygon(outer_, inner_)
|
675
637
|
end
|
676
638
|
|
@@ -678,36 +640,35 @@ module RGeo
|
|
678
640
|
@factory.multi_polygon(polygons_)
|
679
641
|
end
|
680
642
|
|
681
|
-
|
682
|
-
def _read_multipatch(data_) # :nodoc:
|
643
|
+
def _read_multipatch(data_) # :nodoc:
|
683
644
|
# Read counts
|
684
|
-
num_parts_, num_points_ = data_[36,8].unpack(
|
645
|
+
num_parts_, num_points_ = data_[36, 8].unpack("VV")
|
685
646
|
|
686
647
|
# Read remaining data
|
687
|
-
values_ = data_[44, 32 + num_parts_*8 + num_points_*32].unpack("V#{num_parts_*2}E*")
|
648
|
+
values_ = data_[44, 32 + num_parts_ * 8 + num_points_ * 32].unpack("V#{num_parts_ * 2}E*")
|
688
649
|
|
689
650
|
# Parts arrays
|
690
651
|
part_indexes_ = values_.slice!(0, num_parts_) + [num_points_]
|
691
652
|
part_types_ = values_.slice!(0, num_parts_)
|
692
653
|
|
693
654
|
# Extract XY, Z, and M values
|
694
|
-
xys_ = values_.slice!(0, num_points_*2)
|
655
|
+
xys_ = values_.slice!(0, num_points_ * 2)
|
695
656
|
zs_ = values_.slice!(2, num_points_)
|
696
|
-
zs_.map!{ |val_| val_ < NODATA_LIMIT ? 0 : val_ } if zs_
|
657
|
+
zs_.map! { |val_| val_ < NODATA_LIMIT ? 0 : val_ } if zs_
|
697
658
|
ms_ = values_.slice!(4, num_points_)
|
698
|
-
ms_.map!{ |val_| val_ < NODATA_LIMIT ? 0 : val_ } if ms_
|
659
|
+
ms_.map! { |val_| val_ < NODATA_LIMIT ? 0 : val_ } if ms_
|
699
660
|
|
700
661
|
# Generate points
|
701
|
-
points_ = (0..num_points_-1).map do |i_|
|
662
|
+
points_ = (0..num_points_ - 1).map do |i_|
|
702
663
|
extras_ = []
|
703
664
|
extras_ << zs_[i_] if zs_ && @factory_supports_z
|
704
665
|
extras_ << ms_[i_] if ms_ && @factory_supports_m
|
705
|
-
@factory.point(xys_[i_*2], xys_[i_*2+1], *extras_)
|
666
|
+
@factory.point(xys_[i_ * 2], xys_[i_ * 2 + 1], *extras_)
|
706
667
|
end
|
707
668
|
|
708
669
|
# Create the parts
|
709
|
-
parts_ = (0..num_parts_-1).map do |i_|
|
710
|
-
ps_ = points_[part_indexes_[i_]...part_indexes_[i_+1]]
|
670
|
+
parts_ = (0..num_parts_ - 1).map do |i_|
|
671
|
+
ps_ = points_[part_indexes_[i_]...part_indexes_[i_ + 1]]
|
711
672
|
# All part types just translate directly into rings, except for
|
712
673
|
# triangle fan, which requires that we reorder the vertices.
|
713
674
|
if part_types_[i_] == 0
|
@@ -779,7 +740,7 @@ module RGeo
|
|
779
740
|
# the first ring is the outer one. Otherwise, we have to
|
780
741
|
# use GEOS to determine containment.
|
781
742
|
unless @assume_inner_follows_outer
|
782
|
-
geos_polygons_ = sequence_.map{ |ring_| geos_factory_.polygon(ring_) }
|
743
|
+
geos_polygons_ = sequence_.map { |ring_| geos_factory_.polygon(ring_) }
|
783
744
|
outer_poly_ = nil
|
784
745
|
outer_index_ = 0
|
785
746
|
geos_polygons_.each_with_index do |poly_, idx_|
|
@@ -787,7 +748,7 @@ module RGeo
|
|
787
748
|
if poly_.contains?(outer_poly_)
|
788
749
|
outer_poly_ = poly_
|
789
750
|
outer_index_ = idx_
|
790
|
-
break
|
751
|
+
break
|
791
752
|
end
|
792
753
|
else
|
793
754
|
outer_poly_ = poly_
|
@@ -822,7 +783,6 @@ module RGeo
|
|
822
783
|
@factory.collection(polygons_)
|
823
784
|
end
|
824
785
|
|
825
|
-
|
826
786
|
# Shapefile records are provided to the caller as objects of this
|
827
787
|
# type. The record includes the record index (0-based), the
|
828
788
|
# geometry (which may be nil if the shape type is the null type),
|
@@ -831,8 +791,7 @@ module RGeo
|
|
831
791
|
# You should not need to create objects of this type yourself.
|
832
792
|
|
833
793
|
class Record
|
834
|
-
|
835
|
-
def initialize(index_, geometry_, attributes_) # :nodoc:
|
794
|
+
def initialize(index_, geometry_, attributes_) # :nodoc:
|
836
795
|
@index = index_
|
837
796
|
@geometry = geometry_
|
838
797
|
@attributes = attributes_
|
@@ -856,13 +815,7 @@ module RGeo
|
|
856
815
|
def [](key_)
|
857
816
|
@attributes[key_.to_s]
|
858
817
|
end
|
859
|
-
|
860
818
|
end
|
861
|
-
|
862
|
-
|
863
819
|
end
|
864
|
-
|
865
|
-
|
866
820
|
end
|
867
|
-
|
868
821
|
end
|