nofxx-postgis_adapter 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,5 +1,4 @@
1
- == Postgis Adapter
2
-
1
+ = PostgisAdapter
3
2
 
4
3
  A plugin for ActiveRecord which manages the PostGIS geometric columns
5
4
  in a transparent way (that is like the other base data type columns).
@@ -16,18 +15,21 @@ Postgis Manual - http://postgis.refractions.net/documentation/manual-svn
16
15
 
17
16
  If you are using Spatial Adapter, *remove it first*.
18
17
 
18
+
19
19
  ==== Dependencies
20
20
 
21
21
  - georuby
22
22
  - postgres 8.3+
23
23
  - postgis 1.3+
24
24
 
25
+
25
26
  ==== As gem:
26
27
 
27
28
  sudo gem sources --add http://gems.github.com
28
29
  sudo gem install nofxx-postgis_adapter
29
30
 
30
31
  config.gem "nofxx-postgis_adapter", :lib => "postgis_adapter", :source => "http://gems.github.com"
32
+
31
33
 
32
34
  ==== As plugin:
33
35
 
@@ -36,7 +38,6 @@ If you are using Spatial Adapter, *remove it first*.
36
38
 
37
39
  === How to Use
38
40
 
39
-
40
41
  Geometric columns in your ActiveRecord models now appear just like
41
42
  any other column of other basic data types. They can also be dumped
42
43
  in ruby schema mode and loaded in migrations the same way as columns
@@ -90,6 +91,7 @@ Here are this fork additions. To use it:
90
91
  @street.crosses?(@park)
91
92
 
92
93
  @area.contains?(@place)
94
+
93
95
 
94
96
  Polygons:
95
97
 
@@ -101,6 +103,7 @@ Polygons:
101
103
 
102
104
  @park.overlaps?(@other_park)
103
105
  => false
106
+
104
107
 
105
108
  Line Strings:
106
109
 
@@ -164,6 +167,7 @@ Or use a (almost) postgis like notation:
164
167
  @area.bbox "@", @park
165
168
 
166
169
 
170
+
167
171
  === Warning
168
172
 
169
173
  *To be fixed:*
@@ -173,6 +177,7 @@ implement a multi geom.
173
177
 
174
178
  http://nofxx.lighthouseapp.com/projects/20712/tickets/3-multiple-geoms-in-model
175
179
 
180
+
176
181
  === Wiki
177
182
 
178
183
  Check out the wiki pages (http://github.com/nofxx/postgis_adapter/wikis).
@@ -206,8 +211,8 @@ In PostGIS, since you can only use operations with geometries with the same SRID
206
211
  Park.find_by_geom([[3,5.6],[19.98,5.9],123])
207
212
 
208
213
 
209
- == Database Tools
210
214
 
215
+ == Database Tools
211
216
 
212
217
  === Migrations
213
218
 
@@ -244,7 +249,6 @@ the geometric column is a point:
244
249
 
245
250
  == Geometric data types
246
251
 
247
-
248
252
  Ruby geometric datatypes are currently made available only through
249
253
  the GeoRuby library (http://georuby.rubyforge.org): This is where the
250
254
  *Point.from_x_y* in the example above comes from. It is a goal
@@ -252,6 +256,12 @@ of a future release of the Spatial Adapter to support additional
252
256
  geometric datatype libraries, such as Ruby/GEOS, as long as they
253
257
  can support reading and writing of EWKB.
254
258
 
259
+ == Annotate
260
+
261
+ If you are using annotate_models, check out this fork which adds geometrical annotations for PostgisAdapter and SpatialAdapter:
262
+
263
+ http://github.com/nofxx/annotate_models
264
+
255
265
 
256
266
  === Warning
257
267
 
@@ -277,22 +287,23 @@ something like this :
277
287
 
278
288
  == License
279
289
 
280
-
281
290
  Spatial Adapter for Rails is released under the MIT license.
282
- PostGis Adapter is released under the MIT license.
291
+ Postgis Adapter is released under the MIT license.
283
292
 
284
293
 
285
294
  == Support
286
295
 
287
-
288
296
  Tested using rails 2.2.2 / postgresql 8.3.5 / postgis 1.3.3 / linux / osx
289
297
 
290
298
  Any questions, enhancement proposals, bug notifications or corrections:
291
299
 
292
- === PostGis Adapter
300
+
301
+ === PostgisAdapter
293
302
 
294
303
  Project Tracker http://nofxx.lighthouseapp.com/projects/20712-postgis_adapter
295
304
 
305
+
296
306
  === SpatialAdapter
297
307
 
308
+
298
309
  guilhem.vellut+georuby@gmail.com.
@@ -20,7 +20,7 @@ include GeoRuby::SimpleFeatures
20
20
  include SpatialAdapter
21
21
 
22
22
  module PostgisAdapter
23
- VERSION = '0.1.7'
23
+ VERSION = '0.1.8'
24
24
  end
25
25
 
26
26
  #tables to ignore in migration : relative to PostGIS management of geometric columns
@@ -10,6 +10,9 @@ module PostgisFunctions
10
10
  #
11
11
  module ClassMethods
12
12
 
13
+ #
14
+ # Returns the closest record
15
+ #
13
16
  def closest_to(p, srid=4326)
14
17
  find(:first, :order => "ST_Distance(geom, GeomFromText('POINT(#{p.x} #{p.y})', #{srid}))" )
15
18
  end
@@ -18,7 +21,10 @@ module PostgisFunctions
18
21
  find(:all, :order => "ST_Distance(geom, GeomFromText('POINT(#{p.x} #{p.y})', #{srid}))" )
19
22
  end
20
23
 
21
- def by_size sort='asc'
24
+ #
25
+ #
26
+ #
27
+ def by_length sort='asc'
22
28
  find(:all, :order => "ST_length(geom) #{sort}" )
23
29
  end
24
30
 
@@ -98,7 +98,7 @@ module PostgisFunctions
98
98
  # Returns Float ST_Distance(geometry g1, geometry g2);
99
99
  #
100
100
  def distance_to(other)
101
- postgis_calculate(:distance, [self, other])
101
+ postgis_calculate(:distance, [self, other]).to_f
102
102
  end
103
103
 
104
104
  #
@@ -124,6 +124,19 @@ module PostgisFunctions
124
124
  postgis_calculate(:within, [self, other])
125
125
  end
126
126
 
127
+ #
128
+ # True if the geometries are within the specified distance of one another.
129
+ # The distance is specified in units defined by the spatial reference system
130
+ # of the geometries. For this function to make sense, the source geometries
131
+ # must both be of the same coorindate projection, having the same SRID.
132
+ #
133
+ # Returns boolean ST_DWithin(geometry g1, geometry g2, double precision distance);
134
+ #
135
+ def d_within?(other, margin=0.1)
136
+ postgis_calculate(:dwithin, [self, other], margin)
137
+ end
138
+ alias_method "in_bounds?", "d_within?"
139
+
127
140
  #
128
141
  # True if geometry B is completely inside geometry A.
129
142
  #
@@ -217,7 +230,12 @@ module PostgisFunctions
217
230
  def simplify(tolerance=0.1)
218
231
  postgis_calculate(:simplify, self, tolerance)
219
232
  end
220
- #TODO: #def simplify!
233
+
234
+
235
+ def simplify!(tolerance=0.1)
236
+ #FIXME: not good..
237
+ self.geom = simplify
238
+ end
221
239
 
222
240
  #
223
241
  # Returns a "simplified" version of the given geometry using the Douglas-Peuker
@@ -364,20 +382,57 @@ module PostgisFunctions
364
382
  postgis_calculate(:polygonize, self)
365
383
  end
366
384
 
367
- # NEW
368
- #ST_OrderingEquals Returns true if the given geometries represent the same geometry and points are in the same directional order.
369
- #boolean ST_OrderingEquals(g
370
- # ST_PointOnSurface Returns a POINT guaranteed to lie on the surface.
371
- #geometry ST_PointOnSurface(geometry g1);eometry A, geometry B);
385
+ #
386
+ # Returns true if this Geometry is spatially related to anotherGeometry,
387
+ # by testing for intersections between the Interior, Boundary and Exterior
388
+ # of the two geometries as specified by the values in the
389
+ # intersectionPatternMatrix. If no intersectionPatternMatrix is passed in,
390
+ # then returns the maximum intersectionPatternMatrix that relates the 2 geometries.
391
+ #
392
+ #
393
+ # Version 1: Takes geomA, geomB, intersectionMatrix and Returns 1 (TRUE) if
394
+ # this Geometry is spatially related to anotherGeometry, by testing for
395
+ # intersections between the Interior, Boundary and Exterior of the two
396
+ # geometries as specified by the values in the intersectionPatternMatrix.
397
+ #
398
+ # This is especially useful for testing compound checks of intersection,
399
+ # crosses, etc in one step.
400
+ #
401
+ # Do not call with a GeometryCollection as an argument
402
+ #
403
+ # This is the "allowable" version that returns a boolean, not an integer.
404
+ # This is defined in OGC spec.
405
+ # This DOES NOT automagically include an index call. The reason for that
406
+ # is some relationships are anti e.g. Disjoint. If you are using a relationship
407
+ # pattern that requires intersection, then include the && index call.
408
+ #
409
+ # Version 2: Takes geomA and geomB and returns the DE-9IM
410
+ # (dimensionally extended nine-intersection matrix)
411
+ #
412
+ # Do not call with a GeometryCollection as an argument
413
+ # Not in OGC spec, but implied. see s2.1.13.2
414
+ #
415
+ # Both Performed by the GEOS module
416
+ #
417
+ # Returns:
418
+ #
419
+ # text ST_Relate(geometry geomA, geometry geomB);
420
+ # boolean ST_Relate(geometry geomA, geometry geomB, text intersectionPatternMatrix);
421
+ #
422
+ def relate?(other, m = nil)
423
+ # Relate is case sentitive.......
424
+ m = "'#{m}'" if m
425
+ postgis_calculate("Relate", [self, other], m)
426
+ end
427
+
428
+ end
372
429
 
430
+ # NEW
431
+ #ST_OrderingEquals — Returns true if the given geometries represent the same geometry and points are in the same directional order.
432
+ #boolean ST_OrderingEquals(g
433
+ # ST_PointOnSurface — Returns a POINT guaranteed to lie on the surface.
434
+ #geometry ST_PointOnSurface(geometry g1);eometry A, geometry B);
373
435
 
374
- #x ST_SnapToGrid(geometry, geometry, sizeX, sizeY, sizeZ, sizeM)
375
- # ST_X , ST_Y, SE_M, SE_Z, SE_IsMeasured has_m?
376
436
 
377
- #x ST_Relate(geometry, geometry, intersectionPatternMatrix)
378
-
379
-
380
-
381
-
382
-
383
- end
437
+ #x ST_SnapToGrid(geometry, geometry, sizeX, sizeY, sizeZ, sizeM)
438
+ # ST_X , ST_Y, SE_M, SE_Z, SE_IsMeasured has_m?
@@ -17,7 +17,7 @@ module PostgisFunctions
17
17
  # Returns Float
18
18
  #
19
19
  def length
20
- dis = postgis_calculate(:length, self)
20
+ dis = postgis_calculate(:length, self).to_f
21
21
  end
22
22
 
23
23
  #
@@ -28,7 +28,7 @@ module PostgisFunctions
28
28
  # Returns Float
29
29
  #
30
30
  def length_3d
31
- dis = postgis_calculate(:length3d, self)
31
+ dis = postgis_calculate(:length3d, self).to_f
32
32
  end
33
33
 
34
34
  #
@@ -49,7 +49,7 @@ module PostgisFunctions
49
49
  # Returns Float length_spheroid(geometry linestring, spheroid);
50
50
  #
51
51
  def length_spheroid(spheroid = EARTH_SPHEROID)
52
- dis = postgis_calculate(:length_spheroid, self, spheroid)
52
+ dis = postgis_calculate(:length_spheroid, self, spheroid).to_f
53
53
  end
54
54
 
55
55
  #
@@ -104,7 +104,7 @@ module PostgisFunctions
104
104
  # Returns float (0 to 1) ST_Line_Locate_Point(geometry a_linestring, geometry a_point);
105
105
  #
106
106
  def locate_point point
107
- postgis_calculate(:line_locate_point, [self, point])
107
+ postgis_calculate(:line_locate_point, [self, point]).to_f
108
108
  end
109
109
 
110
110
  #
@@ -8,19 +8,6 @@ module PostgisFunctions
8
8
  #
9
9
  module PointFunctions
10
10
 
11
- #
12
- # True if the geometries are within the specified distance of one another.
13
- # The distance is specified in units defined by the spatial reference system
14
- # of the geometries. For this function to make sense, the source geometries
15
- # must both be of the same coorindate projection, having the same SRID.
16
- #
17
- # Returns boolean ST_DWithin(geometry g1, geometry g2, double precision distance);
18
- #
19
- def d_within?(other, margin=0.1)
20
- postgis_calculate(:dwithin, [self, other], margin)
21
- end
22
- alias_method "in_bounds?", "d_within?"
23
-
24
11
  #
25
12
  # Returns a float between 0 and 1 representing the location of the closest point
26
13
  # on LineString to the given Point, as a fraction of total 2d line length.
@@ -33,7 +20,7 @@ module PostgisFunctions
33
20
  # Returns float (0 to 1) ST_Line_Locate_Point(geometry a_linestring, geometry a_point);
34
21
  #
35
22
  def where_on_line line
36
- postgis_calculate(:line_locate_point, [line, self])
23
+ postgis_calculate(:line_locate_point, [line, self]).to_f
37
24
  end
38
25
 
39
26
  #
@@ -46,7 +33,7 @@ module PostgisFunctions
46
33
  # Returns Float ST_Distance_Sphere(geometry pointlonlatA, geometry pointlonlatB);
47
34
  #
48
35
  def distance_sphere_to(other)
49
- dis = postgis_calculate(:distance_sphere, [self, other])
36
+ dis = postgis_calculate(:distance_sphere, [self, other]).to_f
50
37
  end
51
38
 
52
39
  #
@@ -69,7 +56,7 @@ module PostgisFunctions
69
56
  # Returns ST_Distance_Spheroid(geometry geomA, geometry geomB, spheroid);
70
57
  #
71
58
  def distance_spheroid_to(other, spheroid = EARTH_SPHEROID)
72
- postgis_calculate(:distance_spheroid, [self, other], spheroid)
59
+ postgis_calculate(:distance_spheroid, [self, other], spheroid).to_f
73
60
  end
74
61
 
75
62
  #
@@ -83,7 +70,7 @@ module PostgisFunctions
83
70
  #
84
71
  def azimuth other
85
72
  #TODO: return if not point/point
86
- postgis_calculate(:azimuth, [self, other])
73
+ postgis_calculate(:azimuth, [self, other]).to_f
87
74
  rescue
88
75
  ActiveRecord::StatementInvalid
89
76
  end
@@ -15,7 +15,7 @@ module PostgisFunctions
15
15
  # Returns Float ST_Area(geometry g1);
16
16
  #
17
17
  def area
18
- postgis_calculate(:area, self)
18
+ postgis_calculate(:area, self).to_f
19
19
  end
20
20
 
21
21
  #
@@ -27,7 +27,7 @@ module PostgisFunctions
27
27
  # Returns Float ST_Perimeter(geometry g1);
28
28
  #
29
29
  def perimeter
30
- postgis_calculate(:perimeter, self)
30
+ postgis_calculate(:perimeter, self).to_f
31
31
  end
32
32
 
33
33
  #
@@ -37,7 +37,7 @@ module PostgisFunctions
37
37
  # Returns Float ST_Perimeter3D(geometry geomA);
38
38
  #
39
39
  def perimeter3d
40
- postgis_calculate(:perimeter3d, self)
40
+ postgis_calculate(:perimeter3d, self).to_f
41
41
  end
42
42
 
43
43
  #
@@ -56,7 +56,7 @@ module PostgisFunctions
56
56
  #
57
57
  # Data => SELECT Func(A,B)
58
58
  # BBox => SELECT (A <=> B)
59
- #
59
+ #
60
60
  if type == :bbox
61
61
  opcode = nil
62
62
  s_join = " #{options} "
@@ -73,20 +73,22 @@ module PostgisFunctions
73
73
  #p sql; sql
74
74
  end
75
75
 
76
+ #
76
77
  # Execute the query and parse the return.
77
78
  # We may receive:
78
79
  #
79
80
  # "t" or "f" for boolean queries
80
81
  # BIGHASH for geometries
82
+ # HASH for ST_Relate
81
83
  # Rescue a float
82
84
  #
83
85
  def execute_geometrical_calculation(operation, subject, options) #:nodoc:
84
86
  value = connection.select_value(construct_geometric_sql(operation, subject, options))
85
87
  return nil unless value
86
- if value =~ /^\D/
88
+ if value =~ /t|f/
87
89
  {"f" => false, "t" => true}[value]
88
90
  else
89
- GeoRuby::SimpleFeatures::Geometry.from_hex_ewkb(value) rescue value.to_f
91
+ GeoRuby::SimpleFeatures::Geometry.from_hex_ewkb(value) rescue value
90
92
  end
91
93
  end
92
94
 
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "postgis_adapter"
3
- s.version = "0.1.7"
3
+ s.version = "0.1.8"
4
4
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
5
5
  s.authors = ["Marcos Piccinini"]
6
- s.date = "2008-12-10"
6
+ s.date = "2008-12-16"
7
7
  s.description = "Postgis Adapter for Activer Record"
8
8
  s.email = ["x@nofxx.com"]
9
9
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
@@ -16,8 +16,8 @@ describe "LineString" do
16
16
  end
17
17
 
18
18
  it "should sort by size" do
19
- Street.by_size.first.data.should == "Street1"
20
- Street.by_size.last.data.should == "Street3"
19
+ Street.by_length.first.data.should == "Street1"
20
+ Street.by_length.last.data.should == "Street3"
21
21
  end
22
22
 
23
23
  it "largest" do
@@ -14,6 +14,7 @@ describe "Point" do
14
14
  @p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(1,1,123))
15
15
  @p2 ||= Position.create!(:data => "Point2", :geom => Point.from_x_y(5,5,123))
16
16
  @p3 ||= Position.create!(:data => "Point3", :geom => Point.from_x_y(8,8,123))
17
+ @p4 ||= Position.create!(:data => "Point5", :geom => Point.from_x_y(18.1,18,123))
17
18
  end
18
19
 
19
20
 
@@ -82,13 +83,6 @@ describe "Point" do
82
83
  @p1.should be_outside(@c1)
83
84
  end
84
85
 
85
- it do
86
- @p1.should be_in_bounds(@s1)
87
- end
88
-
89
- it "in bounds of a geometry? with option" do
90
- @p3.should_not be_in_bounds(@s1, 1)
91
- end
92
86
 
93
87
  it do
94
88
  @p1.azimuth(@p2).should be_close(0.785398163397448,0.000001)
@@ -117,6 +111,26 @@ describe "Point" do
117
111
  it do
118
112
  @p3.polygonize.geometries.should be_empty
119
113
  end
114
+
115
+ it do
116
+ @p1.should be_in_bounds(@s1)
117
+ end
120
118
 
119
+ it "in bounds of a geometry? with option" do
120
+ @p3.should_not be_in_bounds(@s1, 1)
121
+ end
122
+
123
+ it { @p4.in_bounds?(@s3, 0.01).should be_false }
124
+
125
+ it { @p4.where_on_line(@s3).should be_close(0.335, 0.0001) }
126
+
127
+ it { @s3.locate_point(@p4).should be_close(0.335, 0.1)}
128
+
129
+ it { @s3.interpolate_point(0.335).x.should be_close(18.05, 0.01) }
130
+
131
+ it { @p1.relate?(@s3, "T*T***FF*").should be_false }
132
+
133
+ it { @p1.relate?(@s3).should eql("FF0FFF102") }
134
+
121
135
  end
122
136
 
@@ -24,7 +24,7 @@ describe "Point" do
24
24
  describe "Polygon" do
25
25
 
26
26
  it "sort by area size" do
27
- City.by_size.first.data.should == "City1" #[@c1, @c2, @c3]
27
+ City.by_area.first.data.should == "City1" #[@c1, @c2, @c3]
28
28
  end
29
29
 
30
30
  it do
data/spec/spec.opts CHANGED
@@ -1,6 +1,6 @@
1
1
  --colour
2
2
  --format
3
- profile
3
+ spinner
4
4
  --timeout
5
5
  20
6
- --diff
6
+ --diff
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nofxx-postgis_adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcos Piccinini
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-10 00:00:00 -08:00
12
+ date: 2008-12-16 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency