rgeo-shapefile 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/rgeo-shapefile.svg)](http://badge.fury.io/rb/rgeo-shapefile)
|
4
4
|
[![Build Status](https://travis-ci.org/rgeo/rgeo-shapefile.svg?branch=master)](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
|