esri_shapefile 0.0.1

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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +51 -0
  4. data/Rakefile +2 -0
  5. data/lib/esri_shapefile/byte_model/field.rb +48 -0
  6. data/lib/esri_shapefile/byte_model.rb +43 -0
  7. data/lib/esri_shapefile/models/main_file_header.rb +47 -0
  8. data/lib/esri_shapefile/models/record_header.rb +28 -0
  9. data/lib/esri_shapefile/models/shapes/multi_patch.rb +33 -0
  10. data/lib/esri_shapefile/models/shapes/multi_point.rb +21 -0
  11. data/lib/esri_shapefile/models/shapes/multi_point_m.rb +25 -0
  12. data/lib/esri_shapefile/models/shapes/multi_point_z.rb +29 -0
  13. data/lib/esri_shapefile/models/shapes/null.rb +19 -0
  14. data/lib/esri_shapefile/models/shapes/point.rb +19 -0
  15. data/lib/esri_shapefile/models/shapes/point_m.rb +20 -0
  16. data/lib/esri_shapefile/models/shapes/point_z.rb +21 -0
  17. data/lib/esri_shapefile/models/shapes/poly_line.rb +43 -0
  18. data/lib/esri_shapefile/models/shapes/poly_line_m.rb +50 -0
  19. data/lib/esri_shapefile/models/shapes/poly_line_z.rb +63 -0
  20. data/lib/esri_shapefile/models/shapes/polygon.rb +38 -0
  21. data/lib/esri_shapefile/models/shapes/polygon_m.rb +52 -0
  22. data/lib/esri_shapefile/models/shapes/polygon_z.rb +65 -0
  23. data/lib/esri_shapefile/models/shapes.rb +33 -0
  24. data/lib/esri_shapefile/reader.rb +44 -0
  25. data/lib/esri_shapefile/version.rb +3 -0
  26. data/lib/esri_shapefile.rb +29 -0
  27. data/spec/esri_shapefile/field_spec.rb +95 -0
  28. data/spec/esri_shapefile/model_spec.rb +26 -0
  29. data/spec/esri_shapefile/models/main_file_header_spec.rb +72 -0
  30. data/spec/esri_shapefile/models/record_header_spec.rb +26 -0
  31. data/spec/esri_shapefile/models/shapes/point_spec.rb +24 -0
  32. data/spec/spec_helper.rb +105 -0
  33. 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,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -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
+