GeoRuby 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,5 +1,5 @@
1
1
  =GeoRuby
2
- This is GeoRuby 0.1.1. It is intended as a holder for data returned from PostGIS and the Spatial Extensions of MySql. The data model roughly follows the OGC "Simple Features for SQL" specification (see http://www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections).
2
+ This is GeoRuby 0.2.1. It is intended as a holder for data returned from PostGIS and the Spatial Extensions of MySql. The data model roughly follows the OGC "Simple Features for SQL" specification (see http://www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections).
3
3
 
4
4
  ===Available data types
5
5
  The following geometric data types are provided :
@@ -15,18 +15,16 @@ The following geometric data types are provided :
15
15
  They can be in 2D, 3DZ, 3DM, and 4D.
16
16
 
17
17
  ===Input and output
18
- These geometries can be input and output in WKB/EWKB/WKT/EWKT format (as well as the related HexWKB and HexEWKB formats). HexEWKB and EWKB are the default form under which geometric data is returned respectively from PostGIS and MySql.
18
+ These geometries can be input and output in WKB/EWKB/WKT/EWKT format (as well as the related HexWKB and HexEWKB formats). HexEWKB and WKB are the default form under which geometric data is returned respectively from PostGIS and MySql.
19
19
 
20
20
  ===Installation
21
21
  To install the latest version, just type :
22
22
  gem install GeoRuby
23
23
 
24
24
  ===Changes since the last version
25
- - Addition of support for M and Z dimension in the data types, as well as in the EWKB and EWKT parsers.
26
- - When creating a geometry, the presence of a Z or M dimension must be indicated. By default, the geometry is created in 2D and with a SRID of -1.
27
- - Suppression of +as_binary+, +as_hex_binary+ and +as_text+. They have been replaced with +as_ewkb+, +as_wkb+, +as_hex_ewkb+, +as_hex_wkb+, +as_ewkt+ and +as_wkt+.
28
- - Suppression of the static creation methods +from_raw_point_sequence+ (for some geometric types) and +from_raw_point_sequences+ (for other), to build a geometry from a list of point coordinates. They have been replaced by a +from_coordinates+ for all types.
29
- - The static geometry construction method +from_hexewkb+ has been replaced with +from_hex_ewkb+.
25
+ - Correction of the output of the MultiPoint EWKT string to follow the specification, instead of what is shown in the examples (of the specification) and output by PostGIS. For example, the string previously output as MULTIPOINT(123.4 123.5,456.7 678.887) will now be output as MULTIPOINT((123.4 123.5),(456.7 678.887))
26
+ - Modification of the EWKT input to support the correct MultiPoint EWKT format, on top of the previous one. So both MULTIPOINT(123.4 123.5,456.7 678.887) and MULTIPOINT((123.4 123.5),(456.7 678.887)) would be accepted as valid MultiPoint strings.
27
+ - Addition of a +bounding_box+ method on geometries. Return an array of 2 points representing the 2 corners of the box.
30
28
 
31
29
  ===License
32
30
  GeoRuby is released under the MIT license.
@@ -10,6 +10,7 @@ require 'geo_ruby/simple_features/geometry_collection'
10
10
  module GeoRuby
11
11
  module SimpleFeatures
12
12
 
13
+ #Raised when an error in the EWKB string is detected
13
14
  class EWKBFormatError < StandardError
14
15
  end
15
16
 
@@ -20,6 +21,8 @@ module GeoRuby
20
21
  # ewkb_parser = EWKBParser::new(factory)
21
22
  # ewkb_parser.parse(<EWKB String>)
22
23
  # geometry = @factory.geometry
24
+ #
25
+ #You can also use directly the static method Geometry.from_ewkb
23
26
  class EWKBParser
24
27
 
25
28
  def initialize(factory)
@@ -12,6 +12,7 @@ require 'strscan'
12
12
  module GeoRuby
13
13
  module SimpleFeatures
14
14
 
15
+ #Raised when an error in the EWKT string is detected
15
16
  class EWKTFormatError < StandardError
16
17
  end
17
18
 
@@ -22,6 +23,8 @@ module GeoRuby
22
23
  # ewkt_parser = EWKTParser::new(factory)
23
24
  # ewkt_parser.parse(<EWKT String>)
24
25
  # geometry = @factory.geometry
26
+ #
27
+ #You can also use directly the static method Geometry.from_ewkt
25
28
  class EWKTParser
26
29
 
27
30
  def initialize(factory)
@@ -40,125 +43,294 @@ module GeoRuby
40
43
  #Parses the ewkt string passed as argument and notifies the factory of events
41
44
  def parse(ewkt)
42
45
  @factory.reset
46
+ @tokenizer_structure = TokenizerStructure.new(ewkt)
43
47
  @with_z=false
44
48
  @with_m=false
45
- parse_geometry(ewkt)
49
+ @is_3dm = false
50
+ parse_geometry(true)
46
51
  @srid=nil
47
52
  end
48
53
 
49
54
  private
50
- def parse_geometry(ewkt)
51
- scanner = StringScanner.new(ewkt)
52
- if scanner.scan(/SRID=(-?\d+);/)
53
- if @srid.nil?
54
- @srid = scanner[1].to_i
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")
55
63
  else
56
- #not the root geometry and repeat of the SRID : shouldn't happen
57
- raise EWKTFormatError.new("SRID in internal geometry")
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
58
67
  end
68
+
59
69
  else
60
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
61
71
  @srid= @srid || DEFAULT_SRID
72
+ geom_type = token
62
73
  end
63
74
 
64
- if scanner.scan(/(\w+)/)
65
- geom_type = scanner[1]
66
- if geom_type[-1] == ?M
67
- @with_m=true
68
- geom_type.chop! #remove the M
69
- end
70
- #change the parsing method : this one really is ugly...
71
- if @parse_options.has_key?(geom_type) and scanner.scan(/^\((.*)\)$/)
72
- @parse_options[geom_type].call(scanner[1])
73
- else
74
- raise EWKTFormatError.new("Bad token")
75
- end
75
+ if geom_type[-1] == ?M
76
+ @is_3dm=true
77
+ @with_m=true
78
+ geom_type.chop! #remove the M
76
79
  end
77
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
78
86
  end
79
- def parse_geometry_collection(string)
87
+
88
+ def parse_geometry_collection
89
+ if @tokenizer_structure.get_next_token !='('
90
+ raise EWKTFormatError.new('Invalid GeometryCollection')
91
+ end
92
+
80
93
  @factory.begin_geometry(GeometryCollection,@srid)
81
- scanner = StringScanner.new(string)
82
- while(scanner.scan(/\s*(.*?),\s*(?=[A-Z])/))
83
- parse_geometry(scanner[1])
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
84
102
  end
85
- parse_geometry(scanner.rest)
103
+
86
104
  @factory.end_geometry(@with_z,@with_m)
87
105
  end
88
106
 
89
- def parse_multi_polygon(string)
107
+ def parse_multi_polygon
108
+ if @tokenizer_structure.get_next_token !='('
109
+ raise EWKTFormatError.new('Invalid MultiLineString')
110
+ end
111
+
90
112
  @factory.begin_geometry(MultiPolygon,@srid)
91
- scanner = StringScanner.new(string)
92
- while(scanner.scan(/\s*\(\s*(\((.*?)\))\s*\)\s*,?/)) #beeeh
93
- parse_polygon(scanner[1])
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
94
120
  end
121
+
95
122
  @factory.end_geometry(@with_z,@with_m)
96
123
  end
97
124
 
98
- def parse_multi_line_string(string)
125
+ def parse_multi_line_string
126
+ if @tokenizer_structure.get_next_token !='('
127
+ raise EWKTFormatError.new('Invalid MultiLineString')
128
+ end
129
+
99
130
  @factory.begin_geometry(MultiLineString,@srid)
100
- scanner = StringScanner.new(string)
101
131
 
102
- while(scanner.scan(/\s*\(([^\)]*)\)\s*,?/))
103
- parse_line_string(scanner[1])
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
104
139
  end
140
+
105
141
  @factory.end_geometry(@with_z,@with_m)
106
142
  end
107
143
 
108
- def parse_polygon(string)
144
+ def parse_polygon
145
+ if @tokenizer_structure.get_next_token !='('
146
+ raise EWKTFormatError.new('Invalid Polygon')
147
+ end
148
+
109
149
  @factory.begin_geometry(Polygon,@srid)
110
- scanner = StringScanner.new(string)
111
- while(scanner.scan(/\s*\(([^\)]*)\)\s*,?/))
112
- parse_linear_ring(scanner[1])
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
113
158
  end
159
+
114
160
  @factory.end_geometry(@with_z,@with_m)
115
161
  end
116
-
117
- def parse_multi_point(string)
118
- parse_point_list(MultiPoint,string)
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
119
188
  end
120
- def parse_linear_ring(string)
121
- parse_point_list(LinearRing,string)
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)
122
196
  end
123
- def parse_line_string(string)
124
- parse_point_list(LineString,string)
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)
125
204
  end
126
- #used to parse line_strings and linear_rings and multi_points
127
- def parse_point_list(geometry_type,string)
205
+
206
+ #used to parse line_strings and linear_rings and the PostGIS form of multi_points
207
+ def parse_point_list(geometry_type)
128
208
  @factory.begin_geometry(geometry_type,@srid)
129
- scanner = StringScanner.new(string)
130
- while(scanner.scan(/([^,]*),?/))
131
- parse_point(scanner[1])
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)
132
218
  end
219
+
133
220
  @factory.end_geometry(@with_z,@with_m)
134
221
  end
135
222
 
136
- def parse_point(string)
223
+ def parse_point
224
+ if @tokenizer_structure.get_next_token !='('
225
+ raise EWKTFormatError.new('Invalid Point')
226
+ end
227
+
137
228
  @factory.begin_geometry(Point,@srid)
138
- scanner = StringScanner.new(string)
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
139
240
  coords = Array.new
140
- while scanner.scan(/\s*([-+]?[\d.]+)\s*/)
141
- coords << scanner[1].to_f
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")
142
246
  end
143
247
 
144
- if coords.length == 2
145
- @factory.add_point_x_y(*coords)
146
- elsif coords.length == 3
147
- if @with_m
148
- @factory.add_point_x_y_m(*coords)
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")
149
253
  else
150
- @with_z=true #we know if it is 3dz only when reading the first point
151
- @factory.add_point_x_y_z(*coords)
254
+ @factory.add_point_x_y_m(x.to_f,y.to_f,m.to_f)
255
+ @tokenizer_structure.get_next_token
152
256
  end
153
257
  else
154
- @with_m=true
155
- @with_z=true
156
- @factory.add_point_x_y_z_m(*coords)
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
157
287
  end
158
-
159
- @factory.end_geometry(@with_z,@with_m)
160
288
  end
161
289
  end
162
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
+
333
+ end
334
+
163
335
  end
164
336
  end
@@ -10,46 +10,27 @@ module GeoRuby
10
10
  super(srid,with_z,with_m)
11
11
  @geometries = []
12
12
  end
13
- #add a geometry to the collection
14
- def <<(geometry)
15
- @geometries << geometry
16
- end
17
- #add geometries to the collection
18
- def concat(geometries)
19
- @geometries.concat geometries
20
- end
21
- #number of geometries in the collection
22
- def length
23
- @geometries.length
24
- end
25
- #gets the nth geometry
26
- def [](n)
27
- @geometries[n]
28
- end
29
- #replaces the nth geometry
30
- def []=(n,geometry)
31
- @geometries[n]=geometry
32
- end
33
- #iterates over all the geometries
34
- def each(&proc)
35
- @geometries.each(&proc)
36
- end
37
- #iterates over all the geometries, passing the index to the bloc
38
- def each_index(&proc)
39
- @geometries.each_index(&proc)
40
- end
41
- #inserts geometries at the nth position
42
- def insert(n,*geometry)
43
- @geometries.insert(n,*geometry)
44
- end
45
- #index of the geometry
46
- def index(geometry)
47
- @geometries.index(geometry)
13
+
14
+ #Delegate the unknown methods to the geometries array
15
+ def method_missing(method_name,*args,&b)
16
+ @geometries.send(method_name,*args,&b)
48
17
  end
49
- #remove a slice of the collection
50
- def remove(*slice)
51
- @geometries.slice(*slice)
18
+
19
+ #Bounding box in 2D. Returns an array of 2 points
20
+ def bounding_box
21
+ max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
22
+ each do |geometry|
23
+ bbox = geometry.bounding_box
24
+ sw = bbox[0]
25
+ ne = bbox[1]
26
+ max_y = ne.y if ne.y > max_y
27
+ min_y = sw.y if sw.y < min_y
28
+ max_x = ne.x if ne.x > max_x
29
+ min_x = sw.x if sw.x < min_x
30
+ end
31
+ [Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
52
32
  end
33
+
53
34
  #tests the equality of geometry collections
54
35
  def ==(other_collection)
55
36
  if(other_collection.class != self.class)
@@ -11,50 +11,28 @@ module GeoRuby
11
11
  super(srid,with_z,with_m)
12
12
  @points=[]
13
13
  end
14
+
15
+ #Delegate the unknown methods to the points array
16
+ def method_missing(method_name,*args,&b)
17
+ @points.send(method_name,*args,&b)
18
+ end
19
+
14
20
  #tests if the line string is closed
15
21
  def is_closed
16
22
  #a bit naive...
17
23
  @points.first == @points.last
18
24
  end
19
- #add a point to the end of the line string
20
- def <<(point)
21
- @points << point
22
- end
23
- #add points to the end of the line string
24
- def concat(points)
25
- @points.concat points
26
- end
27
- #number of points of the line string
28
- def length
29
- @points.length
30
- end
31
- #accesses the nth point in the line string
32
- def [](n)
33
- @points[n]
34
- end
35
- #replaces the nth point in the line string
36
- def []=(n,point)
37
- @points[n]=point
38
- end
39
- #iterates over the points in the line string
40
- def each(&proc)
41
- @points.each(&proc)
42
- end
43
- #iterates over the points, passing their indices to the bloc
44
- def each_index(&proc)
45
- @points.each_index(&proc)
46
- end
47
- #inserts points at the nth position
48
- def insert(n,*point)
49
- @points.insert(n,*point)
50
- end
51
- #gets the indices of point
52
- def index(point)
53
- @points.index(point)
54
- end
55
- #Removes a slice of points
56
- def remove(*slice)
57
- @points.slice(*slice)
25
+
26
+ #Bounding box in 2D. Returns an array of 2 points
27
+ def bounding_box
28
+ max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
29
+ each do |point|
30
+ max_y = point.y if point.y > max_y
31
+ min_y = point.y if point.y < min_y
32
+ max_x = point.x if point.x > max_x
33
+ min_x = point.x if point.x < min_x
34
+ end
35
+ [Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
58
36
  end
59
37
 
60
38
  #Tests the equality of line strings
@@ -15,7 +15,7 @@ module GeoRuby
15
15
 
16
16
  #Text representation of a MultiPoint
17
17
  def text_representation(allow_z=true,allow_m=true)
18
- @geometries.collect{|point| point.text_representation(allow_z,allow_m)}.join(",")
18
+ "(" + @geometries.collect{|point| point.text_representation(allow_z,allow_m)}.join("),(") + ")"
19
19
  end
20
20
  #WKT geoemtry type
21
21
  def text_geometry_type
@@ -25,6 +25,12 @@ module GeoRuby
25
25
  @x=x
26
26
  @y=y
27
27
  end
28
+
29
+ #Bounding box in 2D. Returns an array of 2 points
30
+ def bounding_box
31
+ [Point.from_x_y(@x,@y),Point.from_x_y(@x,@y)] #not too difficult...
32
+ end
33
+
28
34
  #tests the equality of the position of points + m
29
35
  def ==(other_point)
30
36
  if other_point.class != self.class
@@ -11,46 +11,17 @@ module GeoRuby
11
11
  super(srid,with_z,with_m)
12
12
  @rings = []
13
13
  end
14
- #add one to the polygon
15
- def <<(ring)
16
- @rings << ring
17
- end
18
- #add one or more rings to the polygon
19
- def concat(rings)
20
- @rings.concat rings
21
- end
22
- #number of linear rings in the polygon
23
- def length
24
- @rings.length
25
- end
26
- #access the nth linear ring
27
- def [](n)
28
- @rings[n]
29
- end
30
- #modifies the value of the nth linear ring
31
- def []=(n,ring)
32
- @rings[n]=ring
33
- end
34
- #iterates over the linear rings
35
- def each(&proc)
36
- @rings.each(&proc)
37
- end
38
- #iterates over the linear rings, passing their indices to the bloc
39
- def each_index(&proc)
40
- @rings.each_index(&proc)
41
- end
42
- #insert linear rings at the nth position
43
- def insert(n,*ring)
44
- @rings.insert(n,*ring)
45
- end
46
- #index of the linear_ring
47
- def index(ring)
48
- @rings.index(ring)
14
+
15
+ #Delegate the unknown methods to the rings array
16
+ def method_missing(method_name,*args,&b)
17
+ @rings.send(method_name,*args,&b)
49
18
  end
50
- #remove linear rings. Arguments can be of the same type as Array#slice
51
- def remove(*slice)
52
- @rings.slice(*slice)
19
+
20
+ #Bounding box in 2D. Returns an array of 2 points
21
+ def bounding_box
22
+ @rings[0].bounding_box
53
23
  end
24
+
54
25
  #tests for other equality. The SRID is not taken into account.
55
26
  def ==(other_polygon)
56
27
  if other_polygon.class != self.class or
data/rakefile.rb CHANGED
@@ -13,7 +13,7 @@ end
13
13
 
14
14
  desc "Generate the documentation"
15
15
  Rake::RDocTask::new do |rdoc|
16
- rdoc.rdoc_dir = 'doc/'
16
+ rdoc.rdoc_dir = 'georuby-doc/'
17
17
  rdoc.title = "GeoRuby Documentation"
18
18
  rdoc.options << '--line-numbers' << '--inline-source'
19
19
  rdoc.rdoc_files.include('README')
@@ -24,10 +24,10 @@ spec = Gem::Specification::new do |s|
24
24
  s.platform = Gem::Platform::RUBY
25
25
 
26
26
  s.name = 'GeoRuby'
27
- s.version = "0.1.1"
27
+ s.version = "0.2.1"
28
28
  s.summary = "Ruby data holder for OGC Simple Features"
29
29
  s.description = <<EOF
30
- GeoRuby is intended as a holder for data returned from PostGIS queries. Therefore, 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)
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)
31
31
  EOF
32
32
  s.author = 'Guilhem Vellut'
33
33
  s.email = 'guilhem.vellut+georuby@gmail.com'
@@ -92,7 +92,7 @@ class TestEWKTParser < Test::Unit::TestCase
92
92
  assert(polygon.instance_of?(Polygon))
93
93
  assert_equal(Polygon.from_coordinates([[[0,0],[4,0],[4,4],[0,4],[0,0]],[[1,1],[3,1],[3,3],[1,3],[1,1]]],256),polygon)
94
94
 
95
- @ewkt_parser.parse("SRID=256;POLYGON((0 0 2,4 0 2,4 4 2,0 4 2,0 0 2),(1 1 2,3 1 2,3 3 2,1 3 2,1 1 2))")
95
+ @ewkt_parser.parse("SRID=256;POLYGON( ( 0 0 2,4 0 2,4 4 2,0 4 2,0 0 2),(1 1 2,3 1 2,3 3 2,1 3 2,1 1 2))")
96
96
  polygon = @factory.geometry
97
97
  assert(polygon.instance_of?(Polygon))
98
98
  assert_equal(Polygon.from_coordinates([[[0,0,2],[4,0,2],[4,4,2],[0,4,2],[0,0,2]],[[1,1,2],[3,1,2],[3,3,2],[1,3,2],[1,1,2]]],256,true),polygon)
@@ -112,6 +112,7 @@ class TestEWKTParser < Test::Unit::TestCase
112
112
  end
113
113
 
114
114
  def test_multi_point
115
+ #Form output by the current version of PostGIS. Future versions will output the one in the specification
115
116
  @ewkt_parser.parse("SRID=444;MULTIPOINT(12.4 -123.3,-65.1 123.4,123.55555555 123)")
116
117
  multi_point = @factory.geometry
117
118
  assert(multi_point.instance_of?(MultiPoint))
@@ -125,6 +126,14 @@ class TestEWKTParser < Test::Unit::TestCase
125
126
  assert_equal(MultiPoint.from_coordinates([[12.4,-123.3,4.5],[-65.1,123.4,6.7],[123.55555555,123,7.8]],444,true),multi_point)
126
127
  assert_equal(444,multi_point.srid)
127
128
  assert_equal(444,multi_point[0].srid)
129
+
130
+ #Form in the EWKT specification (from the OGC)
131
+ @ewkt_parser.parse("SRID=444;MULTIPOINT( ( 12.4 -123.3 4.5 ) , (-65.1 123.4 6.7),(123.55555555 123 7.8))")
132
+ multi_point = @factory.geometry
133
+ assert(multi_point.instance_of?(MultiPoint))
134
+ assert_equal(MultiPoint.from_coordinates([[12.4,-123.3,4.5],[-65.1,123.4,6.7],[123.55555555,123,7.8]],444,true),multi_point)
135
+ assert_equal(444,multi_point.srid)
136
+ assert_equal(444,multi_point[0].srid)
128
137
  end
129
138
 
130
139
  def test_multi_line_string
@@ -82,6 +82,11 @@ class TestSimpleFeatures < Test::Unit::TestCase
82
82
  assert_equal(-3.4,point.z)
83
83
  assert_equal(15,point.m)
84
84
  assert_equal(123,point.srid)
85
+
86
+ bbox = Point.from_x_y_z_m(-1.6,2.8,-3.4,15,123).bounding_box
87
+ assert_equal(2,bbox.length)
88
+ assert_equal(Point.from_x_y(-1.6,2.8),bbox[0])
89
+ assert_equal(Point.from_x_y(-1.6,2.8),bbox[1])
85
90
  end
86
91
 
87
92
  def test_point_equal
@@ -174,6 +179,11 @@ class TestSimpleFeatures < Test::Unit::TestCase
174
179
  assert_equal(3,line_string.length)
175
180
  assert_equal(Point.from_x_y_z(12.4,-45.3,123,123),line_string[0])
176
181
 
182
+ bbox = LineString.from_coordinates([[12.4,-45.3,123],[45.4,41.6,333],[4.456,1.0698,987]],123,true).bounding_box
183
+ assert_equal(2,bbox.length)
184
+ assert_equal(Point.from_x_y(4.456,-45.3),bbox[0])
185
+ assert_equal(Point.from_x_y(45.4,41.6),bbox[1])
186
+
177
187
  end
178
188
 
179
189
  def test_line_string_equal
@@ -260,7 +270,11 @@ class TestSimpleFeatures < Test::Unit::TestCase
260
270
  assert_equal(linear_ring1,polygon[0])
261
271
  assert_equal(linear_ring2,polygon[1])
262
272
 
263
-
273
+ bbox = Polygon.from_coordinates([[[12.4,-45.3,15.2],[45.4,41.6,2.4],[4.456,1.0698,5.6],[12.4,-45.3,6.1]],[[2.4,5.3,4.5],[5.4,1.4263,4.2],[14.46,1.06,123.1],[2.4,5.3,4.4]]],256,true).bounding_box
274
+ assert_equal(2,bbox.length)
275
+ assert_equal(Point.from_x_y(4.456,-45.3),bbox[0])
276
+ assert_equal(Point.from_x_y(45.4,41.6),bbox[1])
277
+
264
278
  end
265
279
  def test_polygon_equal
266
280
  polygon1 = 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]]],256)
@@ -319,6 +333,11 @@ class TestSimpleFeatures < Test::Unit::TestCase
319
333
  assert_equal(256,geometry_collection.srid)
320
334
  assert_equal(2,geometry_collection.length)
321
335
  assert_equal(LineString.from_coordinates([[5.7,12.45],[67.55,54]],256),geometry_collection[1])
336
+
337
+ bbox = geometry_collection.bounding_box
338
+ assert_equal(2,bbox.length)
339
+ assert_equal(Point.from_x_y(4.67,12.45),bbox[0])
340
+ assert_equal(Point.from_x_y(67.55,54),bbox[1])
322
341
  end
323
342
  def test_geometry_collection_equal
324
343
  geometry_collection1 = GeometryCollection.from_geometries([Point.from_x_y(4.67,45.4,256),LineString.from_coordinates([[5.7,12.45],[67.55,54]],256)],256)
@@ -363,10 +382,10 @@ class TestSimpleFeatures < Test::Unit::TestCase
363
382
  end
364
383
  def test_multi_point_text
365
384
  multi_point = MultiPoint.from_coordinates([[12.4,-123.3],[-65.1,123.4],[123.55555555,123]],444)
366
- assert_equal("SRID=444;MULTIPOINT(12.4 -123.3,-65.1 123.4,123.55555555 123)",multi_point.as_ewkt)
385
+ assert_equal("SRID=444;MULTIPOINT((12.4 -123.3),(-65.1 123.4),(123.55555555 123))",multi_point.as_ewkt)
367
386
 
368
387
  multi_point = MultiPoint.from_coordinates([[12.4,-123.3,4.5],[-65.1,123.4,6.7],[123.55555555,123,7.8]],444,true)
369
- assert_equal("SRID=444;MULTIPOINT(12.4 -123.3 4.5,-65.1 123.4 6.7,123.55555555 123 7.8)",multi_point.as_ewkt)
388
+ assert_equal("SRID=444;MULTIPOINT((12.4 -123.3 4.5),(-65.1 123.4 6.7),(123.55555555 123 7.8))",multi_point.as_ewkt)
370
389
 
371
390
 
372
391
  end
metadata CHANGED
@@ -3,15 +3,15 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: GeoRuby
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.1
7
- date: 2006-05-01 00:00:00 +05:00
6
+ version: 0.2.1
7
+ date: 2006-06-02 00:00:00 +05:00
8
8
  summary: Ruby data holder for OGC Simple Features
9
9
  require_paths:
10
10
  - lib
11
11
  email: guilhem.vellut+georuby@gmail.com
12
12
  homepage: http://thepochisuperstarmegashow.com
13
13
  rubyforge_project:
14
- description: GeoRuby is intended as a holder for data returned from PostGIS queries. Therefore, 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)
14
+ description: 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)
15
15
  autorequire:
16
16
  default_executable:
17
17
  bindir: bin