esri_shapefile 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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