esri_shapefile 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +2 -0
- data/lib/esri_shapefile/byte_model/field.rb +48 -0
- data/lib/esri_shapefile/byte_model.rb +43 -0
- data/lib/esri_shapefile/models/main_file_header.rb +47 -0
- data/lib/esri_shapefile/models/record_header.rb +28 -0
- data/lib/esri_shapefile/models/shapes/multi_patch.rb +33 -0
- data/lib/esri_shapefile/models/shapes/multi_point.rb +21 -0
- data/lib/esri_shapefile/models/shapes/multi_point_m.rb +25 -0
- data/lib/esri_shapefile/models/shapes/multi_point_z.rb +29 -0
- data/lib/esri_shapefile/models/shapes/null.rb +19 -0
- data/lib/esri_shapefile/models/shapes/point.rb +19 -0
- data/lib/esri_shapefile/models/shapes/point_m.rb +20 -0
- data/lib/esri_shapefile/models/shapes/point_z.rb +21 -0
- data/lib/esri_shapefile/models/shapes/poly_line.rb +43 -0
- data/lib/esri_shapefile/models/shapes/poly_line_m.rb +50 -0
- data/lib/esri_shapefile/models/shapes/poly_line_z.rb +63 -0
- data/lib/esri_shapefile/models/shapes/polygon.rb +38 -0
- data/lib/esri_shapefile/models/shapes/polygon_m.rb +52 -0
- data/lib/esri_shapefile/models/shapes/polygon_z.rb +65 -0
- data/lib/esri_shapefile/models/shapes.rb +33 -0
- data/lib/esri_shapefile/reader.rb +44 -0
- data/lib/esri_shapefile/version.rb +3 -0
- data/lib/esri_shapefile.rb +29 -0
- data/spec/esri_shapefile/field_spec.rb +95 -0
- data/spec/esri_shapefile/model_spec.rb +26 -0
- data/spec/esri_shapefile/models/main_file_header_spec.rb +72 -0
- data/spec/esri_shapefile/models/record_header_spec.rb +26 -0
- data/spec/esri_shapefile/models/shapes/point_spec.rb +24 -0
- data/spec/spec_helper.rb +105 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1eea7f296a0ef93cc09b8fe87fa30a3c01c67e61
|
4
|
+
data.tar.gz: 5f2f82a3facd9330fde2125598c443c529103551
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5e5a80ef2d2665e3f608229da92f49ae671d29dc74f2e9b222fb9eacb48f93eddcfd5b4edda8c4e9ff3328d013590fee16bc2bd2a09cf6b4dc0b5e8db308108
|
7
|
+
data.tar.gz: 53354693c75d1f5f68c040462b343456d598eae0bbcd603373a1a0f20c3c6b2c29b89a9a8a8f1cfb29a4bbd1bbdb4823730cbd25c4cb413e393cc39a5d3a3848
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Joe Karayusuf
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# EsriShapefile
|
2
|
+
|
3
|
+
Ruby library to read an [ESRI Shapefile](https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'esri_shapefile'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install esri_shapefile
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Read the header of a shapefile
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'esri_shapefile'
|
27
|
+
reader = EsriShapefile::Reader.new("/path/to/shapefile")
|
28
|
+
reader.main_file_header # => Instance of EsriShapefile::MainFileHeader
|
29
|
+
```
|
30
|
+
|
31
|
+
### Read all of the records in a shapefile
|
32
|
+
|
33
|
+
Supported shapes can be found [here](lib/esri_shapefile/models/shapes)
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'esri_shapefile'
|
37
|
+
reader = EsriShapefile::Reader.new("path/to/shapefile")
|
38
|
+
reader.each_record do |header, shape|
|
39
|
+
# Iterate over each record with access to the header and shape.
|
40
|
+
# The header will be an instance of the EsriShapefile::RecordHeader class.
|
41
|
+
# The shape will be one of the shape models found in the models/shapes directory. Example: EsriShapefile::Shapes::Polygon
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it ( https://github.com/karayusuf/esri_shapefile/fork )
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module EsriShapefile
|
2
|
+
module ByteModel
|
3
|
+
class Field
|
4
|
+
attr_reader :name, :position, :type, :byte_order, :number
|
5
|
+
|
6
|
+
TYPES = {
|
7
|
+
integer: { bytesize: 4, unpack: { big: 'l>', little: 'l<' } },
|
8
|
+
double: { bytesize: 8, unpack: { big: 'G', little: 'E' } },
|
9
|
+
point: { bytesize: 16, unpack: { big: 'G', little: 'E', multiplier: 2 } },
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(name, position:, type:, byte_order:, number: nil)
|
13
|
+
@name = name
|
14
|
+
@position = position
|
15
|
+
@type = type
|
16
|
+
@number = number
|
17
|
+
@byte_order = byte_order
|
18
|
+
end
|
19
|
+
|
20
|
+
def list?
|
21
|
+
!@number.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def number
|
25
|
+
@number.nil? ? 1 : @number
|
26
|
+
end
|
27
|
+
|
28
|
+
def number_depends_on_field?
|
29
|
+
@number.is_a?(Symbol)
|
30
|
+
end
|
31
|
+
|
32
|
+
def unused?
|
33
|
+
name == :unused
|
34
|
+
end
|
35
|
+
|
36
|
+
def bytesize
|
37
|
+
TYPES[@type][:bytesize]
|
38
|
+
end
|
39
|
+
|
40
|
+
def unpack_format(values = {})
|
41
|
+
number_of_consecutive_values = number_depends_on_field? ? values[number] : number
|
42
|
+
multiplier = TYPES[@type][:unpack][:multiplier] || 1
|
43
|
+
unpack_format = TYPES[@type][:unpack][@byte_order]
|
44
|
+
"#{unpack_format}#{number_of_consecutive_values * multiplier}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module EsriShapefile
|
2
|
+
module ByteModel
|
3
|
+
|
4
|
+
def field(name, number: nil, position:, type:, byte_order:)
|
5
|
+
attr_accessor name unless name == :unused
|
6
|
+
fields << Field.new(name, position: position, type: type, byte_order: byte_order, number: number)
|
7
|
+
end
|
8
|
+
|
9
|
+
def fields
|
10
|
+
@fields ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def from_bytes(bytes)
|
14
|
+
field_values = {}
|
15
|
+
fields.reduce(0) do |offset, field|
|
16
|
+
if !field.unused?
|
17
|
+
unpack_format = field.unpack_format(field_values)
|
18
|
+
field_value = bytes.unpack("@#{offset}#{unpack_format}")
|
19
|
+
|
20
|
+
if field.type == :point
|
21
|
+
field_value = field_value.each_slice(2).map do |x, y|
|
22
|
+
point = Shapes::Point.new
|
23
|
+
point.x = x
|
24
|
+
point.y = y
|
25
|
+
point
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
field_values[field.name] = field.list? ? field_value : field_value.first
|
30
|
+
end
|
31
|
+
|
32
|
+
offset += field.bytesize
|
33
|
+
(offset < bytes.size) ? offset : break
|
34
|
+
end
|
35
|
+
|
36
|
+
field_values.reduce(self.new) do |model, (field, value)|
|
37
|
+
model.send("#{field}=", value)
|
38
|
+
model
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
#
|
5
|
+
# The main file header is 100 bytes long. The fields in the file header are
|
6
|
+
# listed below with their byte position, type, and byte order. Position is
|
7
|
+
# with respect to the start of the file.
|
8
|
+
#
|
9
|
+
class MainFileHeader
|
10
|
+
extend EsriShapefile::ByteModel
|
11
|
+
|
12
|
+
field :file_code, position: 0, type: :integer, byte_order: :big
|
13
|
+
field :unused, position: 4, type: :integer, byte_order: :big
|
14
|
+
field :unused, position: 8, type: :integer, byte_order: :big
|
15
|
+
field :unused, position: 12, type: :integer, byte_order: :big
|
16
|
+
field :unused, position: 16, type: :integer, byte_order: :big
|
17
|
+
field :unused, position: 20, type: :integer, byte_order: :big
|
18
|
+
|
19
|
+
field :file_length, position: 24, type: :integer, byte_order: :big
|
20
|
+
field :version, position: 28, type: :integer, byte_order: :little
|
21
|
+
field :shape_type, position: 32, type: :integer, byte_order: :little
|
22
|
+
|
23
|
+
field :x_min, position: 36, type: :double, byte_order: :little
|
24
|
+
field :y_min, position: 44, type: :double, byte_order: :little
|
25
|
+
field :x_max, position: 52, type: :double, byte_order: :little
|
26
|
+
field :y_max, position: 60, type: :double, byte_order: :little
|
27
|
+
|
28
|
+
field :z_min, position: 68, type: :double, byte_order: :little
|
29
|
+
field :z_max, position: 76, type: :double, byte_order: :little
|
30
|
+
field :m_min, position: 84, type: :double, byte_order: :little
|
31
|
+
field :m_max, position: 92, type: :double, byte_order: :little
|
32
|
+
|
33
|
+
# The value for file length is the total length of the file in 16-bit words
|
34
|
+
# (including the fifty 16-bit words that make up the header). This means
|
35
|
+
# that we need to multiply the value by 2 in order to know the size of the
|
36
|
+
# file in bytes
|
37
|
+
def file_length_bytes
|
38
|
+
file_length * 2
|
39
|
+
end
|
40
|
+
|
41
|
+
def shape
|
42
|
+
Shapes.from_type(shape_type)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
#
|
5
|
+
# The header for each record stores the record number and content length for
|
6
|
+
# the record. Record headers have a fixed length of 8 bytes. The list of
|
7
|
+
# fields shows the fields in the record header with their byte position, type,
|
8
|
+
# and byte order. The field position is with respect to the start of the
|
9
|
+
# record.
|
10
|
+
#
|
11
|
+
class RecordHeader
|
12
|
+
extend EsriShapefile::ByteModel
|
13
|
+
|
14
|
+
# Record numbers begin at 1.
|
15
|
+
field :record_number, position: 0, type: :integer, byte_order: :big
|
16
|
+
|
17
|
+
# The content length for a record is the length of the record contents
|
18
|
+
# section measured in 16-bit words. Each record, therefore, contributes (4 +
|
19
|
+
# content_length) 16-bit words toward the total length of the file, as
|
20
|
+
# stored as Byte 24 in the file header.
|
21
|
+
field :content_length, position: 4, type: :integer, byte_order: :big
|
22
|
+
|
23
|
+
def content_length_bytes
|
24
|
+
content_length * 2
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
#
|
7
|
+
#
|
8
|
+
class MultiPatch
|
9
|
+
extend EsriShapefile::ByteModel
|
10
|
+
|
11
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
12
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
13
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
14
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
15
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
16
|
+
|
17
|
+
field :num_parts, position: 36, type: :integer, byte_order: :little
|
18
|
+
field :num_points, position: 40, type: :integer, byte_order: :little
|
19
|
+
field :parts, position: 44, type: :integer, byte_order: :little, number: :num_parts
|
20
|
+
field :part_types, position: :w, type: :integer, byte_order: :little, number: :num_parts
|
21
|
+
field :points, position: :x, type: :point, byte_order: :little, number: :num_points
|
22
|
+
|
23
|
+
field :z_min, position: :x, type: :double, byte_order: :little
|
24
|
+
field :z_max, position: :x_plus_8, type: :double, byte_order: :little
|
25
|
+
field :z_array, position: :x_plus_16, type: :double, byte_order: :little, number: :num_points
|
26
|
+
|
27
|
+
field :m_min, position: :y, type: :double, byte_order: :little
|
28
|
+
field :m_max, position: :y_plus_8, type: :double, byte_order: :little
|
29
|
+
field :m_array, position: :y_plus_16, type: :double, byte_order: :little, number: :num_points
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A MultiPoint represents a set of points.
|
7
|
+
#
|
8
|
+
class MultiPoint
|
9
|
+
extend EsriShapefile::ByteModel
|
10
|
+
|
11
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
12
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
13
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
14
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
15
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
16
|
+
field :num_points, position: 36, type: :integer, byte_order: :little
|
17
|
+
field :points, position: 40, type: :point, byte_order: :little, number: :num_points
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A MultiPoint represents a set of points.
|
7
|
+
#
|
8
|
+
class MultiPointM
|
9
|
+
extend EsriShapefile::ByteModel
|
10
|
+
|
11
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
12
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
13
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
14
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
15
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
16
|
+
field :num_points, position: 36, type: :integer, byte_order: :little
|
17
|
+
field :points, position: 40, type: :point, byte_order: :little, number: :num_points
|
18
|
+
|
19
|
+
field :m_min, position: :x, type: :double, byte_order: :little
|
20
|
+
field :m_max, position: :x_plus_8, type: :double, byte_order: :little
|
21
|
+
field :m_array, position: :x_plus_16, type: :double, byte_order: :little, number: :num_points
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A MultiPoint represents a set of points.
|
7
|
+
#
|
8
|
+
class MultiPointZ
|
9
|
+
extend EsriShapefile::ByteModel
|
10
|
+
|
11
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
12
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
13
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
14
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
15
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
16
|
+
field :num_points, position: 36, type: :integer, byte_order: :little
|
17
|
+
field :points, position: 40, type: :point, byte_order: :little, number: :num_points
|
18
|
+
|
19
|
+
field :z_min, position: :x, type: :double, byte_order: :little
|
20
|
+
field :z_max, position: :x_plus_8, type: :double, byte_order: :little
|
21
|
+
field :z_array, position: :x_plus_16, type: :double, byte_order: :little, number: :num_points
|
22
|
+
|
23
|
+
field :m_min, position: :y, type: :double, byte_order: :little
|
24
|
+
field :m_max, position: :y_plus_8, type: :double, byte_order: :little
|
25
|
+
field :m_array, position: :y_plus_16, type: :double, byte_order: :little, number: :num_points
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A shape type of 0 indicates a null shape, with no geometric data for the
|
7
|
+
# shape. Each feature type (point, lie, polygon, etc.) supports nulls - it
|
8
|
+
# is valid to have points and null points in the same shapefile. Often null
|
9
|
+
# shapes are place holders; they are used during shapefile creation and are
|
10
|
+
# populated with geometric data soon after they are created.
|
11
|
+
#
|
12
|
+
class Null
|
13
|
+
extend EsriShapefile::ByteModel
|
14
|
+
|
15
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A point consists of a pair of double-precision coordinates
|
7
|
+
# in the order X,Y.
|
8
|
+
#
|
9
|
+
class Point
|
10
|
+
extend EsriShapefile::ByteModel
|
11
|
+
|
12
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
13
|
+
field :x, position: 4, type: :double, byte_order: :little
|
14
|
+
field :y, position: 12, type: :double, byte_order: :little
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A point consists of a pair of double-precision coordinates
|
7
|
+
# in the order X,Y,Z plus a measure.
|
8
|
+
#
|
9
|
+
class PointM
|
10
|
+
extend EsriShapefile::ByteModel
|
11
|
+
|
12
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
13
|
+
field :x, position: 4, type: :double, byte_order: :little
|
14
|
+
field :y, position: 12, type: :double, byte_order: :little
|
15
|
+
field :measure, position: 28, type: :double, byte_order: :little
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A point consists of a pair of double-precision coordinates
|
7
|
+
# in the order X,Y,Z plus a measure.
|
8
|
+
#
|
9
|
+
class PointZ
|
10
|
+
extend EsriShapefile::ByteModel
|
11
|
+
|
12
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
13
|
+
field :x, position: 4, type: :double, byte_order: :little
|
14
|
+
field :y, position: 12, type: :double, byte_order: :little
|
15
|
+
field :z, position: 20, type: :double, byte_order: :little
|
16
|
+
field :measure, position: 28, type: :double, byte_order: :little
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A PolyLine is an ordered set of vertices that consists of one or more
|
7
|
+
# parts. A part is a connected sequence of two or more points. Parts may or
|
8
|
+
# may not be connected to one another. Parts may or may not intersect one
|
9
|
+
# another.
|
10
|
+
#
|
11
|
+
# Because this specification does not forbid consecutive points with
|
12
|
+
# identical coordinates, shapefile readers must handle such cases. On the
|
13
|
+
# other hand, the degenerate, zero length parts that might result are not
|
14
|
+
# allowed.
|
15
|
+
#
|
16
|
+
class PolyLine
|
17
|
+
extend EsriShapefile::ByteModel
|
18
|
+
|
19
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
20
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
21
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
22
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
23
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
24
|
+
|
25
|
+
# The number of parts in the PolyLine
|
26
|
+
field :num_parts, position: 36, type: :integer, byte_order: :little
|
27
|
+
|
28
|
+
# The total number of points for all parts.
|
29
|
+
field :num_points, position: 40, type: :integer, byte_order: :little
|
30
|
+
|
31
|
+
# An array of length num_parts. Stores, for each PolyLine, the index of
|
32
|
+
# its first point in the points array. Array indexes are with respect to 0.
|
33
|
+
field :parts, position: 44, type: :integer, byte_order: :little, number: :num_parts
|
34
|
+
|
35
|
+
# An array of length NumPoints. The points for each part in the PolyLine
|
36
|
+
# are stored end to end. The points for Part 2 follow the points for
|
37
|
+
# Part 1, and so on. The parts array holds the array index of the starting
|
38
|
+
# point for each part. There is no delimiter in the points array between parts.
|
39
|
+
field :points, position: :x, type: :point, byte_order: :little, number: :num_points
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A PolyLineM consists of one or more parts. A part is a connected sequence
|
7
|
+
# of two or more points. Parts may or may not be connected to one another.
|
8
|
+
# Parts may or may not intersect one another.
|
9
|
+
#
|
10
|
+
class PolyLineM
|
11
|
+
extend EsriShapefile::ByteModel
|
12
|
+
|
13
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
14
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
15
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
16
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
17
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
18
|
+
|
19
|
+
# The number of parts in the PolyLine
|
20
|
+
field :num_parts, position: 36, type: :integer, byte_order: :little
|
21
|
+
|
22
|
+
# The total number of points for all parts.
|
23
|
+
field :num_points, position: 40, type: :integer, byte_order: :little
|
24
|
+
|
25
|
+
# An array of length num_parts. Stores, for each PolyLine, the index of
|
26
|
+
# its first point in the points array. Array indexes are with respect to 0.
|
27
|
+
field :parts, position: 44, type: :integer, byte_order: :little, number: :num_parts
|
28
|
+
|
29
|
+
# An array of length NumPoints. The points for each part in the PolyLine
|
30
|
+
# are stored end to end. The points for Part 2 follow the points for
|
31
|
+
# Part 1, and so on. The parts array holds the array index of the starting
|
32
|
+
# point for each part. There is no delimiter in the points array between parts.
|
33
|
+
field :points, position: :x, type: :point, byte_order: :little, number: :num_points
|
34
|
+
|
35
|
+
# The minimum measure for the PolyLineZ
|
36
|
+
field :m_min, position: :z, type: :double, byte_order: :little
|
37
|
+
|
38
|
+
# The maximum measure for the PolyLineZ
|
39
|
+
field :m_max, position: :z_plus_8, type: :double, byte_order: :little
|
40
|
+
|
41
|
+
# An array of length num_points. The measures for each part in the
|
42
|
+
# PolyLineZ are stored end to end. The measures for Part 2 follow the
|
43
|
+
# measures for Part 1, and so on. The parts array holds the array index of
|
44
|
+
# the starting measure for each part. There is no delimited in the measure
|
45
|
+
# array between parts.
|
46
|
+
field :m_array, position: :z_plus_16, type: :double, byte_order: :little, number: :num_points
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A PolyLineZ consists of one or more parts. A part is a connected sequence
|
7
|
+
# of two or more points. Parts may or may not be connected to one another.
|
8
|
+
# Parts may or may not intersect one another.
|
9
|
+
#
|
10
|
+
class PolyLineZ
|
11
|
+
extend EsriShapefile::ByteModel
|
12
|
+
|
13
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
14
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
15
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
16
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
17
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
18
|
+
|
19
|
+
# The number of parts in the PolyLine
|
20
|
+
field :num_parts, position: 36, type: :integer, byte_order: :little
|
21
|
+
|
22
|
+
# The total number of points for all parts.
|
23
|
+
field :num_points, position: 40, type: :integer, byte_order: :little
|
24
|
+
|
25
|
+
# An array of length num_parts. Stores, for each PolyLine, the index of
|
26
|
+
# its first point in the points array. Array indexes are with respect to 0.
|
27
|
+
field :parts, position: 44, type: :integer, byte_order: :little, number: :num_parts
|
28
|
+
|
29
|
+
# An array of length NumPoints. The points for each part in the PolyLine
|
30
|
+
# are stored end to end. The points for Part 2 follow the points for
|
31
|
+
# Part 1, and so on. The parts array holds the array index of the starting
|
32
|
+
# point for each part. There is no delimiter in the points array between parts.
|
33
|
+
field :points, position: :x, type: :point, byte_order: :little, number: :num_points
|
34
|
+
|
35
|
+
# The minimum Z value for the PolyLineZ
|
36
|
+
field :z_min, position: :y, type: :double, byte_order: :little
|
37
|
+
|
38
|
+
# The maximum Z value for the PoliyLineZ
|
39
|
+
field :z_max, position: :y_plus_8, type: :double, byte_order: :little
|
40
|
+
|
41
|
+
# An array of length num_points. the Z values for each part in the
|
42
|
+
# PolyLineZ are stored end to end. The Z values for Part 2 follow the Z
|
43
|
+
# values for Part 1, and so on. The parts array holds the array index of
|
44
|
+
# the starting point for each part. There is no delimited in the Z array
|
45
|
+
# between parts.
|
46
|
+
field :z_array, position: :y_plus_16, type: :double, byte_order: :little, number: :num_points
|
47
|
+
|
48
|
+
# The minimum measure for the PolyLineZ
|
49
|
+
field :m_min, position: :z, type: :double, byte_order: :little
|
50
|
+
|
51
|
+
# The maximum measure for the PolyLineZ
|
52
|
+
field :m_max, position: :z_plus_8, type: :double, byte_order: :little
|
53
|
+
|
54
|
+
# An array of length num_points. The measures for each part in the
|
55
|
+
# PolyLineZ are stored end to end. The measures for Part 2 follow the
|
56
|
+
# measures for Part 1, and so on. The parts array holds the array index of
|
57
|
+
# the starting measure for each part. There is no delimited in the measure
|
58
|
+
# array between parts.
|
59
|
+
field :m_array, position: :z_plus_16, type: :double, byte_order: :little, number: :num_points
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'esri_shapefile/byte_model'
|
2
|
+
|
3
|
+
module EsriShapefile
|
4
|
+
module Shapes
|
5
|
+
#
|
6
|
+
# A polygon consists of one or more rings. A ring is a connected sequence of
|
7
|
+
# four or more points that form a closed, non-self-intersecting loop. A
|
8
|
+
# polygon may contain multiple outer rings. The order of vertices or
|
9
|
+
# orientation for a ring indicates which side of the ring is the interior of
|
10
|
+
# the polygon. The neighborhood to the right of an observer walking along
|
11
|
+
# the ring in vertex order is the neighborhood inside the polygon. Vertices
|
12
|
+
# of rings defining holes in polygons are in counterclockwise direction.
|
13
|
+
# Vertices for a single, ringed polygon are, therefore, always in clockwise
|
14
|
+
# order. The rings of a polygon are referred to as its parts.
|
15
|
+
#
|
16
|
+
# Because this specification does not forbid consecutive points with
|
17
|
+
# identical coordinates, shapefile readers must handle such cases. On the
|
18
|
+
# other hand, the degenerate, zero length or zero area parts that might
|
19
|
+
# result are not allowed.
|
20
|
+
#
|
21
|
+
# The Polygon structure is identical to the PolyLine structure.
|
22
|
+
#
|
23
|
+
class Polygon
|
24
|
+
extend EsriShapefile::ByteModel
|
25
|
+
|
26
|
+
field :shape_type, position: 0, type: :integer, byte_order: :little
|
27
|
+
field :x_min, position: 4, type: :double, byte_order: :little
|
28
|
+
field :y_min, position: 12, type: :double, byte_order: :little
|
29
|
+
field :x_max, position: 20, type: :double, byte_order: :little
|
30
|
+
field :y_max, position: 28, type: :double, byte_order: :little
|
31
|
+
field :num_parts, position: 36, type: :integer, byte_order: :little
|
32
|
+
field :num_points, position: 40, type: :integer, byte_order: :little
|
33
|
+
field :parts, position: 44, type: :integer, byte_order: :little, number: :num_parts
|
34
|
+
field :points, position: :x, type: :point, byte_order: :little, number: :num_points
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|