GeoRuby 1.3.1 → 1.3.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.
- 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
|