esri_shapefile 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1eea7f296a0ef93cc09b8fe87fa30a3c01c67e61
4
- data.tar.gz: 5f2f82a3facd9330fde2125598c443c529103551
3
+ metadata.gz: fb1817abc87ffd5412b71bd0bb63bf45b2b139d2
4
+ data.tar.gz: 56eb64d557473ecb32f2f1b95597795ad8dd46b7
5
5
  SHA512:
6
- metadata.gz: a5e5a80ef2d2665e3f608229da92f49ae671d29dc74f2e9b222fb9eacb48f93eddcfd5b4edda8c4e9ff3328d013590fee16bc2bd2a09cf6b4dc0b5e8db308108
7
- data.tar.gz: 53354693c75d1f5f68c040462b343456d598eae0bbcd603373a1a0f20c3c6b2c29b89a9a8a8f1cfb29a4bbd1bbdb4823730cbd25c4cb413e393cc39a5d3a3848
6
+ metadata.gz: 0258bfab1a89bcde50fface153b299bb623a12e9494bcc093c3bda6ee70cbdbb6c66a357260cfce9c5abda4d3306551908d5e1efdf90c4d0fdb2f9c5f7e40a6b
7
+ data.tar.gz: 8348c2c65807999818dcfca9879f5baed08ef5f3e565970ee9690b987ba01c2f6649254a42a7d62945ff024d6b9b5f292da488fd4f7ff45708e137069a4f5ca1
@@ -2,6 +2,8 @@ require "esri_shapefile/version"
2
2
  require "esri_shapefile/byte_model"
3
3
  require "esri_shapefile/byte_model/field"
4
4
 
5
+ require "esri_shapefile/models/utils/ring"
6
+
5
7
  require "esri_shapefile/models/shapes/null"
6
8
  require "esri_shapefile/models/shapes/point"
7
9
  require "esri_shapefile/models/shapes/point_m"
@@ -22,8 +24,9 @@ require "esri_shapefile/models/main_file_header"
22
24
  require "esri_shapefile/models/record_header"
23
25
 
24
26
  require "esri_shapefile/reader"
27
+ require "esri_shapefile/converter/svg"
28
+ require "esri_shapefile/converter/svg/polygon"
25
29
 
26
30
  module EsriShapefile
27
- # Your code goes here...
28
31
  end
29
32
 
@@ -1,41 +1,55 @@
1
1
  module EsriShapefile
2
2
  module ByteModel
3
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)
4
+ attr_accessor :metadata
5
+
6
+ def self.included(model)
7
+ model.extend(ClassMethods)
7
8
  end
8
9
 
9
- def fields
10
- @fields ||= []
10
+ def self.extended(model)
11
+ error_message = "\nInvalid ByteModel usage: `extend EsriShapefile::ByteModel`\n"
12
+ error_message << "Please change the syntax to `include EsriShapefile::ByteModel'"
13
+ raise error_message
11
14
  end
12
15
 
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
16
+ module ClassMethods
17
+ def field(name, number: nil, position:, type:, byte_order:)
18
+ attr_accessor name unless name == :unused
19
+ fields << Field.new(name, position: position, type: type, byte_order: byte_order, number: number)
20
+ end
21
+
22
+ def fields
23
+ @fields ||= []
24
+ end
25
+
26
+ def from_bytes(bytes)
27
+ field_values = {}
28
+ fields.reduce(0) do |offset, field|
29
+ if !field.unused?
30
+ unpack_format = field.unpack_format(field_values)
31
+ field_value = bytes.unpack("@#{offset}#{unpack_format}")
32
+
33
+ if field.type == :point
34
+ field_value = field_value.each_slice(2).map do |x, y|
35
+ point = Shapes::Point.new
36
+ point.x = x
37
+ point.y = y
38
+ point
39
+ end
26
40
  end
41
+
42
+ field_values[field.name] = field.list? ? field_value : field_value.first
27
43
  end
28
44
 
29
- field_values[field.name] = field.list? ? field_value : field_value.first
45
+ offset += field.bytesize(field_values)
46
+ (offset < bytes.size) ? offset : break
30
47
  end
31
48
 
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)
49
+ field_values.reduce(self.new) do |model, (field, value)|
50
+ model.send("#{field}=", value)
38
51
  model
52
+ end
39
53
  end
40
54
  end
41
55
 
@@ -33,8 +33,16 @@ module EsriShapefile
33
33
  name == :unused
34
34
  end
35
35
 
36
- def bytesize
37
- TYPES[@type][:bytesize]
36
+ def bytesize(values = {})
37
+ size = TYPES[@type][:bytesize]
38
+
39
+ if number_depends_on_field?
40
+ multiplier = TYPES[@type][:unpack][:multiplier] || 1
41
+ number_of_consecutive_values = number_depends_on_field? ? values[number] : number
42
+ number_of_consecutive_values * multiplier * size
43
+ else
44
+ size
45
+ end
38
46
  end
39
47
 
40
48
  def unpack_format(values = {})
@@ -0,0 +1,56 @@
1
+ module EsriShapefile
2
+ module Converter
3
+ class Svg
4
+
5
+ attr_reader :shapefile_path
6
+
7
+ def initialize(shapefile_path)
8
+ @shapefile_path = shapefile_path
9
+ end
10
+
11
+ def call(output_filepath)
12
+ File.open(output_filepath, "w") do |output_file|
13
+ reader = EsriShapefile::Reader.new(shapefile_path)
14
+ output_file.write(open_svg_header(reader.main_file_header))
15
+
16
+ reader.each_record do |record_header, shape|
17
+ shape_converter = get_shape_converter(shape)
18
+ output_file.write(shape_converter.to_svg(shape))
19
+ end
20
+
21
+ output_file.write(close_svg_header)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def get_shape_converter(shape)
28
+ case
29
+ when Shapes::Polygon then Svg::Polygon
30
+ else raise "Shape not supported"
31
+ end
32
+ end
33
+
34
+ def open_svg_header(main_file_header)
35
+ header = '<!DOCTYPE html>'
36
+ header << '<html>'
37
+ header << '<body>'
38
+
39
+ height = main_file_header.y_max - main_file_header.y_min
40
+ width = main_file_header.x_max - main_file_header.x_min
41
+
42
+ header << "<svg "
43
+ header << " height=\"100%\""
44
+ header << " width=\"100%\""
45
+ header << " viewbox=\"#{main_file_header.x_min} #{-main_file_header.y_max} #{width} #{height}\" >"
46
+ header
47
+ end
48
+
49
+ def close_svg_header
50
+ '</svg></body></html>'
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,25 @@
1
+ module EsriShapefile
2
+ module Converter
3
+ class Svg::Polygon
4
+
5
+ def self.to_svg(polygon)
6
+ svg = '<g'
7
+ polygon.metadata.each do |key, value|
8
+ svg << " #{key}=\"#{value}\""
9
+ end
10
+ svg << '>'
11
+
12
+ polygon.rings.each do |ring|
13
+ svg << '<polygon points="'
14
+ ring.points.each do |ring|
15
+ svg << "#{ring.x},#{-ring.y} "
16
+ end
17
+ svg << '" />'
18
+ end
19
+
20
+ svg << "</g>"
21
+ svg
22
+ end
23
+ end
24
+ end
25
+ end
@@ -7,7 +7,7 @@ module EsriShapefile
7
7
  # with respect to the start of the file.
8
8
  #
9
9
  class MainFileHeader
10
- extend EsriShapefile::ByteModel
10
+ include EsriShapefile::ByteModel
11
11
 
12
12
  field :file_code, position: 0, type: :integer, byte_order: :big
13
13
  field :unused, position: 4, type: :integer, byte_order: :big
@@ -9,7 +9,7 @@ module EsriShapefile
9
9
  # record.
10
10
  #
11
11
  class RecordHeader
12
- extend EsriShapefile::ByteModel
12
+ include EsriShapefile::ByteModel
13
13
 
14
14
  # Record numbers begin at 1.
15
15
  field :record_number, position: 0, type: :integer, byte_order: :big
@@ -6,7 +6,7 @@ module EsriShapefile
6
6
  #
7
7
  #
8
8
  class MultiPatch
9
- extend EsriShapefile::ByteModel
9
+ include EsriShapefile::ByteModel
10
10
 
11
11
  field :shape_type, position: 0, type: :integer, byte_order: :little
12
12
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -6,7 +6,7 @@ module EsriShapefile
6
6
  # A MultiPoint represents a set of points.
7
7
  #
8
8
  class MultiPoint
9
- extend EsriShapefile::ByteModel
9
+ include EsriShapefile::ByteModel
10
10
 
11
11
  field :shape_type, position: 0, type: :integer, byte_order: :little
12
12
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -6,7 +6,7 @@ module EsriShapefile
6
6
  # A MultiPoint represents a set of points.
7
7
  #
8
8
  class MultiPointM
9
- extend EsriShapefile::ByteModel
9
+ include EsriShapefile::ByteModel
10
10
 
11
11
  field :shape_type, position: 0, type: :integer, byte_order: :little
12
12
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -6,7 +6,7 @@ module EsriShapefile
6
6
  # A MultiPoint represents a set of points.
7
7
  #
8
8
  class MultiPointZ
9
- extend EsriShapefile::ByteModel
9
+ include EsriShapefile::ByteModel
10
10
 
11
11
  field :shape_type, position: 0, type: :integer, byte_order: :little
12
12
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -10,7 +10,7 @@ module EsriShapefile
10
10
  # populated with geometric data soon after they are created.
11
11
  #
12
12
  class Null
13
- extend EsriShapefile::ByteModel
13
+ include EsriShapefile::ByteModel
14
14
 
15
15
  field :shape_type, position: 0, type: :integer, byte_order: :little
16
16
  end
@@ -7,12 +7,24 @@ module EsriShapefile
7
7
  # in the order X,Y.
8
8
  #
9
9
  class Point
10
- extend EsriShapefile::ByteModel
10
+ include EsriShapefile::ByteModel
11
11
 
12
12
  field :shape_type, position: 0, type: :integer, byte_order: :little
13
13
  field :x, position: 4, type: :double, byte_order: :little
14
14
  field :y, position: 12, type: :double, byte_order: :little
15
15
 
16
+ def self.at(x:, y:)
17
+ point = Point.new
18
+ point.x = x
19
+ point.y = y
20
+ point
21
+ end
22
+
23
+ def eql?(point)
24
+ point.is_a?(Point) && point.x == x && point.y == y
25
+ end
26
+ alias_method :==, :eql?
27
+
16
28
  end
17
29
  end
18
30
  end
@@ -7,7 +7,7 @@ module EsriShapefile
7
7
  # in the order X,Y,Z plus a measure.
8
8
  #
9
9
  class PointM
10
- extend EsriShapefile::ByteModel
10
+ include EsriShapefile::ByteModel
11
11
 
12
12
  field :shape_type, position: 0, type: :integer, byte_order: :little
13
13
  field :x, position: 4, type: :double, byte_order: :little
@@ -7,7 +7,7 @@ module EsriShapefile
7
7
  # in the order X,Y,Z plus a measure.
8
8
  #
9
9
  class PointZ
10
- extend EsriShapefile::ByteModel
10
+ include EsriShapefile::ByteModel
11
11
 
12
12
  field :shape_type, position: 0, type: :integer, byte_order: :little
13
13
  field :x, position: 4, type: :double, byte_order: :little
@@ -14,7 +14,7 @@ module EsriShapefile
14
14
  # allowed.
15
15
  #
16
16
  class PolyLine
17
- extend EsriShapefile::ByteModel
17
+ include EsriShapefile::ByteModel
18
18
 
19
19
  field :shape_type, position: 0, type: :integer, byte_order: :little
20
20
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -8,7 +8,7 @@ module EsriShapefile
8
8
  # Parts may or may not intersect one another.
9
9
  #
10
10
  class PolyLineM
11
- extend EsriShapefile::ByteModel
11
+ include EsriShapefile::ByteModel
12
12
 
13
13
  field :shape_type, position: 0, type: :integer, byte_order: :little
14
14
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -8,7 +8,7 @@ module EsriShapefile
8
8
  # Parts may or may not intersect one another.
9
9
  #
10
10
  class PolyLineZ
11
- extend EsriShapefile::ByteModel
11
+ include EsriShapefile::ByteModel
12
12
 
13
13
  field :shape_type, position: 0, type: :integer, byte_order: :little
14
14
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -21,7 +21,7 @@ module EsriShapefile
21
21
  # The Polygon structure is identical to the PolyLine structure.
22
22
  #
23
23
  class Polygon
24
- extend EsriShapefile::ByteModel
24
+ include EsriShapefile::ByteModel
25
25
 
26
26
  field :shape_type, position: 0, type: :integer, byte_order: :little
27
27
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -32,6 +32,15 @@ module EsriShapefile
32
32
  field :num_points, position: 40, type: :integer, byte_order: :little
33
33
  field :parts, position: 44, type: :integer, byte_order: :little, number: :num_parts
34
34
  field :points, position: :x, type: :point, byte_order: :little, number: :num_points
35
+
36
+ def rings
37
+ @rings ||= begin
38
+ ring_parts = (parts + [points.size])
39
+ ring_parts.each_cons(2).map do |ring_start_index, next_ring_index|
40
+ Ring.new(points[ring_start_index...next_ring_index])
41
+ end
42
+ end
43
+ end
35
44
  end
36
45
  end
37
46
  end
@@ -10,7 +10,7 @@ module EsriShapefile
10
10
  # The PolygonM structure is identical to the PolyLineM structure
11
11
  #
12
12
  class PolygonM
13
- extend EsriShapefile::ByteModel
13
+ include EsriShapefile::ByteModel
14
14
 
15
15
  field :shape_type, position: 0, type: :integer, byte_order: :little
16
16
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -10,7 +10,7 @@ module EsriShapefile
10
10
  # The PolygonZ structure is identical to the PolyLineZ structure
11
11
  #
12
12
  class PolygonZ
13
- extend EsriShapefile::ByteModel
13
+ include EsriShapefile::ByteModel
14
14
 
15
15
  field :shape_type, position: 0, type: :integer, byte_order: :little
16
16
  field :x_min, position: 4, type: :double, byte_order: :little
@@ -0,0 +1,38 @@
1
+ module EsriShapefile
2
+ class Ring
3
+ attr_reader :points, :direction
4
+
5
+ def initialize(points)
6
+ @points = points
7
+ @direction = determine_direction(points)
8
+ end
9
+
10
+ private
11
+
12
+ # Sum over the edges, (x2 − x1)(y2 + y1). If the result is positive the
13
+ # curve is clockwise, if it's negative the curve is counter-clockwise. (The
14
+ # result is twice the enclosed area, with a +/- convention.)
15
+ #
16
+ # point[0] = (5,0) edge[0]: (6-5)(4+0) = 4
17
+ # point[1] = (6,4) edge[1]: (4-6)(5+4) = -18
18
+ # point[2] = (4,5) edge[2]: (1-4)(5+5) = -30
19
+ # point[3] = (1,5) edge[3]: (1-1)(0+5) = 0
20
+ # point[4] = (1,0) edge[4]: (5-1)(0+0) = 0
21
+ # ---
22
+ # -44 counter-clockwise
23
+ def determine_direction(points)
24
+ sum_over_edges = points.
25
+ each_cons(2).
26
+ reduce(0) { |sum, (p1, p2)| sum += ((p2.x - p1.x) * (p2.y + p1.y)) }
27
+
28
+ sum_over_edges < 0 ? :count_clockwise : :clockwise
29
+ end
30
+
31
+ def eql?(ring)
32
+ ring.is_a?(Ring) && ring.points == @points && ring.direction == @direction
33
+ end
34
+ alias_method :==, :eql?
35
+
36
+ end
37
+ end
38
+
@@ -1,3 +1,6 @@
1
+ require 'pathname'
2
+ require 'dbf'
3
+
1
4
  module EsriShapefile
2
5
  class Reader
3
6
 
@@ -7,15 +10,19 @@ module EsriShapefile
7
10
  attr_reader :main_file_header
8
11
 
9
12
  def initialize(path_to_shapefile)
10
- @path_to_shapefile = path_to_shapefile
13
+ @path_to_shapefile = Pathname.new(path_to_shapefile)
14
+ @path_to_dbf = @path_to_shapefile.sub_ext(".dbf")
15
+
11
16
  @main_file_header = parse_main_file_header
12
17
  end
13
18
 
14
19
  def each_record
20
+ dbf = @path_to_dbf.file? ? DBF::Table.new(@path_to_dbf.to_s) : nil
21
+
15
22
  File.open(@path_to_shapefile) do |file|
16
23
  file.pos = MAIN_FILE_HEADER_BYTESIZE
17
24
 
18
- (0..Float::INFINITY).lazy.reduce(file.pos) do |current_offset, number|
25
+ (0..Float::INFINITY).lazy.reduce(file.pos) do |current_offset, _|
19
26
  break if current_offset >= main_file_header.file_length_bytes
20
27
 
21
28
  record_header_bytes = file.read(RECORD_HEADER_BYTESIZE)
@@ -23,7 +30,9 @@ module EsriShapefile
23
30
 
24
31
  shape_bytes = file.read(record_header.content_length_bytes)
25
32
  shape_class = Shapes.find_by_bytes(shape_bytes)
33
+
26
34
  shape = shape_class.from_bytes(shape_bytes)
35
+ shape.metadata = get_record_metadata(dbf, record_header.record_number)
27
36
 
28
37
  yield record_header, shape
29
38
 
@@ -34,6 +43,13 @@ module EsriShapefile
34
43
 
35
44
  private
36
45
 
46
+ # Retrieve the metadata for the shape from the associated .dbf file.
47
+ # Record numbers are one based, while the dbf file reader is 0 based.
48
+ # So we subtract one from the record number when performing the lookup.
49
+ def get_record_metadata(dbf, record_number)
50
+ dbf.nil? ? {} : dbf.find(record_number - 1).attributes
51
+ end
52
+
37
53
  def parse_main_file_header
38
54
  main_file_header_bytes = File.binread(@path_to_shapefile, 100, 0)
39
55
  MainFileHeader.from_bytes(main_file_header_bytes)
@@ -1,3 +1,3 @@
1
1
  module EsriShapefile
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -5,7 +5,7 @@ describe EsriShapefile::ByteModel do
5
5
  describe "declaring fields" do
6
6
  let(:example_model) do
7
7
  Class.new do
8
- extend EsriShapefile::ByteModel
8
+ include EsriShapefile::ByteModel
9
9
  field :foo, position: 0, type: :integer, byte_order: :little
10
10
  end
11
11
  end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'pry'
3
+
4
+ module EsriShapefile
5
+ module Shapes
6
+ describe Polygon do
7
+
8
+ let(:polygon) do
9
+ polygon = Shapes::Polygon.new
10
+ polygon.parts = [0,5]
11
+ polygon.points = [
12
+ Point.at(x: 200, y: 200),
13
+ Point.at(x: 250, y: 250),
14
+ Point.at(x: 300, y: 200),
15
+ Point.at(x: 250, y: 150),
16
+ Point.at(x: 200, y: 200),
17
+
18
+ Point.at(x: 100, y: 200),
19
+ Point.at(x: 250, y: 350),
20
+ Point.at(x: 400, y: 200),
21
+ Point.at(x: 250, y: 50),
22
+ Point.at(x: 100, y: 200),
23
+ ]
24
+ polygon
25
+ end
26
+
27
+ describe "#rings" do
28
+ it "foo" do
29
+ expect(polygon.rings).to eql([
30
+ Ring.new([
31
+ Point.at(x: 200, y: 200),
32
+ Point.at(x: 250, y: 250),
33
+ Point.at(x: 300, y: 200),
34
+ Point.at(x: 250, y: 150),
35
+ Point.at(x: 200, y: 200),
36
+ ]),
37
+ Ring.new([
38
+ Point.at(x: 100, y: 200),
39
+ Point.at(x: 250, y: 350),
40
+ Point.at(x: 400, y: 200),
41
+ Point.at(x: 250, y: 50),
42
+ Point.at(x: 100, y: 200),
43
+ ])
44
+ ])
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
data/spec/spec_helper.rb CHANGED
@@ -47,7 +47,7 @@ RSpec.configure do |config|
47
47
  # compatibility in RSpec 3). It causes shared context metadata to be
48
48
  # inherited by the metadata hash of host groups and examples, rather than
49
49
  # triggering implicit auto-inclusion in groups with matching metadata.
50
- config.shared_context_metadata_behavior = :apply_to_host_groups
50
+ # config.shared_context_metadata_behavior = :apply_to_host_groups
51
51
 
52
52
  # The settings below are suggested to provide a good initial experience
53
53
  # with RSpec, but feel free to customize to your heart's content.
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: esri_shapefile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Karayusuf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-28 00:00:00.000000000 Z
11
+ date: 2016-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dbf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  description: Library to read and write ESRI Shapefiles
56
84
  email:
57
85
  - jkarayusuf@gmail.com
@@ -65,6 +93,8 @@ files:
65
93
  - lib/esri_shapefile.rb
66
94
  - lib/esri_shapefile/byte_model.rb
67
95
  - lib/esri_shapefile/byte_model/field.rb
96
+ - lib/esri_shapefile/converter/svg.rb
97
+ - lib/esri_shapefile/converter/svg/polygon.rb
68
98
  - lib/esri_shapefile/models/main_file_header.rb
69
99
  - lib/esri_shapefile/models/record_header.rb
70
100
  - lib/esri_shapefile/models/shapes.rb
@@ -82,6 +112,7 @@ files:
82
112
  - lib/esri_shapefile/models/shapes/polygon.rb
83
113
  - lib/esri_shapefile/models/shapes/polygon_m.rb
84
114
  - lib/esri_shapefile/models/shapes/polygon_z.rb
115
+ - lib/esri_shapefile/models/utils/ring.rb
85
116
  - lib/esri_shapefile/reader.rb
86
117
  - lib/esri_shapefile/version.rb
87
118
  - spec/esri_shapefile/field_spec.rb
@@ -89,6 +120,7 @@ files:
89
120
  - spec/esri_shapefile/models/main_file_header_spec.rb
90
121
  - spec/esri_shapefile/models/record_header_spec.rb
91
122
  - spec/esri_shapefile/models/shapes/point_spec.rb
123
+ - spec/esri_shapefile/models/shapes/polygon_spec.rb
92
124
  - spec/spec_helper.rb
93
125
  homepage: ''
94
126
  licenses:
@@ -110,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
142
  version: '0'
111
143
  requirements: []
112
144
  rubyforge_project:
113
- rubygems_version: 2.2.0
145
+ rubygems_version: 2.2.2
114
146
  signing_key:
115
147
  specification_version: 4
116
148
  summary: Library to read and write ESRI Shapefiles
@@ -120,4 +152,5 @@ test_files:
120
152
  - spec/esri_shapefile/models/main_file_header_spec.rb
121
153
  - spec/esri_shapefile/models/record_header_spec.rb
122
154
  - spec/esri_shapefile/models/shapes/point_spec.rb
155
+ - spec/esri_shapefile/models/shapes/polygon_spec.rb
123
156
  - spec/spec_helper.rb