shapelib 0.7.0

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/shapelib.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'shapelib_ext'
2
+ require 'shapelib/shape'
@@ -0,0 +1,14 @@
1
+ module Shapelib
2
+ class Shape
3
+ def each
4
+ latlngs.each do |l|
5
+ yield l
6
+ end
7
+ end
8
+
9
+ def latlngs
10
+ @latlngs ||= yvals.zip(xvals)
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,3 @@
1
+ module Shapelib
2
+ VERSION = "0.7.0"
3
+ end
data/test/libtest.rb ADDED
@@ -0,0 +1,80 @@
1
+ class AssertFail < Exception
2
+ end
3
+
4
+ def assert(a, b)
5
+ caller = ""
6
+ begin
7
+ raise "no problem"
8
+ rescue RuntimeError => e
9
+ caller = e.backtrace[1]
10
+ end
11
+ if (b === a) then
12
+ val = b.inspect
13
+ val = "#{val}..." if val.size > 40
14
+ print "ok #{caller}: #{val}\n" if $VERBOSE
15
+ else
16
+ val = a.inspect
17
+ val = "#{val}..." if val.size > 200
18
+ raise AssertFail, val
19
+ end
20
+ end
21
+
22
+ def file_delete(*args)
23
+ for file in args
24
+ next unless File.exist?(file)
25
+ File.delete(file)
26
+ end
27
+ end
28
+
29
+ def fold_line(line)
30
+ buf = ""
31
+ while line
32
+ head = line[0..63]
33
+ buf << (head + "\n")
34
+ line = line[64..-1]
35
+ end
36
+ buf
37
+ end
38
+
39
+ def assert_file(filename, pat)
40
+ f = File.read(filename)
41
+ r = [pat.gsub(/\s+/, "")].pack('H*')
42
+
43
+ if (r === f) then
44
+ print "ok <#{filename}>\n" if $VERBOSE
45
+ else
46
+ for i in 0...(f.size)
47
+ next if (f[i] == r[i])
48
+ printf "ofs=%08x file=%02x expected=%02x\n", i, f[i], r[i]
49
+ break
50
+ end
51
+ print "#{filename} is longer than expected\n" if f.size > r.size
52
+ h = f.unpack('H*').first
53
+ File.open("#{filename}.hex", "w") { |fp| fp.write(fold_line(h)) }
54
+ print "hex dump of <#{filename}> is saved to <#{filename}.hex>.\n"
55
+ raise AssertFail
56
+ end
57
+ end
58
+
59
+ def testblock(title)
60
+ begin
61
+ yield
62
+ rescue Exception => e
63
+ print "#{title} failed: #{e.message} (#{e.class.to_s})\n"
64
+ print "| ", e.backtrace[1..-1].join("\n| "), "\n"
65
+ return 1
66
+ else
67
+ print "#{title} ok\n"
68
+ return 0
69
+ end
70
+ end
71
+
72
+ def tainttest(msg)
73
+ begin
74
+ yield
75
+ rescue SecurityError => e
76
+ assert(e.message, msg)
77
+ else
78
+ raise SecurityError, "<#{msg}> doesn't come" if $SAFE > 0
79
+ end
80
+ end
data/test/zsample1.rb ADDED
@@ -0,0 +1,168 @@
1
+ require 'shapelib'
2
+
3
+ class Sample1
4
+ include ShapeLib
5
+
6
+ def initialize
7
+ end
8
+
9
+ def layer1
10
+ fp = ShapeFile.new('ts1stn.shp', :Point)
11
+ fp.add_field 'name', :String, 24
12
+ fp.add_field 'wdir', :String, 6 # 4
13
+ fp.add_field 'wspd', :Integer, 6 # 2
14
+ fp.add_field 'weather', :String, 16
15
+ fp.add_field 'pres', :Integer, 6 # 4
16
+ fp.add_field 'temp', :Integer, 6 # 3
17
+ fp.write new_point(124.17, 24.33,
18
+ 'name' => 'Ishigakijima', 'wdir' => 'S', 'wspd' => 3,
19
+ 'weather' => 'shower', 'pres' => 1014, 'temp' => 24)
20
+ csv = <<EOF
21
+ 127:41.1, 26:12.4, Naha, S, 4, partly cloudy, 1015, 21
22
+ 131.23, 25.83, Minamidaito Jima, SSW, 2, partly cloudy, 1017, 20
23
+ 129:29.7, 28:22.7, Naze, SW, 2, partly cloudy, 1017, 20
24
+ 130.72, 31.80, Kagoshima, WSW, 1, shower, 1013, 18
25
+ 128:49.6, 32:41.6, Fukue, NNE, 3, cloudy, 1014, 11
26
+ 129:17.5, 34:11.8, Izuhara, NNW, 2, cloudy, 1016, 10
27
+ 133:00.6, 32:43.3, Ashizuri Misaki, W, 2, cloudy, 1011, 17
28
+ 134:10.6, 33:15.1, Muroto Misaki, NNE, 3, fog, 1012, 13
29
+ 132:46.6, 33:50.6, Matsuyama, SE, 1, rain, 1014, 10
30
+ 132:04.2, 34:53.8, Hamada, ENE, 1, cloudy, 1015, 8
31
+ 133.3, 36.2, Saigo, NNE, 2, shower, 1016, 7
32
+ 135.6, 34.7, Osaka, NNE, 2, cloudy, 1014, 9
33
+ 135:45.6, 33:27.0, Shio no Misaki, NE, 1, shower, 1012, 13
34
+ 139.8, 33.1, Hachijo Jima, SW, 4, shower, 1013, 18
35
+ 139.4, 34.8, Izu Oshima, NNE, 4, shower, 1014, 9
36
+ 138:12.7, 34:36.2, Omaezaki, NE, 2, rain, 1012, 12
37
+ 140:51.4, 35:44.3, Choshi, NNE, 5, rain, 1014, 7
38
+ 139:03.6, 36:24.3, Maebashi, WNW, 1, rain, 1015, 8
39
+ 140:54.2, 36:56.8, Onahama, N, 3, rain, 1017, 5
40
+ 136:53.7, 37:23.5, Wajima, ENE, 1, rain, 1016, 5
41
+ 138:14.3, 38:01.7, Aikawa, SE, 2, rain, 1016, 4
42
+ 140.9, 38.2, Sendai, NNW, 1, snow-rain, 1018, 1
43
+ 141:57.9, 39:38.8, Miyako, N, 2, snow, 1020, 1
44
+ 140.2, 39.6, Akita, NNE, 1, cloudy, 1018, 0
45
+ 140.8, 41.8, Hakodate, NNE, 3, cloudy, 1019, -4
46
+ 142:46.6, 42:09.7, Urakawa, NNE, 2, cloudy, 1019, -5
47
+ 145:35.1, 43:19.8, Nemuro, CALM, 0, cloudy, 1019, -5
48
+ 141:40.7, 45:24.9, Wakkanai, W, 3, cloudy, 1018, -4
49
+ 151, 46, Poronaisk, W, 3, cloudy, 1018, -4
50
+ 156, 50, Severo-Kurilsk, WSW, 3, partly cloudy, 1014, -16
51
+ 135.17, 48.52, Habarovsk, CALM, 0, partly cloudy, 1014, -19
52
+ 135:48, 44:21, Rudnaya Pristan, W, 1, cloudy, 1019, -13
53
+ 131.93, 43.12, Vladivostok, SE, 3, cloudy, 1018, -5
54
+ 126.97, 37.57, Seoul, NNE, 1, partly cloudy, 1019, 1
55
+ 131, 37, Ulleung-do, NE, 1, cloudy, 1018, 3
56
+ 128.93, 35.18, Pusan, NNE, 3, cloudy, 1016, 6
57
+ 127, 35, Mokpo, NNE, 3, cloudy, 1019, 3
58
+ 126.50, 33.50, Cheju-do, NNE, 1, cloudy, 1017, 9
59
+ 121.55, 25.07, Taipei, ESE, 1, cloudy, 1013, 21
60
+ 120.35, 22.58, Kaohsiung, N, 1, cloudy, 1013, 24
61
+ 125.22, 43.90, Changchun, WNW, 3, clear, 1024, -13
62
+ 116.28, 39.93, Beijing, NNW, 4, partly cloudy, 1031, -2
63
+ 121.63, 38.90, Dalian, NNW, 3, partly cloudy, 1024, -1
64
+ 120.33, 36.07, Qingdao, NNW, 4, fog, 1024, 2
65
+ 121.4, 31.2, Shanghai, N, 3, rain, 1021, 7
66
+ 114.13, 30.62, Wuhan, NNW, 2, rain, 1025, 8
67
+ 118.08, 24.48, Xiamen, CALM, 0, fog, 1014, 18
68
+ 114.02, 22.20, Hong Kong, ESE, 2, partly cloudy, 1014, 21
69
+ 120.53, 18.18, Laoag, CALM, 0, clear, 1012, 22
70
+ 121.00, 14.52, Manila, WNW, 1, partly cloudy, 1013, 25
71
+ 142.18, 27.08, Chichi Jima, NW, 1, clear, 1020, 16
72
+ 133.97, 24.30, Minami Tori Shima, E, 4, X, 1021, 23
73
+ 138:43.6, 35:21.6, Fujisan, X, X, X, X, -4
74
+ 126, 29, SHIP, NW, 5, rain, 1015, X
75
+ 148, 21, SHIP, E, 3, cloudy, 1018, X
76
+ 139, 31, SHIP, SW, 7, partly cloudy, 1016, X
77
+ 136, 39, SHIP, ENE, 5, partly cloudy, 1017, X
78
+ 146, 36, SHIP, ENE, 5, rain, 1013, X
79
+ EOF
80
+ for line in csv.split(/\n/)
81
+ x, y, name, wdir, wspd, weather, pres, temp = line.split(/, */)
82
+ x = $1.to_i + $2.to_f / 60 if /(\d+):(\d+(\.\d)?)/ === x
83
+ y = $1.to_i + $2.to_f / 60 if /(\d+):(\d+(\.\d)?)/ === y
84
+ x = Float(x)
85
+ y = Float(y)
86
+ wdir = nil if wdir == 'X'
87
+ weather = nil if weather == 'X'
88
+ wspd = (wspd == 'X' ? nil : Integer(wspd))
89
+ pres = (pres == 'X' ? nil : Integer(pres))
90
+ temp = (temp == 'X' ? nil : Integer(temp))
91
+ fp.write new_point(x, y,
92
+ 'name' => name, 'wdir' => wdir, 'wspd' => wspd,
93
+ 'weather' => weather , 'pres' => pres, 'temp' => temp)
94
+ end
95
+ fp.close
96
+ end
97
+
98
+ def layer2
99
+ fp = ShapeFile.new('ts1sys.shp', :Point)
100
+ fp.add_field 'class', 'String', 16
101
+ fp.add_field 'symbol', 'String', 3
102
+ fp.add_field 'pres', 'Integer', 4
103
+ fp.add_field 'dir', 'String', 4
104
+ fp.add_field 'speed', 'Integer', 3
105
+ fp.write new_point(169, 45, 'class' => 'Low', 'symbol' => 'L',
106
+ 'pres' => 992, 'dir' => 'NNE', 'speed' => 20)
107
+ fp.write new_point(177, 58, 'class' => 'Low', 'symbol' => 'L',
108
+ 'pres' => 996, 'dir' => 'N', 'speed' => 10)
109
+ fp.write new_point(130, 41, 'class' => 'Low', 'symbol' => 'L',
110
+ 'pres' => 1016, 'dir' => 'ENE', 'speed' => 10)
111
+ fp.write new_point(134, 33, 'class' => 'Low', 'symbol' => 'L',
112
+ 'pres' => 1012, 'dir' => 'ENE', 'speed' => 20)
113
+ fp.write new_point(152, 57, 'class' => 'Low', 'symbol' => 'L',
114
+ 'pres' => 1000, 'dir' => 'WSW', 'speed' => 5)
115
+ fp.write new_point(156, 48, 'class' => 'Low', 'symbol' => 'L',
116
+ 'pres' => 1004, 'dir' => 'E', 'speed' => 10)
117
+ fp.write new_point(139, 3, 'class' => 'Low', 'symbol' => 'L',
118
+ 'pres' => 1008, 'dir' => 'STNR', 'speed' => 0)
119
+ fp.write new_point(138, 43, 'class' => 'High', 'symbol' => 'H',
120
+ 'pres' => 1020, 'dir' => 'E', 'speed' => 15)
121
+ fp.write new_point(164, 29, 'class' => 'High', 'symbol' => 'H',
122
+ 'pres' => 1024, 'dir' => 'E', 'speed' => 20)
123
+ fp.close
124
+ end
125
+
126
+ def layer3
127
+ fp = ShapeFile.new('ts1frnt.shp', :Arc)
128
+ fp.add_field 'class', 'String', 16
129
+
130
+ arc = Arc.new [[169, 45], [172, 44], [175, 41]]
131
+ arc['class'] = 'occlusion'
132
+ fp.write arc
133
+
134
+ arc = Arc.new [[175, 41], [177, 39], [178, 37]]
135
+ arc['class'] = 'warm'
136
+ fp.write arc
137
+
138
+ arc = Arc.new [[175, 41], [171, 38], [164, 36]]
139
+ arc['class'] = 'cold'
140
+ fp.write arc
141
+
142
+ arc = Arc.new [[119, 27], [128, 29], [134, 33], [139, 34],
143
+ [142, 35], [150, 35]]
144
+ arc['class'] = 'stationary'
145
+ fp.write arc
146
+
147
+ fp.close
148
+ end
149
+
150
+ def layer4
151
+ fp = ShapeFile.new('ts1isop.shp', :Arc)
152
+ fp.add_field 'pres', 'Integer', 4
153
+ arc = Arc.new [[168, 19], [150, 18], [141, 19], [129, 22], [133, 29], [147, 34], [149, 36], [141, 37], [128, 34], [122, 28], [110, 25]]
154
+ arc['pres'] = 1016
155
+ fp.write arc
156
+ fp.close
157
+ end
158
+
159
+ def run
160
+ layer1
161
+ layer2
162
+ layer3
163
+ layer4
164
+ end
165
+
166
+ end
167
+
168
+ Sample1.new.run
data/test/ztest1.rb ADDED
@@ -0,0 +1,253 @@
1
+ require 'shapelib'
2
+ require 'libtest.rb'
3
+
4
+ def test1
5
+ testblock('test1') do
6
+ file_delete(*%w(test1.dbf test1.shp test1.shx))
7
+ s = ShapeLib::ShapeFile.new('test1.shp', :Point, [["id", :Integer, 8]])
8
+ assert(s.field_count, 1)
9
+ s.add_field 'name', ShapeLib::String, 12
10
+ assert(s.field_count, 2)
11
+ assert(s.field_index('name'), 1)
12
+ assert(s.field_type('name'), :String)
13
+ assert(s.field_type(1), :String)
14
+ s.add_field 'k', ShapeLib::Integer, 3
15
+ assert(s.field_count, 3)
16
+ s.add_field 'y', "Float", 8, 3
17
+ assert(s.field_index('y'), 3)
18
+ assert(s.field_type('y'), :Float)
19
+ assert(s.field_count, 4)
20
+ assert(s.size, 0)
21
+
22
+ shape = ShapeLib::Point.new(100, 101, 'id' => 234)
23
+ shape['name'] = 'foo'
24
+ shape['k'] = 18
25
+ fval = shape['y'] = 31.415926
26
+ assert(s.write(shape), 0)
27
+ assert(s.size, 1)
28
+ assert(shape.x, 100.0)
29
+
30
+ assert(s.fields, %w(id name k y))
31
+ assert(s.field_type(1), :String)
32
+ assert(s.field_name(1), 'name')
33
+
34
+ assert(shape['id'], 234)
35
+ assert(shape['name'], 'foo')
36
+ assert(shape['k'], 18)
37
+ assert(shape['y'], fval)
38
+ assert(shape['unspecified'], nil)
39
+
40
+ shape = ShapeLib.new_point(200, 201)
41
+ assert(s.write(shape), 1)
42
+ assert(s.size, 2)
43
+
44
+ assert(shape['id'], nil)
45
+ assert(shape.x, 200.0)
46
+
47
+ shape = s.read(0)
48
+ assert(shape.shape_id, 0)
49
+ assert(shape['id'], 234)
50
+ assert(shape['name'], 'foo')
51
+ assert(shape['k'], 18)
52
+ # note that only 3 digits after decimal point is conserved.
53
+ assert(shape['y'], 31.416)
54
+ assert(shape['unspecified'], nil)
55
+ assert(shape['unspecified2'], nil)
56
+
57
+ assert s.maxbound, [200, 201, 0, 0]
58
+
59
+ s.close
60
+
61
+ assert_file 'test1.dbf', <<EOF
62
+ 035f071a02000000a10020000000000000000000000000000000000000000000
63
+ 69640000000000000000004e0000000008000000000000000000000000000000
64
+ 6e616d650000000000000043000000000c000000000000000000000000000000
65
+ 6b000000000000000000004e0000000003000000000000000000000000000000
66
+ 79000000000000000000004e0000000008030000000000000000000000000000
67
+ 0d202020202020323334666f6f202020202020202020203138202033312e3431
68
+ 36202a2a2a2a2a2a2a2a0000000000000000000000002a2a2a2a2a2a2a2a2a2a
69
+ 2a
70
+ EOF
71
+ assert_file 'test1.shp', <<EOF
72
+ 0000270a00000000000000000000000000000000000000000000004ee8030000
73
+ 0100000000000000000059400000000000405940000000000000694000000000
74
+ 0020694000000000000000000000000000000000000000000000000000000000
75
+ 00000000000000010000000a0100000000000000000059400000000000405940
76
+ 000000020000000a0100000000000000000069400000000000206940
77
+ EOF
78
+ assert_file 'test1.shx', <<EOF
79
+ 0000270a00000000000000000000000000000000000000000000003ae8030000
80
+ 0100000000000000000059400000000000405940000000000000694000000000
81
+ 0020694000000000000000000000000000000000000000000000000000000000
82
+ 00000000000000320000000a000000400000000a
83
+ EOF
84
+
85
+ file_delete(*%w(test1.dbf test1.shp test1.shx))
86
+ end
87
+ end
88
+
89
+ def test2
90
+ testblock('test2') do
91
+ file_delete(*%w(test2.dbf test2.shp test2.shx))
92
+ s = ShapeLib::ShapeFile.new('test2.shp', ShapeLib::PointM)
93
+ assert(s.class.to_s, "ShapeLib::ShapeFile")
94
+ assert(s.field_count, 0)
95
+ s.add_field 'name', ShapeLib::String, 12
96
+ assert(s.field_count, 1)
97
+ assert(s.size, 0)
98
+
99
+ shape = ShapeLib.new_point(301, 302, 303)
100
+ assert(shape.class.to_s, "ShapeLib::PointM")
101
+ s.write(shape)
102
+ assert(s.size, 1)
103
+ assert(shape.m, 303)
104
+
105
+ shape = ShapeLib::PointM.new(401, 402, 403)
106
+ assert(shape.class.to_s, "ShapeLib::PointM")
107
+ s.write(shape)
108
+ assert(s.size, 2)
109
+
110
+ s.close
111
+ assert_file 'test2.shp', <<EOF
112
+ 0000270a000000000000000000000000000000000000000000000056e8030000
113
+ 150000000000000000d072400000000000e07240000000000010794000000000
114
+ 00207940000000000000000000000000000000000000000000f0724000000000
115
+ 00307940000000010000000e150000000000000000d072400000000000e07240
116
+ 0000000000f07240000000020000000e15000000000000000010794000000000
117
+ 002079400000000000307940
118
+ EOF
119
+
120
+ sx = ShapeLib::ShapeFile.open('test2.shp')
121
+ assert sx.shape_type, :PointM
122
+ assert sx.minbound, [301.0, 302.0, 303.0, 0]
123
+ assert sx.maxbound, [401.0, 402.0, 403.0, 0]
124
+ sx.close
125
+
126
+ file_delete(*%w(test2.dbf test2.shp test2.shx))
127
+ end
128
+ end
129
+
130
+ def testA1
131
+ testblock('testA1') do
132
+ file_delete(*%w(testa1.dbf testa1.shp testa1.shx))
133
+ s = ShapeLib::ShapeFile.new('testa1.shp', "Arc")
134
+ assert(s.class.to_s, "ShapeLib::ShapeFile")
135
+ assert(s.field_count, 0)
136
+ s.add_field 'name', ShapeLib::String, 12
137
+ assert(s.field_count, 1)
138
+ assert(s.size, 0)
139
+
140
+ p1 = ShapeLib.new_point(1.1, 1.2)
141
+ p2 = ShapeLib.new_point(2.1, 2.2)
142
+ p3 = ShapeLib.new_point(3.1, 3.2)
143
+ shape = ShapeLib::Arc.new([p1, p2, p3])
144
+ assert(shape.class.to_s, 'ShapeLib::Arc')
145
+ assert(shape.n_parts, 1)
146
+ assert(shape.n_vertices, 3)
147
+ assert(shape.shape_id, nil)
148
+ assert(shape.shape_type, :Arc)
149
+ assert(s.write(shape), 0)
150
+
151
+ arc2 = [[101, 102], [111, 112], [121, 122]]
152
+ shape = ShapeLib::Arc.new([p1, p3], arc2)
153
+ assert(shape.n_parts, 2)
154
+ assert(s.write(shape), 1)
155
+
156
+ assert(shape.shape_id, nil)
157
+ assert(s.read(1).shape_id, 1)
158
+
159
+ file_delete(*%w(testa1.dbf testa1.shp testa1.shx))
160
+ end
161
+ end
162
+
163
+ def test3
164
+ testblock('test3') do
165
+ pt = ShapeLib::Point.new 4324434.13545, 3495423412.4324324
166
+ assert(pt.wkt, "POINT(4324434.135 3495423412)")
167
+ assert(pt.part_type, nil)
168
+ mp = ShapeLib::MultiPoint.new [1, 2], [3, 4], [5, 6]
169
+ assert(mp.wkt, "MULTIPOINT(1 2, 3 4, 5 6)")
170
+
171
+ ar = ShapeLib::Arc.new [1, 2], [3, 4], [5, 6]
172
+ assert(ar.wkt, "LINESTRING(1 2, 3 4, 5 6)")
173
+ assert(ar.xvals, [1, 3, 5])
174
+ assert(ar.yvals, [2, 4, 6])
175
+ ar = ShapeLib::Arc.new([[1, 2], [3, 4], [5, 6]])
176
+ assert(ar.wkt, "LINESTRING(1 2, 3 4, 5 6)")
177
+ ar = ShapeLib::Arc.new([[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10]])
178
+ assert(ar.wkt, "MULTILINESTRING((1 2, 3 4, 5 6), (7 8, 9 10))")
179
+ assert ar.xvals, [1, 3, 5, 7, 9]
180
+
181
+ ar2 = ShapeLib::Shape.new(arh = ar.to_h)
182
+ assert(ar2.class.to_s, "ShapeLib::Arc")
183
+ assert(ar2.to_h, arh)
184
+ assert(ar2.wkt, ar.wkt)
185
+
186
+ arm = ShapeLib::ArcM.new [1, 2, 3], [4, 5, 6], [7, 8, 9]
187
+ assert arm.mvals, [3, 6, 9]
188
+ arm = ShapeLib::ArcM.new [1, 2], [4, 5], [7, 8]
189
+ assert arm.mvals, [nil, nil, nil]
190
+
191
+ pl = ShapeLib::Polygon.new [1, 2], [3, 4], [5, 6.5], [1, 2]
192
+ assert(pl.wkt, "POLYGON((1 2, 3 4, 5 6.5, 1 2))")
193
+ assert(pl.rewind_polygon, true)
194
+ assert(pl.wkt, "POLYGON((1 2, 5 6.5, 3 4, 1 2))")
195
+ pl = ShapeLib::Polygon.new [[1, 2], [3, 4], [5, 6.5], [1, 2]]
196
+ assert(pl.wkt, "POLYGON((1 2, 3 4, 5 6.5, 1 2))")
197
+ pl = ShapeLib::Polygon.new([[1, 2], [3, 4], [5, 6.5], [1, 2]],
198
+ [[7, 8], [9, 10], [11, 12.5], [7, 8]])
199
+ assert(pl.part_type, [:Ring, :Ring])
200
+ assert(pl.wkt,
201
+ "POLYGON((1 2, 3 4, 5 6.5, 1 2), (7 8, 9 10, 11 12.5, 7 8))")
202
+
203
+ pl['abbrev'] = 'WI'
204
+ pl['state'] = 'Wisconsin'
205
+ pl['update'] = '2006-02-16'
206
+ assert ShapeLib::Shape.new(pl.to_h).to_h, pl.to_h
207
+
208
+ mq = ShapeLib::MultiPatch.new :OuterRing, [1, 2], [3, 4], [5, 6.5], [1, 2]
209
+ assert(mq.wkt, "POLYGON((1 2, 3 4, 5 6.5, 1 2))")
210
+ end
211
+ end
212
+
213
+ def test4
214
+ testblock('test4') do
215
+ file_delete(*%w(test4.dbf test4.shp test4.shx))
216
+ s = ShapeLib::ShapeFile.new('test4.shp', :PointM)
217
+ assert(s.class.to_s, "ShapeLib::ShapeFile")
218
+ assert(s.field_count, 0)
219
+ assert(s.size, 0)
220
+ # shape = ShapeLib.new_point(301, 302, 303, 'foo' => 123)
221
+ shape = ShapeLib.new_point(301, 302, 303)
222
+ assert(s.write(shape), 0)
223
+ shape = ShapeLib::PointM.new(401, 402, 403)
224
+ assert(s.write(shape), 1)
225
+ s.close
226
+
227
+ fp = ShapeLib::ShapeFile.open('test4')
228
+ assert fp.size, 2
229
+ shape = fp.read(0)
230
+ assert(shape.class.to_s, "ShapeLib::Shape")
231
+ assert fp.size, 2
232
+ fp.close
233
+
234
+ ShapeLib::ShapeFile.open('test4.shp') do |fp|
235
+ shape = fp.read
236
+ assert(shape.shape_id, 0)
237
+ shape = fp.read
238
+ assert(shape.shape_id, 1)
239
+ assert(fp.read, nil)
240
+ i = 0
241
+ fp.each do |shape|
242
+ assert shape.shape_id, i
243
+ i += 1
244
+ end
245
+ assert i, 2
246
+ end
247
+
248
+ file_delete(*%w(test4.dbf test4.shp test4.shx))
249
+ end
250
+ end
251
+
252
+
253
+ exit(test1 + test2 + testA1 + test3 + test4)