shapely 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.
- data/lib/shapefile.rb +66 -0
- data/lib/shapefile/shape.rb +38 -0
- data/lib/shapefile/shape/multi_patch.rb +3 -0
- data/lib/shapefile/shape/multi_point.rb +11 -0
- data/lib/shapefile/shape/null.rb +3 -0
- data/lib/shapefile/shape/point.rb +32 -0
- data/lib/shapefile/shape/poly_line.rb +11 -0
- data/lib/shapefile/shape/polygon.rb +11 -0
- data/lib/shapely.rb +1 -0
- metadata +82 -0
data/lib/shapefile.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "dbf"
|
2
|
+
|
3
|
+
class Shapefile
|
4
|
+
HEADER_BYTES = 100
|
5
|
+
|
6
|
+
attr_reader :shape_class
|
7
|
+
|
8
|
+
def initialize(shp, shx = nil, dbf = nil)
|
9
|
+
# Open files.
|
10
|
+
@shp = File.open(shp)
|
11
|
+
@dbf = DBF::Table.new(dbf) if dbf
|
12
|
+
# Read and verify the header.
|
13
|
+
hdr = @shp.read(HEADER_BYTES).unpack("NNNNNNNVVEEEEEEEE")
|
14
|
+
unless hdr[0] == 9994
|
15
|
+
raise RuntimeError, "#{shp} isn't a shapefile"
|
16
|
+
end
|
17
|
+
unless hdr[7] == 1000
|
18
|
+
raise RuntimeError, "#{shp} isn't a supported version of shapefile"
|
19
|
+
end
|
20
|
+
unless @shape_class = Shape.class_for_code(hdr[8])
|
21
|
+
raise RuntimeError, "#{shp} is composed of an unsupported shape type"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.open(shp, shx = nil, dbf = nil)
|
26
|
+
new(shp, shx, dbf)
|
27
|
+
end
|
28
|
+
|
29
|
+
def shapes
|
30
|
+
result = []
|
31
|
+
each_shape {|shape| result << shape}
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
def each_shape(&block)
|
36
|
+
@shp.seek(HEADER_BYTES, IO::SEEK_SET)
|
37
|
+
until @shp.eof?
|
38
|
+
# Read the next shape record.
|
39
|
+
nbr, len, shp_type = @shp.read(12).unpack("NNV")
|
40
|
+
record = @shp.read(len * 2 - 4)
|
41
|
+
next if shp_type == Shape::Null.code
|
42
|
+
shape = @shape_class.new(nbr, record)
|
43
|
+
# Load the shape's attributes. DBF's record method is ridiculously slow
|
44
|
+
# (it rereads every single row each time you call it), so we cheat a bit
|
45
|
+
# and use some of its private methods.
|
46
|
+
if @dbf
|
47
|
+
@dbf.send(:seek_to_record, nbr - 1)
|
48
|
+
unless @dbf.send(:deleted_record?)
|
49
|
+
shape.attributes = DBF::Record.new(@dbf).attributes
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# Run the shape through the block.
|
53
|
+
block.call(shape)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def attribute_names
|
58
|
+
if @dbf
|
59
|
+
@dbf.columns.collect {|c| c.name.downcase}
|
60
|
+
else
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
require "shapefile/shape"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Shapefile::Shape
|
2
|
+
attr_reader :id
|
3
|
+
attr_accessor :attributes
|
4
|
+
|
5
|
+
def initialize(id, raw_record) # :nodoc:
|
6
|
+
@id = id
|
7
|
+
self.attributes = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.enumerate_subclass_codes # :nodoc:
|
11
|
+
@codes_classes = {}
|
12
|
+
constants.each do |const|
|
13
|
+
subclass = eval("Shapefile::Shape::#{const}") rescue next
|
14
|
+
@codes_classes[subclass.code] = subclass
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.code
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.class_for_code(code)
|
23
|
+
@codes_classes[code]
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
attributes[key]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require "shapefile/shape/multi_patch.rb"
|
32
|
+
require "shapefile/shape/multi_point.rb"
|
33
|
+
require "shapefile/shape/null.rb"
|
34
|
+
require "shapefile/shape/point.rb"
|
35
|
+
require "shapefile/shape/poly_line.rb"
|
36
|
+
require "shapefile/shape/polygon.rb"
|
37
|
+
|
38
|
+
Shapefile::Shape.enumerate_subclass_codes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Shapefile::Shape::MultiPoint < Shapefile::Shape
|
2
|
+
def self.code; 8 end
|
3
|
+
end
|
4
|
+
|
5
|
+
class Shapefile::Shape::MultiPointM < Shapefile::Shape::MultiPoint
|
6
|
+
def self.code; 28 end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Shapefile::Shape::MultiPointZ < Shapefile::Shape::MultiPointM
|
10
|
+
def self.code; 18 end
|
11
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Shapefile::Shape::Point < Shapefile::Shape
|
2
|
+
attr_reader :x, :y
|
3
|
+
|
4
|
+
def self.code; 1 end
|
5
|
+
|
6
|
+
def initialize(nbr, record)
|
7
|
+
super
|
8
|
+
@x, @y = record.unpack("EE")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Shapefile::Shape::PointM < Shapefile::Shape::Point
|
13
|
+
attr_reader :m
|
14
|
+
|
15
|
+
def self.code; 21 end
|
16
|
+
|
17
|
+
def initialize(nbr, record)
|
18
|
+
super
|
19
|
+
@m = record[16, 8].unpack("E")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Shapefile::Shape::PointZ < Shapefile::Shape::PointM
|
24
|
+
attr_reader :z
|
25
|
+
|
26
|
+
def self.code; 11 end
|
27
|
+
|
28
|
+
def initialize(nbr, record)
|
29
|
+
super
|
30
|
+
@z, @m = record[16, 16].unpack("EE")
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Shapefile::Shape::PolyLine < Shapefile::Shape
|
2
|
+
def self.code; 3 end
|
3
|
+
end
|
4
|
+
|
5
|
+
class Shapefile::Shape::PolyLineM < Shapefile::Shape::PolyLine
|
6
|
+
def self.code; 23 end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Shapefile::Shape::PolyLineZ < Shapefile::Shape::PolyLineM
|
10
|
+
def self.code; 13 end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Shapefile::Shape::Polygon < Shapefile::Shape
|
2
|
+
def self.code; 5 end
|
3
|
+
end
|
4
|
+
|
5
|
+
class Shapefile::Shape::PolygonM < Shapefile::Shape::Polygon
|
6
|
+
def self.code; 25 end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Shapefile::Shape::PolygonZ < Shapefile::Shape::PolygonM
|
10
|
+
def self.code; 15 end
|
11
|
+
end
|
data/lib/shapely.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "shapefile"
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shapely
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
version: "0.1"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Dana Contreras
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2010-03-27 00:00:00 -04:00
|
17
|
+
default_executable:
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: dbf
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
segments:
|
27
|
+
- 1
|
28
|
+
- 0
|
29
|
+
- 0
|
30
|
+
version: 1.0.0
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
description:
|
34
|
+
email:
|
35
|
+
executables: []
|
36
|
+
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
files:
|
42
|
+
- lib/shapely.rb
|
43
|
+
- lib/shapefile.rb
|
44
|
+
- lib/shapefile/shape.rb
|
45
|
+
- lib/shapefile/shape/multi_patch.rb
|
46
|
+
- lib/shapefile/shape/multi_point.rb
|
47
|
+
- lib/shapefile/shape/null.rb
|
48
|
+
- lib/shapefile/shape/point.rb
|
49
|
+
- lib/shapefile/shape/poly_line.rb
|
50
|
+
- lib/shapefile/shape/polygon.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/DanaDanger/shapely
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.3.6
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: A gem for reading ESRI Shapefiles.
|
81
|
+
test_files: []
|
82
|
+
|