GeoRuby 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/geo_ruby/shp4r/shp.rb +1 -1
- data/lib/geo_ruby/simple_features/io/ewkb_parser.rb +213 -0
- data/lib/geo_ruby/simple_features/io/ewkt_parser.rb +335 -0
- data/lib/geo_ruby/simple_features/io/geometry_factory.rb +65 -0
- data/rakefile.rb +1 -1
- data/tools/lib/spatial_adapter/README +4 -4
- data/tools/lib/spatial_adapter/lib/common_spatial_adapter.rb +2 -0
- data/tools/lib/spatial_adapter/lib/mysql_spatial_adapter.rb +51 -27
- data/tools/lib/spatial_adapter/lib/post_gis_adapter.rb +52 -26
- data/tools/lib/spatial_adapter/rakefile.rb +1 -1
- data/tools/lib/spatial_adapter/test/access_mysql_test.rb +8 -8
- data/tools/lib/spatial_adapter/test/migration_mysql_test.rb +3 -4
- data/tools/lib/spatial_adapter/test/migration_postgis_test.rb +22 -4
- metadata +11 -11
- data/test/data/polyline2.dbf +0 -0
- data/test/data/polyline2.shp +0 -0
- data/test/data/polyline2.shx +0 -0
data/lib/geo_ruby/shp4r/shp.rb
CHANGED
@@ -444,7 +444,7 @@ module GeoRuby
|
|
444
444
|
else
|
445
445
|
data.to_s
|
446
446
|
end
|
447
|
-
@dbf_io << [str].pack("
|
447
|
+
@dbf_io << [str].pack("A#{field.length}")
|
448
448
|
end
|
449
449
|
|
450
450
|
shp_str,min_xp,max_xp,min_yp,max_yp,min_zp,max_zp,min_mp,max_mp = build_shp_geometry(record.geometry)
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'geo_ruby/simple_features/point'
|
2
|
+
require 'geo_ruby/simple_features/line_string'
|
3
|
+
require 'geo_ruby/simple_features/linear_ring'
|
4
|
+
require 'geo_ruby/simple_features/polygon'
|
5
|
+
require 'geo_ruby/simple_features/multi_point'
|
6
|
+
require 'geo_ruby/simple_features/multi_line_string'
|
7
|
+
require 'geo_ruby/simple_features/multi_polygon'
|
8
|
+
require 'geo_ruby/simple_features/geometry_collection'
|
9
|
+
|
10
|
+
module GeoRuby
|
11
|
+
module SimpleFeatures
|
12
|
+
module Io
|
13
|
+
#Raised when an error in the EWKB string is detected
|
14
|
+
class EWKBFormatError < StandardError
|
15
|
+
end
|
16
|
+
|
17
|
+
#Parses EWKB strings and notifies of events (such as the beginning of the definition of geometry, the value of the SRID...) the factory passed as argument to the constructor.
|
18
|
+
#
|
19
|
+
#=Example
|
20
|
+
# factory = GeometryFactory::new
|
21
|
+
# ewkb_parser = EWKBParser::new(factory)
|
22
|
+
# ewkb_parser.parse(<EWKB String>)
|
23
|
+
# geometry = @factory.geometry
|
24
|
+
#
|
25
|
+
#You can also use directly the static method Geometry.from_ewkb
|
26
|
+
class EWKBParser
|
27
|
+
|
28
|
+
def initialize(factory)
|
29
|
+
@factory = factory
|
30
|
+
@parse_options ={
|
31
|
+
1 => method(:parse_point),
|
32
|
+
2 => method(:parse_line_string),
|
33
|
+
3 => method(:parse_polygon),
|
34
|
+
4 => method(:parse_multi_point),
|
35
|
+
5 => method(:parse_multi_line_string),
|
36
|
+
6 => method(:parse_multi_polygon),
|
37
|
+
7 => method(:parse_geometry_collection)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
#Parses the ewkb string passed as argument and notifies the factory of events
|
42
|
+
def parse(ewkb)
|
43
|
+
@factory.reset
|
44
|
+
@unpack_structure=UnpackStructure::new(ewkb)
|
45
|
+
@with_z = false
|
46
|
+
@with_m = false
|
47
|
+
parse_geometry
|
48
|
+
@unpack_structure.done
|
49
|
+
@srid=nil
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def parse_geometry
|
54
|
+
@unpack_structure.endianness=@unpack_structure.read_byte
|
55
|
+
@geometry_type = @unpack_structure.read_uint
|
56
|
+
|
57
|
+
if (@geometry_type & Z_MASK) != 0
|
58
|
+
@with_z=true
|
59
|
+
@geometry_type = @geometry_type & ~Z_MASK
|
60
|
+
end
|
61
|
+
if (@geometry_type & M_MASK) != 0
|
62
|
+
@with_m=true
|
63
|
+
@geometry_type = @geometry_type & ~M_MASK
|
64
|
+
end
|
65
|
+
if (@geometry_type & SRID_MASK) != 0
|
66
|
+
@srid = @unpack_structure.read_uint
|
67
|
+
@geometry_type = @geometry_type & ~SRID_MASK
|
68
|
+
else
|
69
|
+
#to manage multi geometries : the srid is not present in sub_geometries, therefore we take the srid of the parent ; if it is the root, we take the default srid
|
70
|
+
@srid= @srid || DEFAULT_SRID
|
71
|
+
end
|
72
|
+
|
73
|
+
if @parse_options.has_key? @geometry_type
|
74
|
+
@parse_options[@geometry_type].call
|
75
|
+
else
|
76
|
+
raise EWKBFormatError::new("Unknown geometry type")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_geometry_collection
|
81
|
+
parse_multi_geometries(GeometryCollection)
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_multi_polygon
|
85
|
+
parse_multi_geometries(MultiPolygon)
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_multi_line_string
|
89
|
+
parse_multi_geometries(MultiLineString)
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_multi_point
|
93
|
+
parse_multi_geometries(MultiPoint)
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_multi_geometries(geometry_type)
|
97
|
+
@factory.begin_geometry(geometry_type,@srid)
|
98
|
+
num_geometries = @unpack_structure.read_uint
|
99
|
+
1.upto(num_geometries) { parse_geometry }
|
100
|
+
@factory.end_geometry(@with_z,@with_m)
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_polygon
|
104
|
+
@factory.begin_geometry(Polygon,@srid)
|
105
|
+
num_linear_rings = @unpack_structure.read_uint
|
106
|
+
1.upto(num_linear_rings) {parse_linear_ring}
|
107
|
+
@factory.end_geometry(@with_z,@with_m)
|
108
|
+
end
|
109
|
+
|
110
|
+
def parse_linear_ring
|
111
|
+
parse_point_list(LinearRing)
|
112
|
+
end
|
113
|
+
|
114
|
+
def parse_line_string
|
115
|
+
parse_point_list(LineString)
|
116
|
+
end
|
117
|
+
|
118
|
+
#used to parse line_strings and linear_rings
|
119
|
+
def parse_point_list(geometry_type)
|
120
|
+
@factory.begin_geometry(geometry_type,@srid)
|
121
|
+
num_points = @unpack_structure.read_uint
|
122
|
+
1.upto(num_points) {parse_point}
|
123
|
+
@factory.end_geometry(@with_z,@with_m)
|
124
|
+
end
|
125
|
+
|
126
|
+
def parse_point
|
127
|
+
@factory.begin_geometry(Point,@srid)
|
128
|
+
x = @unpack_structure.read_double
|
129
|
+
y = @unpack_structure.read_double
|
130
|
+
if ! (@with_z or @with_m) #most common case probably
|
131
|
+
@factory.add_point_x_y(x,y)
|
132
|
+
elsif @with_m and @with_z
|
133
|
+
z = @unpack_structure.read_double
|
134
|
+
m = @unpack_structure.read_double
|
135
|
+
@factory.add_point_x_y_z_m(x,y,z,m)
|
136
|
+
elsif @with_z
|
137
|
+
z = @unpack_structure.read_double
|
138
|
+
@factory.add_point_x_y_z(x,y,z)
|
139
|
+
else
|
140
|
+
m = @unpack_structure.read_double
|
141
|
+
@factory.add_point_x_y_m(x,y,m)
|
142
|
+
end
|
143
|
+
|
144
|
+
@factory.end_geometry(@with_z,@with_m)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
#Parses HexEWKB strings. In reality, it just transforms the HexEWKB string into the equivalent EWKB string and lets the EWKBParser do the actual parsing.
|
149
|
+
class HexEWKBParser < EWKBParser
|
150
|
+
def initialize(factory)
|
151
|
+
super(factory)
|
152
|
+
end
|
153
|
+
#parses an HexEWKB string
|
154
|
+
def parse(hexewkb)
|
155
|
+
super(decode_hex(hexewkb))
|
156
|
+
end
|
157
|
+
#transforms a HexEWKB string into an EWKB string
|
158
|
+
def decode_hex(hexewkb)
|
159
|
+
temp_hexewkb= hexewkb.clone
|
160
|
+
result=""
|
161
|
+
while c = temp_hexewkb.slice!(0,2) do
|
162
|
+
break if c.length==0
|
163
|
+
result << c.hex
|
164
|
+
end
|
165
|
+
result
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
class UnpackStructure #:nodoc:
|
171
|
+
NDR=1
|
172
|
+
XDR=0
|
173
|
+
def initialize(ewkb)
|
174
|
+
@position=0
|
175
|
+
@ewkb=ewkb
|
176
|
+
end
|
177
|
+
def done
|
178
|
+
raise EWKBFormatError::new("Trailing data") if @position != @ewkb.length
|
179
|
+
end
|
180
|
+
def read_double
|
181
|
+
i=@position
|
182
|
+
@position += 8
|
183
|
+
packed_double = @ewkb[i...@position]
|
184
|
+
raise EWKBFormatError::new("Truncated data") if packed_double.nil? or packed_double.length < 8
|
185
|
+
packed_double.unpack(@double_mark)[0]
|
186
|
+
end
|
187
|
+
def read_uint
|
188
|
+
i=@position
|
189
|
+
@position += 4
|
190
|
+
packed_uint = @ewkb[i...@position]
|
191
|
+
raise EWKBFormatError::new("Truncated data") if packed_uint.nil? or packed_uint.length < 4
|
192
|
+
packed_uint.unpack(@uint_mark)[0]
|
193
|
+
end
|
194
|
+
def read_byte
|
195
|
+
i = @position
|
196
|
+
@position += 1
|
197
|
+
packed_byte = @ewkb[i...@position]
|
198
|
+
raise EWKBFormatError::new("Truncated data") if packed_byte.nil? or packed_byte.length < 1
|
199
|
+
packed_byte.unpack("C")[0]
|
200
|
+
end
|
201
|
+
def endianness=(byte_order)
|
202
|
+
if(byte_order == NDR)
|
203
|
+
@uint_mark="V"
|
204
|
+
@double_mark="E"
|
205
|
+
elsif(byte_order == XDR)
|
206
|
+
@uint_mark="N"
|
207
|
+
@double_mark="G"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,335 @@
|
|
1
|
+
require 'geo_ruby/simple_features/point'
|
2
|
+
require 'geo_ruby/simple_features/line_string'
|
3
|
+
require 'geo_ruby/simple_features/linear_ring'
|
4
|
+
require 'geo_ruby/simple_features/polygon'
|
5
|
+
require 'geo_ruby/simple_features/multi_point'
|
6
|
+
require 'geo_ruby/simple_features/multi_line_string'
|
7
|
+
require 'geo_ruby/simple_features/multi_polygon'
|
8
|
+
require 'geo_ruby/simple_features/geometry_collection'
|
9
|
+
|
10
|
+
require 'strscan'
|
11
|
+
|
12
|
+
module GeoRuby
|
13
|
+
module SimpleFeatures
|
14
|
+
module Io
|
15
|
+
#Raised when an error in the EWKT string is detected
|
16
|
+
class EWKTFormatError < StandardError
|
17
|
+
end
|
18
|
+
|
19
|
+
#Parses EWKT strings and notifies of events (such as the beginning of the definition of geometry, the value of the SRID...) the factory passed as argument to the constructor.
|
20
|
+
#
|
21
|
+
#=Example
|
22
|
+
# factory = GeometryFactory::new
|
23
|
+
# ewkt_parser = EWKTParser::new(factory)
|
24
|
+
# ewkt_parser.parse(<EWKT String>)
|
25
|
+
# geometry = @factory.geometry
|
26
|
+
#
|
27
|
+
#You can also use directly the static method Geometry.from_ewkt
|
28
|
+
class EWKTParser
|
29
|
+
|
30
|
+
def initialize(factory)
|
31
|
+
@factory = factory
|
32
|
+
@parse_options ={
|
33
|
+
"POINT" => method(:parse_point),
|
34
|
+
"LINESTRING" => method(:parse_line_string),
|
35
|
+
"POLYGON" => method(:parse_polygon),
|
36
|
+
"MULTIPOINT" => method(:parse_multi_point),
|
37
|
+
"MULTILINESTRING" => method(:parse_multi_line_string),
|
38
|
+
"MULTIPOLYGON" => method(:parse_multi_polygon),
|
39
|
+
"GEOMETRYCOLLECTION" => method(:parse_geometry_collection)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
#Parses the ewkt string passed as argument and notifies the factory of events
|
44
|
+
def parse(ewkt)
|
45
|
+
@factory.reset
|
46
|
+
@tokenizer_structure = TokenizerStructure.new(ewkt)
|
47
|
+
@with_z=false
|
48
|
+
@with_m=false
|
49
|
+
@is_3dm = false
|
50
|
+
parse_geometry(true)
|
51
|
+
@srid=nil
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def parse_geometry(srid_allowed)
|
56
|
+
|
57
|
+
token = @tokenizer_structure.get_next_token
|
58
|
+
if token == 'SRID'
|
59
|
+
#SRID present
|
60
|
+
raise EWKTFormatError.new("SRID not allowed at this position") if(!srid_allowed)
|
61
|
+
if @tokenizer_structure.get_next_token != '='
|
62
|
+
raise EWKTFormatError.new("Invalid SRID expression")
|
63
|
+
else
|
64
|
+
@srid = @tokenizer_structure.get_next_token.to_i
|
65
|
+
raise EWKTFormatError.new("Invalid SRID separator") if @tokenizer_structure.get_next_token != ';'
|
66
|
+
geom_type = @tokenizer_structure.get_next_token
|
67
|
+
end
|
68
|
+
|
69
|
+
else
|
70
|
+
#to manage multi geometries : the srid is not present in sub_geometries, therefore we take the srid of the parent ; if it is the root, we take the default srid
|
71
|
+
@srid= @srid || DEFAULT_SRID
|
72
|
+
geom_type = token
|
73
|
+
end
|
74
|
+
|
75
|
+
if geom_type[-1] == ?M
|
76
|
+
@is_3dm=true
|
77
|
+
@with_m=true
|
78
|
+
geom_type.chop! #remove the M
|
79
|
+
end
|
80
|
+
|
81
|
+
if @parse_options.has_key?(geom_type)
|
82
|
+
@parse_options[geom_type].call
|
83
|
+
else
|
84
|
+
raise EWKTFormatError.new("Urecognized geometry type: #{geom_type}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_geometry_collection
|
89
|
+
if @tokenizer_structure.get_next_token !='('
|
90
|
+
raise EWKTFormatError.new('Invalid GeometryCollection')
|
91
|
+
end
|
92
|
+
|
93
|
+
@factory.begin_geometry(GeometryCollection,@srid)
|
94
|
+
|
95
|
+
token = ''
|
96
|
+
while token != ')'
|
97
|
+
parse_geometry(false)
|
98
|
+
token = @tokenizer_structure.get_next_token
|
99
|
+
if token.nil?
|
100
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
@factory.end_geometry(@with_z,@with_m)
|
105
|
+
end
|
106
|
+
|
107
|
+
def parse_multi_polygon
|
108
|
+
if @tokenizer_structure.get_next_token !='('
|
109
|
+
raise EWKTFormatError.new('Invalid MultiLineString')
|
110
|
+
end
|
111
|
+
|
112
|
+
@factory.begin_geometry(MultiPolygon,@srid)
|
113
|
+
token = ''
|
114
|
+
while token != ')'
|
115
|
+
parse_polygon
|
116
|
+
token = @tokenizer_structure.get_next_token
|
117
|
+
if token.nil?
|
118
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
@factory.end_geometry(@with_z,@with_m)
|
123
|
+
end
|
124
|
+
|
125
|
+
def parse_multi_line_string
|
126
|
+
if @tokenizer_structure.get_next_token !='('
|
127
|
+
raise EWKTFormatError.new('Invalid MultiLineString')
|
128
|
+
end
|
129
|
+
|
130
|
+
@factory.begin_geometry(MultiLineString,@srid)
|
131
|
+
|
132
|
+
token = ''
|
133
|
+
while token != ')'
|
134
|
+
parse_line_string
|
135
|
+
token = @tokenizer_structure.get_next_token
|
136
|
+
if token.nil?
|
137
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
@factory.end_geometry(@with_z,@with_m)
|
142
|
+
end
|
143
|
+
|
144
|
+
def parse_polygon
|
145
|
+
if @tokenizer_structure.get_next_token !='('
|
146
|
+
raise EWKTFormatError.new('Invalid Polygon')
|
147
|
+
end
|
148
|
+
|
149
|
+
@factory.begin_geometry(Polygon,@srid)
|
150
|
+
|
151
|
+
token = ''
|
152
|
+
while token != ')'
|
153
|
+
parse_linear_ring
|
154
|
+
token = @tokenizer_structure.get_next_token
|
155
|
+
if token.nil?
|
156
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
@factory.end_geometry(@with_z,@with_m)
|
161
|
+
end
|
162
|
+
|
163
|
+
#must support the PostGIS form and the one in the specification
|
164
|
+
def parse_multi_point
|
165
|
+
if @tokenizer_structure.get_next_token !='('
|
166
|
+
raise EWKTFormatError.new('Invalid MultiPoint')
|
167
|
+
end
|
168
|
+
|
169
|
+
token = @tokenizer_structure.check_next_token
|
170
|
+
if token == '('
|
171
|
+
#specification
|
172
|
+
@factory.begin_geometry(MultiPoint,@srid)
|
173
|
+
|
174
|
+
token = ''
|
175
|
+
while token != ')'
|
176
|
+
parse_point
|
177
|
+
token = @tokenizer_structure.get_next_token
|
178
|
+
if token.nil?
|
179
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
@factory.end_geometry(@with_z,@with_m)
|
184
|
+
else
|
185
|
+
#postgis
|
186
|
+
parse_point_list(MultiPoint)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def parse_linear_ring
|
191
|
+
if @tokenizer_structure.get_next_token !='('
|
192
|
+
raise EWKTFormatError.new('Invalid Linear ring')
|
193
|
+
end
|
194
|
+
|
195
|
+
parse_point_list(LinearRing)
|
196
|
+
end
|
197
|
+
|
198
|
+
def parse_line_string
|
199
|
+
if @tokenizer_structure.get_next_token !='('
|
200
|
+
raise EWKTFormatError.new('Invalid Line string')
|
201
|
+
end
|
202
|
+
|
203
|
+
parse_point_list(LineString)
|
204
|
+
end
|
205
|
+
|
206
|
+
#used to parse line_strings and linear_rings and the PostGIS form of multi_points
|
207
|
+
def parse_point_list(geometry_type)
|
208
|
+
@factory.begin_geometry(geometry_type,@srid)
|
209
|
+
|
210
|
+
token = ''
|
211
|
+
while token != ')'
|
212
|
+
@factory.begin_geometry(Point,@srid)
|
213
|
+
token = parse_coords
|
214
|
+
if token.nil?
|
215
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
216
|
+
end
|
217
|
+
@factory.end_geometry(@with_z,@with_m)
|
218
|
+
end
|
219
|
+
|
220
|
+
@factory.end_geometry(@with_z,@with_m)
|
221
|
+
end
|
222
|
+
|
223
|
+
def parse_point
|
224
|
+
if @tokenizer_structure.get_next_token !='('
|
225
|
+
raise EWKTFormatError.new('Invalid Point')
|
226
|
+
end
|
227
|
+
|
228
|
+
@factory.begin_geometry(Point,@srid)
|
229
|
+
|
230
|
+
token = parse_coords
|
231
|
+
|
232
|
+
if token != ')'
|
233
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
234
|
+
end
|
235
|
+
|
236
|
+
@factory.end_geometry(@with_z,@with_m)
|
237
|
+
end
|
238
|
+
|
239
|
+
def parse_coords
|
240
|
+
coords = Array.new
|
241
|
+
x = @tokenizer_structure.get_next_token
|
242
|
+
y = @tokenizer_structure.get_next_token
|
243
|
+
|
244
|
+
if x.nil? or y.nil?
|
245
|
+
raise EWKTFormatError.new("Bad Point format")
|
246
|
+
end
|
247
|
+
|
248
|
+
if @is_3dm
|
249
|
+
m = @tokenizer_structure.get_next_token
|
250
|
+
|
251
|
+
if m.nil? or m == ',' or m == ')'
|
252
|
+
raise EWKTFormatError.new("No M dimension found")
|
253
|
+
else
|
254
|
+
@factory.add_point_x_y_m(x.to_f,y.to_f,m.to_f)
|
255
|
+
@tokenizer_structure.get_next_token
|
256
|
+
end
|
257
|
+
else
|
258
|
+
z = @tokenizer_structure.get_next_token
|
259
|
+
|
260
|
+
if z.nil?
|
261
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
262
|
+
end
|
263
|
+
|
264
|
+
if z == ',' or z == ')'
|
265
|
+
#2D : no z no m
|
266
|
+
@factory.add_point_x_y(x.to_f,y.to_f)
|
267
|
+
z
|
268
|
+
else
|
269
|
+
m = @tokenizer_structure.get_next_token
|
270
|
+
if m.nil?
|
271
|
+
raise EWKTFormatError.new("EWKT string not correctly terminated")
|
272
|
+
end
|
273
|
+
|
274
|
+
if m == ',' or m ==')'
|
275
|
+
#3Dz : no m
|
276
|
+
@with_z = true
|
277
|
+
@factory.add_point_x_y_z(x.to_f,y.to_f,z.to_f)
|
278
|
+
m
|
279
|
+
else
|
280
|
+
#4D
|
281
|
+
@with_z = true
|
282
|
+
@with_m = true
|
283
|
+
@factory.add_point_x_y_z_m(x.to_f,y.to_f,z.to_f,m.to_f)
|
284
|
+
@tokenizer_structure.get_next_token
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
class TokenizerStructure
|
292
|
+
|
293
|
+
def initialize(ewkt)
|
294
|
+
@ewkt = ewkt
|
295
|
+
@scanner = StringScanner.new(ewkt)
|
296
|
+
@regex = /\s*([\w.-]+)s*/
|
297
|
+
end
|
298
|
+
|
299
|
+
def get_next_token
|
300
|
+
if @scanner.scan(@regex).nil?
|
301
|
+
if @scanner.eos?
|
302
|
+
nil
|
303
|
+
else
|
304
|
+
ch = @scanner.getch
|
305
|
+
while ch == ' '
|
306
|
+
ch = @scanner.getch
|
307
|
+
end
|
308
|
+
ch
|
309
|
+
end
|
310
|
+
else
|
311
|
+
@scanner[1]
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
|
316
|
+
def check_next_token
|
317
|
+
check = @scanner.check(@regex)
|
318
|
+
if check.nil?
|
319
|
+
if @scanner.eos?
|
320
|
+
nil
|
321
|
+
else
|
322
|
+
pos = @scanner.pos
|
323
|
+
while @ewkt[pos].chr == ' '
|
324
|
+
pos+=1
|
325
|
+
end
|
326
|
+
@ewkt[pos].chr
|
327
|
+
end
|
328
|
+
else
|
329
|
+
check
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'geo_ruby/simple_features/point'
|
2
|
+
require 'geo_ruby/simple_features/line_string'
|
3
|
+
require 'geo_ruby/simple_features/linear_ring'
|
4
|
+
require 'geo_ruby/simple_features/polygon'
|
5
|
+
require 'geo_ruby/simple_features/multi_point'
|
6
|
+
require 'geo_ruby/simple_features/multi_line_string'
|
7
|
+
require 'geo_ruby/simple_features/multi_polygon'
|
8
|
+
require 'geo_ruby/simple_features/geometry_collection'
|
9
|
+
|
10
|
+
|
11
|
+
module GeoRuby
|
12
|
+
module SimpleFeatures
|
13
|
+
module Io
|
14
|
+
#Creates a new geometry according to constructions received from a parser, for example EWKBParser.
|
15
|
+
class GeometryFactory
|
16
|
+
#the built geometry
|
17
|
+
attr_reader :geometry
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@geometry_stack = []
|
21
|
+
end
|
22
|
+
#resets the factory
|
23
|
+
def reset
|
24
|
+
@geometry_stack = []
|
25
|
+
end
|
26
|
+
#add a 2D point to the current geometry
|
27
|
+
def add_point_x_y(x,y)
|
28
|
+
@geometry_stack.last.set_x_y(x,y)
|
29
|
+
end
|
30
|
+
#add a 3D point to the current geometry
|
31
|
+
def add_point_x_y_z(x,y,z)
|
32
|
+
@geometry_stack.last.set_x_y_z(x,y,z)
|
33
|
+
end
|
34
|
+
#add a 2D point with M to the current geometry
|
35
|
+
def add_point_x_y_m(x,y,m)
|
36
|
+
@geometry_stack.last.set_x_y(x,y)
|
37
|
+
@geometry_stack.last.m=m
|
38
|
+
end
|
39
|
+
#add a 3D point with M to the current geometry
|
40
|
+
def add_point_x_y_z_m(x,y,z,m)
|
41
|
+
@geometry_stack.last.set_x_y_z(x,y,z)
|
42
|
+
@geometry_stack.last.m=m
|
43
|
+
end
|
44
|
+
#begin a geometry of type +geometry_type+
|
45
|
+
def begin_geometry(geometry_type,srid=DEFAULT_SRID)
|
46
|
+
geometry= geometry_type::new(srid)
|
47
|
+
@geometry= geometry if @geometry.nil?
|
48
|
+
@geometry_stack << geometry
|
49
|
+
end
|
50
|
+
#terminates the current geometry
|
51
|
+
def end_geometry(with_z=false,with_m=false)
|
52
|
+
@geometry=@geometry_stack.pop
|
53
|
+
@geometry.with_z=with_z
|
54
|
+
@geometry.with_m=with_m
|
55
|
+
#add the newly defined geometry to its parent if there is one
|
56
|
+
@geometry_stack.last << geometry if !@geometry_stack.empty?
|
57
|
+
end
|
58
|
+
#abort a geometry
|
59
|
+
def abort_geometry
|
60
|
+
reset
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/rakefile.rb
CHANGED
@@ -24,7 +24,7 @@ spec = Gem::Specification::new do |s|
|
|
24
24
|
s.platform = Gem::Platform::RUBY
|
25
25
|
|
26
26
|
s.name = 'GeoRuby'
|
27
|
-
s.version = "1.3.
|
27
|
+
s.version = "1.3.2"
|
28
28
|
s.summary = "Ruby data holder for OGC Simple Features"
|
29
29
|
s.description = <<EOF
|
30
30
|
GeoRuby is intended as a holder for data returned from PostGIS and MySQL Spatial queries. The data model roughly follows the OGC "Simple Features for SQL" specification (see www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections)
|
@@ -29,7 +29,7 @@ Here is an example of code for the creation of a table with a geometric column i
|
|
29
29
|
|
30
30
|
Here is a related statement valid for MySql version <= 5.0.16 :
|
31
31
|
ActiveRecord::Schema.define do
|
32
|
-
create_table "table_points",
|
32
|
+
create_table "table_points", ;options=>"ENGINE=MyISAM", :force => true do |t|
|
33
33
|
t.column "data", :string
|
34
34
|
t.column "geom", :point, :null=>false
|
35
35
|
end
|
@@ -63,11 +63,11 @@ For MySQL, it is slightly different since it does not support Z dimension or SRI
|
|
63
63
|
|
64
64
|
==== Fixtures
|
65
65
|
|
66
|
-
If you use fixtures for your unit tests, at some point, you will want to input a geometry. You could transform your geometries to a form suitable for YAML yourself everytime but the spatial adapter provides a method to do it for you: +
|
66
|
+
If you use fixtures for your unit tests, at some point, you will want to input a geometry. You could transform your geometries to a form suitable for YAML yourself everytime but the spatial adapter provides a method to do it for you: +to_yaml+. It works for both MySQL and PostGIS (although the string returned is different for each database). You would use it like this, if the geometric column is a point:
|
67
67
|
fixture:
|
68
68
|
id: 1
|
69
69
|
data: HELLO
|
70
|
-
geom: <%= Point.from_x_y(123.5,321.9).
|
70
|
+
geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>
|
71
71
|
|
72
72
|
==== Find_by
|
73
73
|
|
@@ -103,7 +103,7 @@ Ruby geometric datatypes are currently made available only through the GeoRuby l
|
|
103
103
|
- Support of M dimensions in migrations. The <tt>:dimension</tt> key in the column definition has disappeared and has been replaced by <tt>:with_z</tt> and <tt>:with_m</tt>.
|
104
104
|
- Addition of unit tests. At the plugin root, Run <tt>rake test:mysql</tt> to run the mysql tests and <tt>rake test:postgis</tt> for the postgis ones. You will need to configure your connection in <tt>test/db/database_mysql.yml</tt> and <tt>test/db/database_postgis.yml</tt>. If you get errors on your platform, please report to mailto:guilhem.vellut+georuby@gmail.com.
|
105
105
|
- Addition of a find_by methods with a special behaviour for geometries
|
106
|
-
- Addition of a
|
106
|
+
- Addition of a to_yaml method to use inside a YAML fixture
|
107
107
|
|
108
108
|
===TODO
|
109
109
|
- Support of other geometric datatype libraries in addition to GeoRuby
|
@@ -4,34 +4,66 @@ require 'common_spatial_adapter'
|
|
4
4
|
|
5
5
|
include GeoRuby::SimpleFeatures
|
6
6
|
|
7
|
-
|
8
|
-
#add a method to_fixture_format to the Geometry class which will transform a geometry in a form suitable to be used in a YAML file (such as in a fixture)
|
7
|
+
#add a method to_yaml to the Geometry class which will transform a geometry in a form suitable to be used in a YAML file (such as in a fixture)
|
9
8
|
GeoRuby::SimpleFeatures::Geometry.class_eval do
|
10
9
|
def to_fixture_format
|
11
10
|
"!binary | #{[(255.chr * 4) + as_wkb].pack('m')}"
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
14
|
ActiveRecord::Base.class_eval do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
arguments[idx]
|
27
|
-
|
15
|
+
require 'active_record/version'
|
16
|
+
|
17
|
+
#For Rails < 1.2
|
18
|
+
if ActiveRecord::VERSION::STRING < "1.15.1"
|
19
|
+
def self.construct_conditions_from_arguments(attribute_names, arguments)
|
20
|
+
conditions = []
|
21
|
+
attribute_names.each_with_index do |name, idx|
|
22
|
+
if columns_hash[name].is_a?(SpatialColumn)
|
23
|
+
#when the discriminating column is spatial, always use the MBRIntersects (bounding box intersection check) operator : the user can pass either a geometric object (which will be transformed to a string using the quote method of the database adapter) or an array with the corner points of a bounding box
|
24
|
+
if arguments[idx].is_a?(Array)
|
25
|
+
#using some georuby utility : The multipoint has a bbox whose corners are the 2 points passed as parameters : [ pt1, pt2]
|
26
|
+
arguments[idx]= MultiPoint.from_coordinates(arguments[idx])
|
27
|
+
elsif arguments[idx].is_a?(Envelope)
|
28
|
+
arguments[idx]= MultiPoint.from_points([arguments[idx].lower_corner,arguments[idx].upper_corner])
|
29
|
+
end
|
28
30
|
conditions << "MBRIntersects(?, #{table_name}.#{connection.quote_column_name(name)}) "
|
31
|
+
else
|
32
|
+
conditions << "#{table_name}.#{connection.quote_column_name(name)} #{attribute_condition(arguments[idx])} "
|
29
33
|
end
|
30
|
-
|
31
|
-
|
34
|
+
end
|
35
|
+
[ conditions.join(" AND "), *arguments[0...attribute_names.length] ]
|
36
|
+
end
|
37
|
+
|
38
|
+
else
|
39
|
+
def self.get_conditions(attrs)
|
40
|
+
attrs.map do |attr, value|
|
41
|
+
if columns_hash[attr].is_a?(SpatialColumn)
|
42
|
+
if value.is_a?(Array)
|
43
|
+
#using some georuby utility : The multipoint has a bbox whose corners are the 2 points passed as parameters : [ pt1, pt2]
|
44
|
+
attrs[attr]= MultiPoint.from_coordinates(value)
|
45
|
+
elsif value.is_a?(Envelope)
|
46
|
+
attrs[attr]= MultiPoint.from_points([value.lower_corner,value.upper_corner])
|
47
|
+
end
|
48
|
+
"MBRIntersects(?, #{table_name}.#{connection.quote_column_name(attr)}) "
|
49
|
+
else
|
50
|
+
#original stuff
|
51
|
+
"#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
|
52
|
+
end
|
53
|
+
end.join(' AND ')
|
54
|
+
end
|
55
|
+
if ActiveRecord::VERSION::STRING == "1.15.1"
|
56
|
+
def self.sanitize_sql_hash(attrs)
|
57
|
+
conditions = get_conditions(attrs)
|
58
|
+
replace_bind_variables(conditions, attrs.values)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
#For Rails >= 1.2
|
62
|
+
def self.sanitize_sql_hash(attrs)
|
63
|
+
conditions = get_conditions(attrs)
|
64
|
+
replace_bind_variables(conditions, expand_range_bind_variables(attrs.values))
|
32
65
|
end
|
33
66
|
end
|
34
|
-
[ conditions.join(" AND "), *arguments[0...attribute_names.length] ]
|
35
67
|
end
|
36
68
|
end
|
37
69
|
|
@@ -76,18 +108,10 @@ ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
|
|
76
108
|
#Redefines add_index to support the case where the index is spatial
|
77
109
|
#If the :spatial key in the options table is true, then the sql string for a spatial index is created
|
78
110
|
def add_index(table_name,column_name,options = {})
|
79
|
-
index_name = options[:name] ||
|
111
|
+
index_name = options[:name] || index_name(table_name,:column => Array(column_name))
|
80
112
|
|
81
113
|
if options[:spatial]
|
82
|
-
|
83
|
-
#one by one or error : Should raise exception instead? ; use default name even if name passed as argument
|
84
|
-
Array(column_name).each do |col|
|
85
|
-
execute "CREATE SPATIAL INDEX #{table_name}_#{col}_index ON #{table_name} (#{col})"
|
86
|
-
end
|
87
|
-
else
|
88
|
-
col = Array(column_name)[0]
|
89
|
-
execute "CREATE SPATIAL INDEX #{index_name} ON #{table_name} (#{col})"
|
90
|
-
end
|
114
|
+
execute "CREATE SPATIAL INDEX #{index_name} ON #{table_name} (#{Array(column_name).join(", ")})"
|
91
115
|
else
|
92
116
|
index_type = options[:unique] ? "UNIQUE" : ""
|
93
117
|
#all together
|
@@ -8,7 +8,7 @@ include GeoRuby::SimpleFeatures
|
|
8
8
|
ActiveRecord::SchemaDumper.ignore_tables << "spatial_ref_sys" << "geometry_columns"
|
9
9
|
|
10
10
|
|
11
|
-
#add a method
|
11
|
+
#add a method to_yaml to the Geometry class which will transform a geometry in a form suitable to be used in a YAML file (such as in a fixture)
|
12
12
|
GeoRuby::SimpleFeatures::Geometry.class_eval do
|
13
13
|
def to_fixture_format
|
14
14
|
as_hex_ewkb
|
@@ -17,24 +17,58 @@ end
|
|
17
17
|
|
18
18
|
|
19
19
|
ActiveRecord::Base.class_eval do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
arguments[idx]
|
20
|
+
require 'active_record/version'
|
21
|
+
|
22
|
+
#For Rails < 1.2
|
23
|
+
if ActiveRecord::VERSION::STRING < "1.15.1"
|
24
|
+
def self.construct_conditions_from_arguments(attribute_names, arguments)
|
25
|
+
conditions = []
|
26
|
+
attribute_names.each_with_index do |name, idx|
|
27
|
+
if columns_hash[name].is_a?(SpatialColumn)
|
28
|
+
#when the discriminating column is spatial, always use the && (bounding box intersection check) operator : the user can pass either a geometric object (which will be transformed to a string using the quote method of the database adapter) or an array representing 2 opposite corners of a bounding box
|
29
|
+
if arguments[idx].is_a?(Array)
|
30
|
+
bbox = arguments[idx]
|
31
|
+
conditions << "#{table_name}.#{connection.quote_column_name(name)} && SetSRID(?::box3d, #{bbox[2] || DEFAULT_SRID} ) "
|
32
|
+
#Could do without the ? and replace directly with the quoted BBOX3D but like this, the flow is the same everytime
|
33
|
+
arguments[idx]= "BOX3D(" + bbox[0].join(" ") + "," + bbox[1].join(" ") + ")"
|
34
|
+
else
|
35
|
+
conditions << "#{table_name}.#{connection.quote_column_name(name)} && ? "
|
36
|
+
end
|
30
37
|
else
|
31
|
-
conditions << "#{table_name}.#{connection.quote_column_name(name)}
|
38
|
+
conditions << "#{table_name}.#{connection.quote_column_name(name)} #{attribute_condition(arguments[idx])} "
|
32
39
|
end
|
33
|
-
|
34
|
-
|
40
|
+
end
|
41
|
+
[ conditions.join(" AND "), *arguments[0...attribute_names.length] ]
|
42
|
+
end
|
43
|
+
else
|
44
|
+
def self.get_conditions(attrs)
|
45
|
+
attrs.map do |attr, value|
|
46
|
+
if columns_hash[attr].is_a?(SpatialColumn)
|
47
|
+
if value.is_a?(Array)
|
48
|
+
attrs[attr]= "BOX3D(" + value[0].join(" ") + "," + value[1].join(" ") + ")"
|
49
|
+
"#{table_name}.#{connection.quote_column_name(attr)} && SetSRID(?::box3d, #{value[2] || DEFAULT_SRID} ) "
|
50
|
+
elsif value.is_a?(Envelope)
|
51
|
+
attrs[attr]= "BOX3D(" + value.lower_corner.text_representation + "," + value.upper_corner.text_representation + ")"
|
52
|
+
"#{table_name}.#{connection.quote_column_name(attr)} && SetSRID(?::box3d, #{value.srid} ) "
|
53
|
+
else
|
54
|
+
"#{table_name}.#{connection.quote_column_name(attr)} && ? "
|
55
|
+
end
|
56
|
+
else
|
57
|
+
"#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
|
58
|
+
end
|
59
|
+
end.join(' AND ')
|
60
|
+
end
|
61
|
+
if ActiveRecord::VERSION::STRING == "1.15.1"
|
62
|
+
def self.sanitize_sql_hash(attrs)
|
63
|
+
conditions = get_conditions(attrs)
|
64
|
+
replace_bind_variables(conditions, attrs.values)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
def self.sanitize_sql_hash(attrs)
|
68
|
+
conditions = get_conditions(attrs)
|
69
|
+
replace_bind_variables(conditions, expand_range_bind_variables(attrs.values))
|
35
70
|
end
|
36
71
|
end
|
37
|
-
[ conditions.join(" AND "), *arguments[0...attribute_names.length] ]
|
38
72
|
end
|
39
73
|
end
|
40
74
|
|
@@ -84,7 +118,7 @@ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
|
|
84
118
|
alias :original_remove_column :remove_column
|
85
119
|
def remove_column(table_name,column_name)
|
86
120
|
columns(table_name).each do |col|
|
87
|
-
if col.name
|
121
|
+
if col.name == column_name.to_s
|
88
122
|
#check if the column is geometric
|
89
123
|
unless geometry_data_types[col.type].nil?
|
90
124
|
execute "SELECT DropGeometryColumn('#{table_name}','#{column_name}')"
|
@@ -109,17 +143,9 @@ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
|
|
109
143
|
|
110
144
|
#Adds a GIST spatial index to a column. Its name will be <table_name>_<column_name>_spatial_index unless the key :name is present in the options hash, in which case its value is taken as the name of the index.
|
111
145
|
def add_index(table_name,column_name,options = {})
|
112
|
-
index_name = options[:name] ||
|
146
|
+
index_name = options[:name] || index_name(table_name,:column => Array(column_name))
|
113
147
|
if options[:spatial]
|
114
|
-
|
115
|
-
#one by one or error : Should raise exception instead? ; use default name even if name passed as argument
|
116
|
-
Array(column_name).each do |col|
|
117
|
-
execute "CREATE INDEX #{table_name}_#{col}_index ON #{table_name} USING GIST (#{col} GIST_GEOMETRY_OPS)"
|
118
|
-
end
|
119
|
-
else
|
120
|
-
col = Array(column_name)[0]
|
121
|
-
execute "CREATE INDEX #{index_name} ON #{table_name} USING GIST (#{col} GIST_GEOMETRY_OPS)"
|
122
|
-
end
|
148
|
+
execute "CREATE INDEX #{index_name} ON #{table_name} USING GIST (#{Array(column_name).join(", ")} GIST_GEOMETRY_OPS)"
|
123
149
|
else
|
124
150
|
index_type = options[:unique] ? "UNIQUE" : ""
|
125
151
|
#all together
|
@@ -11,7 +11,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
11
11
|
pt = TablePoint.new(:data => "Test", :geom => Point.from_x_y(1.2,4.5))
|
12
12
|
assert(pt.save)
|
13
13
|
|
14
|
-
pt = TablePoint.
|
14
|
+
pt = TablePoint.find(:first)
|
15
15
|
assert(pt)
|
16
16
|
assert_equal("Test",pt.data)
|
17
17
|
assert_equal(Point.from_x_y(1.2,4.5),pt.geom)
|
@@ -22,7 +22,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
22
22
|
ls = TableLineString.new(:value => 3, :geom => LineString.from_coordinates([[1.4,2.5],[1.5,6.7]]))
|
23
23
|
assert(ls.save)
|
24
24
|
|
25
|
-
ls = TableLineString.
|
25
|
+
ls = TableLineString.find(:first)
|
26
26
|
assert(ls)
|
27
27
|
assert_equal(3,ls.value)
|
28
28
|
assert_equal(LineString.from_coordinates([[1.4,2.5],[1.5,6.7]]),ls.geom)
|
@@ -33,7 +33,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
33
33
|
pg = TablePolygon.new(:geom => Polygon.from_coordinates([[[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],[[2.4,5.3],[5.4,1.4263],[14.46,1.06],[2.4,5.3]]]))
|
34
34
|
assert(pg.save)
|
35
35
|
|
36
|
-
pg = TablePolygon.
|
36
|
+
pg = TablePolygon.find(:first)
|
37
37
|
assert(pg)
|
38
38
|
assert_equal(Polygon.from_coordinates([[[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],[[2.4,5.3],[5.4,1.4263],[14.46,1.06],[2.4,5.3]]]),pg.geom)
|
39
39
|
end
|
@@ -42,7 +42,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
42
42
|
mp = TableMultiPoint.new(:geom => MultiPoint.from_coordinates([[12.4,-123.3],[-65.1,123.4],[123.55555555,123]]))
|
43
43
|
assert(mp.save)
|
44
44
|
|
45
|
-
mp = TableMultiPoint.
|
45
|
+
mp = TableMultiPoint.find(:first)
|
46
46
|
assert(mp)
|
47
47
|
assert_equal(MultiPoint.from_coordinates([[12.4,-123.3],[-65.1,123.4],[123.55555555,123]]),mp.geom)
|
48
48
|
end
|
@@ -51,7 +51,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
51
51
|
ml = TableMultiLineString.new(:geom => MultiLineString.from_line_strings([LineString.from_coordinates([[1.5,45.2],[-54.12312,-0.012]]),LineString.from_coordinates([[1.5,45.2],[-54.12312,-0.012],[45.123,123.3]])]))
|
52
52
|
assert(ml.save)
|
53
53
|
|
54
|
-
ml = TableMultiLineString.
|
54
|
+
ml = TableMultiLineString.find(:first)
|
55
55
|
assert(ml)
|
56
56
|
assert_equal(MultiLineString.from_line_strings([LineString.from_coordinates([[1.5,45.2],[-54.12312,-0.012]]),LineString.from_coordinates([[1.5,45.2],[-54.12312,-0.012],[45.123,123.3]])]),ml.geom)
|
57
57
|
end
|
@@ -60,7 +60,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
60
60
|
mp = TableMultiPolygon.new( :geom => MultiPolygon.from_polygons([Polygon.from_coordinates([[[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],[[2.4,5.3],[5.4,1.4263],[14.46,1.06],[2.4,5.3]]]),Polygon.from_coordinates([[[0,0],[4,0],[4,4],[0,4],[0,0]],[[1,1],[3,1],[3,3],[1,3],[1,1]]])]))
|
61
61
|
assert(mp.save)
|
62
62
|
|
63
|
-
mp = TableMultiPolygon.
|
63
|
+
mp = TableMultiPolygon.find(:first)
|
64
64
|
assert(mp)
|
65
65
|
assert_equal(MultiPolygon.from_polygons([Polygon.from_coordinates([[[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],[[2.4,5.3],[5.4,1.4263],[14.46,1.06],[2.4,5.3]]]),Polygon.from_coordinates([[[0,0],[4,0],[4,4],[0,4],[0,0]],[[1,1],[3,1],[3,3],[1,3],[1,1]]])]),mp.geom)
|
66
66
|
end
|
@@ -69,7 +69,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
69
69
|
gm = TableGeometry.new(:geom => LineString.from_coordinates([[12.4,-45.3],[45.4,41.6],[4.456,1.0698]]))
|
70
70
|
assert(gm.save)
|
71
71
|
|
72
|
-
gm = TableGeometry.
|
72
|
+
gm = TableGeometry.find(:first)
|
73
73
|
assert(gm)
|
74
74
|
assert_equal(LineString.from_coordinates([[12.4,-45.3],[45.4,41.6],[4.456,1.0698]]),gm.geom)
|
75
75
|
end
|
@@ -78,7 +78,7 @@ class AccessMysqlTest < Test::Unit::TestCase
|
|
78
78
|
gc = TableGeometryCollection.new(:geom => GeometryCollection.from_geometries([Point.from_x_y(4.67,45.4),LineString.from_coordinates([[5.7,12.45],[67.55,54]])]))
|
79
79
|
assert(gc.save)
|
80
80
|
|
81
|
-
gc = TableGeometryCollection.
|
81
|
+
gc = TableGeometryCollection.find(:first)
|
82
82
|
assert(gc)
|
83
83
|
assert_equal(GeometryCollection.from_geometries([Point.from_x_y(4.67,45.4),LineString.from_coordinates([[5.7,12.45],[67.55,54]])]),gc.geom)
|
84
84
|
end
|
@@ -71,16 +71,15 @@ class MigrationMysqlTest < Test::Unit::TestCase
|
|
71
71
|
assert_equal(0,connection.indexes("parks").length) #index on id does not count
|
72
72
|
|
73
73
|
ActiveRecord::Schema.define() do
|
74
|
-
add_index "parks","geom",:spatial=>true
|
74
|
+
add_index "parks","geom",:spatial=>true
|
75
75
|
end
|
76
76
|
|
77
77
|
#TEST
|
78
78
|
assert_equal(1,connection.indexes("parks").length)
|
79
79
|
assert(connection.indexes("parks")[0].spatial)
|
80
|
-
|
81
|
-
|
80
|
+
|
82
81
|
ActiveRecord::Schema.define() do
|
83
|
-
remove_index "parks"
|
82
|
+
remove_index "parks","geom"
|
84
83
|
end
|
85
84
|
|
86
85
|
#TEST
|
@@ -77,21 +77,39 @@ class MigrationPostgisTest < Test::Unit::TestCase
|
|
77
77
|
assert_equal(0,connection.indexes("parks").length) #index on id does not count
|
78
78
|
|
79
79
|
ActiveRecord::Schema.define do
|
80
|
-
add_index "parks","geom",:spatial=>true
|
80
|
+
add_index "parks","geom",:spatial=>true
|
81
81
|
end
|
82
82
|
|
83
83
|
#TEST
|
84
84
|
assert_equal(1,connection.indexes("parks").length)
|
85
85
|
assert(connection.indexes("parks")[0].spatial)
|
86
|
-
|
87
|
-
|
86
|
+
|
88
87
|
ActiveRecord::Schema.define do
|
89
|
-
remove_index "parks"
|
88
|
+
remove_index "parks", "geom"
|
90
89
|
end
|
91
90
|
|
92
91
|
#TEST
|
93
92
|
assert_equal(0,connection.indexes("parks").length)
|
94
93
|
|
94
|
+
ActiveRecord::Schema.define do
|
95
|
+
remove_column "parks","geom2"
|
96
|
+
end
|
97
|
+
|
98
|
+
#testing with point
|
99
|
+
ActiveRecord::Schema.define do
|
100
|
+
add_column "parks","geom2", :point
|
101
|
+
end
|
102
|
+
|
103
|
+
ActiveRecord::Schema.define do
|
104
|
+
add_index "parks","geom2",:spatial=>true,:name => "example_spatial_index"
|
105
|
+
end
|
106
|
+
|
107
|
+
#TEST
|
108
|
+
assert_equal(1,connection.indexes("parks").length)
|
109
|
+
assert(connection.indexes("parks")[0].spatial)
|
110
|
+
assert_equal("example_spatial_index",connection.indexes("parks")[0].name)
|
111
|
+
|
112
|
+
|
95
113
|
end
|
96
114
|
|
97
115
|
def test_keyword_column_name
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: GeoRuby
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.3.
|
7
|
-
date: 2007-
|
6
|
+
version: 1.3.2
|
7
|
+
date: 2007-09-14 00:00:00 +02:00
|
8
8
|
summary: Ruby data holder for OGC Simple Features
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,7 +29,6 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Guilhem Vellut
|
31
31
|
files:
|
32
|
-
- lib/geo_ruby.rb
|
33
32
|
- lib/geo_ruby/shp4r/dbf.rb
|
34
33
|
- lib/geo_ruby/shp4r/shp.rb
|
35
34
|
- lib/geo_ruby/simple_features/envelope.rb
|
@@ -40,6 +39,9 @@ files:
|
|
40
39
|
- lib/geo_ruby/simple_features/geometry_factory.rb
|
41
40
|
- lib/geo_ruby/simple_features/georss_parser.rb
|
42
41
|
- lib/geo_ruby/simple_features/helper.rb
|
42
|
+
- lib/geo_ruby/simple_features/io/ewkb_parser.rb
|
43
|
+
- lib/geo_ruby/simple_features/io/ewkt_parser.rb
|
44
|
+
- lib/geo_ruby/simple_features/io/geometry_factory.rb
|
43
45
|
- lib/geo_ruby/simple_features/linear_ring.rb
|
44
46
|
- lib/geo_ruby/simple_features/line_string.rb
|
45
47
|
- lib/geo_ruby/simple_features/multi_line_string.rb
|
@@ -47,6 +49,7 @@ files:
|
|
47
49
|
- lib/geo_ruby/simple_features/multi_polygon.rb
|
48
50
|
- lib/geo_ruby/simple_features/point.rb
|
49
51
|
- lib/geo_ruby/simple_features/polygon.rb
|
52
|
+
- lib/geo_ruby.rb
|
50
53
|
- test/test_ewkb_parser.rb
|
51
54
|
- test/test_ewkt_parser.rb
|
52
55
|
- test/test_georss_kml.rb
|
@@ -60,38 +63,35 @@ files:
|
|
60
63
|
- test/data/point.shp
|
61
64
|
- test/data/polygon.shp
|
62
65
|
- test/data/polyline.shp
|
63
|
-
- test/data/polyline2.shp
|
64
66
|
- test/data/multipoint.dbf
|
65
67
|
- test/data/point.dbf
|
66
68
|
- test/data/polygon.dbf
|
67
69
|
- test/data/polyline.dbf
|
68
|
-
- test/data/polyline2.dbf
|
69
70
|
- test/data/multipoint.shx
|
70
71
|
- test/data/point.shx
|
71
72
|
- test/data/polygon.shx
|
72
73
|
- test/data/polyline.shx
|
73
|
-
- test/data/polyline2.shx
|
74
74
|
- tools/db.yml
|
75
75
|
- tools/lib/spatial_adapter/test/db/database_mysql.yml
|
76
76
|
- tools/lib/spatial_adapter/test/db/database_postgis.yml
|
77
|
-
- tools/shp2sql.rb
|
78
77
|
- tools/lib/spatial_adapter/init.rb
|
79
|
-
- tools/lib/spatial_adapter/rakefile.rb
|
80
78
|
- tools/lib/spatial_adapter/lib/common_spatial_adapter.rb
|
81
79
|
- tools/lib/spatial_adapter/lib/mysql_spatial_adapter.rb
|
82
80
|
- tools/lib/spatial_adapter/lib/post_gis_adapter.rb
|
81
|
+
- tools/lib/spatial_adapter/rakefile.rb
|
83
82
|
- tools/lib/spatial_adapter/test/access_mysql_test.rb
|
84
83
|
- tools/lib/spatial_adapter/test/access_postgis_test.rb
|
84
|
+
- tools/lib/spatial_adapter/test/common/common_mysql.rb
|
85
|
+
- tools/lib/spatial_adapter/test/common/common_postgis.rb
|
85
86
|
- tools/lib/spatial_adapter/test/find_mysql_test.rb
|
86
87
|
- tools/lib/spatial_adapter/test/find_postgis_test.rb
|
87
88
|
- tools/lib/spatial_adapter/test/migration_mysql_test.rb
|
88
89
|
- tools/lib/spatial_adapter/test/migration_postgis_test.rb
|
89
|
-
- tools/lib/spatial_adapter/test/common/common_mysql.rb
|
90
|
-
- tools/lib/spatial_adapter/test/common/common_postgis.rb
|
91
90
|
- tools/lib/spatial_adapter/test/models/models_mysql.rb
|
92
91
|
- tools/lib/spatial_adapter/test/models/models_postgis.rb
|
93
92
|
- tools/lib/spatial_adapter/test/schema/schema_mysql.rb
|
94
93
|
- tools/lib/spatial_adapter/test/schema/schema_postgis.rb
|
94
|
+
- tools/shp2sql.rb
|
95
95
|
- tools/lib/spatial_adapter
|
96
96
|
- tools/lib/spatial_adapter/lib
|
97
97
|
- tools/lib/spatial_adapter/MIT-LICENSE
|
data/test/data/polyline2.dbf
DELETED
Binary file
|
data/test/data/polyline2.shp
DELETED
Binary file
|
data/test/data/polyline2.shx
DELETED
Binary file
|