shapelib 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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)