postgis_adapter 0.2.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -11,32 +11,42 @@ Postgis Manual - http://postgis.refractions.net/documentation/manual-svn
11
11
  *PostGIS and Rails 2+ only*.
12
12
 
13
13
 
14
- === Install
14
+ == Install
15
15
 
16
16
  If you are using Spatial Adapter, *remove it first*.
17
17
 
18
18
 
19
- ==== Dependencies
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
+ === As gem:
27
+
28
+ sudo gem install postgis-adapter
29
+
30
+ Rails:
31
+
32
+ config.gem "postgis_adapter"
33
+
34
+ Github version:
35
+
36
+
37
+ sudo gem install nofxx-postgis_adapter --source http://gems.github.com
38
+
39
+ Rails:
27
40
 
28
- sudo gem sources --add http://gems.github.com
29
- sudo gem install nofxx-postgis_adapter
30
-
31
41
  config.gem "nofxx-postgis_adapter", :lib => "postgis_adapter", :source => "http://gems.github.com"
32
-
33
-
34
- ==== As plugin:
42
+
43
+
44
+ === As plugin:
35
45
 
36
46
  script/plugin install git://github.com/nofxx/postgis_adapter.git
37
47
 
38
48
 
39
- === How to Use
49
+ == How to Use
40
50
 
41
51
  Geometric columns in your ActiveRecord models now appear just like
42
52
  any other column of other basic data types. They can also be dumped
@@ -55,11 +65,11 @@ The plugin will get this information by itself.
55
65
  Here is an example of PostGIS row creation and access, using the
56
66
  model and the table defined above :
57
67
 
58
- pt = TablePoint.new(:data => "Hello!",:geom => Point.from_x_y(1,2))
59
- pt.save
60
- pt = TablePoint.first
61
- puts pt.geom.x
62
- => 1
68
+ pt = TablePoint.new(:data => "Hello!",:geom => Point.from_x_y(1,2))
69
+ pt.save
70
+ pt = TablePoint.first
71
+ puts pt.geom.x
72
+ => 1
63
73
 
64
74
 
65
75
  == PostGIS Functions
@@ -78,7 +88,7 @@ Here are this fork additions. To use it:
78
88
  @street = Street.new( :line => **LineString** )
79
89
 
80
90
 
81
- === Play!
91
+ == Play!
82
92
 
83
93
  @place.inside?(@park)
84
94
  => true
@@ -91,9 +101,9 @@ Here are this fork additions. To use it:
91
101
  @street.crosses?(@park)
92
102
 
93
103
  @area.contains?(@place)
94
-
95
104
 
96
- Polygons:
105
+
106
+ === Polygons:
97
107
 
98
108
  @park.area
99
109
  => 1345
@@ -103,9 +113,14 @@ Polygons:
103
113
 
104
114
  @park.overlaps?(@other_park)
105
115
  => false
106
-
107
116
 
108
- Line Strings:
117
+ Supports transform (useful to transform SRID to UTM for area in Km^2)
118
+
119
+ @park.area(SRID)
120
+ => Area with new SRID
121
+
122
+
123
+ === Line Strings:
109
124
 
110
125
  @street_east.intersects?(@street_west)
111
126
  => false
@@ -120,7 +135,7 @@ Line Strings:
120
135
  => 4.40853636
121
136
 
122
137
 
123
- === And for classes:
138
+ === Class Methods
124
139
 
125
140
  City.close_to(@point)
126
141
  => [Array of cities in order by distance...
@@ -158,7 +173,7 @@ Line Strings:
158
173
  same_as?
159
174
 
160
175
 
161
- Or use a (almost) postgis like notation:
176
+ Or use a (almost) PostGIS like notation:
162
177
 
163
178
  @area.bbox "<<", @point
164
179
 
@@ -200,15 +215,15 @@ the find_by_*geom_column*: Either by passing a geometric object directly,
200
215
  or passing an array with the 2 opposite corners of a bounding box
201
216
  (with 2 or 3 coordinates depending of the dimension of the data).
202
217
 
203
- Park.find_by_geom(LineString.from_coordinates([[1.4,5.6],[2.7,8.9],[1.6,5.6]]))
218
+ Park.find_by_geom(LineString.from_coordinates([[1.4,5.6],[2.7,8.9],[1.6,5.6]]))
204
219
 
205
220
  or
206
221
 
207
- Park.find_by_geom([[3,5.6],[19.98,5.9]])
222
+ Park.find_by_geom([[3,5.6],[19.98,5.9]])
208
223
 
209
224
  In PostGIS, since you can only use operations with geometries with the same SRID, you can add a third element representing the SRID of the bounding box to the array. It is by default set to -1:
210
225
 
211
- Park.find_by_geom([[3,5.6],[19.98,5.9],123])
226
+ Park.find_by_geom([[3,5.6],[19.98,5.9],123])
212
227
 
213
228
 
214
229
 
@@ -221,13 +236,13 @@ geometric column in PostGIS, along with the addition of a spatial
221
236
  index on the column :
222
237
 
223
238
  ActiveRecord::Schema.define do
224
- create_table :places do |t|
239
+ create_table :places do |t|
225
240
  t.string :name
226
- t.point :geom, :srid => 123, :with_z => true, :null => false
227
-
241
+ t.point :geom, :srid => 123, :with_z => true, :null => false
242
+
228
243
  t.timestamps
229
244
  end
230
- add_index :table_points, :geom, :spatial=>true
245
+ add_index :table_points, :geom, :spatial=>true
231
246
  end
232
247
 
233
248
 
@@ -242,9 +257,9 @@ is different for each database). You would use it like this, if
242
257
  the geometric column is a point:
243
258
 
244
259
  fixture:
245
- id: 1
246
- data: HELLO
247
- geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>
260
+ id: 1
261
+ data: HELLO
262
+ geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>
248
263
 
249
264
 
250
265
  === Annotate
@@ -295,7 +310,7 @@ Postgis Adapter is released under the MIT license.
295
310
 
296
311
  == Support
297
312
 
298
- Tested using rails 2.2.2 / postgresql 8.3.5 / postgis 1.3.3 / linux / osx
313
+ Tested using rails 2.2.2/2.3.0 / postgresql 8.3.5 / postgis 1.3.3 / linux / osx
299
314
 
300
315
  Any questions, enhancement proposals, bug notifications or corrections:
301
316
 
@@ -4,7 +4,8 @@
4
4
  # Spatial Adapter PostGIS Adapter for ActiveRecord
5
5
  #
6
6
  #
7
- #require 'active_record'
7
+ require 'activerecord'
8
+ require 'active_record/connection_adapters/postgresql_adapter'
8
9
  require 'geo_ruby'
9
10
  require 'postgis_adapter/common_spatial_adapter'
10
11
  require 'postgis_functions'
@@ -17,7 +18,7 @@ include GeoRuby::SimpleFeatures
17
18
  include SpatialAdapter
18
19
 
19
20
  module PostgisAdapter
20
- VERSION = '0.2.1'
21
+ VERSION = '0.2.3'
21
22
  end
22
23
 
23
24
  #tables to ignore in migration : relative to PostGIS management of geometric columns
@@ -250,7 +251,8 @@ SELECT * FROM geometry_columns WHERE f_table_name = '#{table_name}'
250
251
  end
251
252
 
252
253
  raw_geom_infos
253
-
254
+ rescue => e
255
+ nil
254
256
  end
255
257
 
256
258
  end
@@ -10,7 +10,7 @@ module PostgisFunctions
10
10
  # These operators utilize indexes. They compare geometries by bounding boxes.
11
11
  #
12
12
  # You can use the literal forms or call directly using the 'bbox' method. eg.:
13
- #
13
+ #
14
14
  # @point.bbox(">>", @area)
15
15
  # @point.bbox("|&>", @area)
16
16
  #
@@ -125,4 +125,4 @@ module PostgisFunctions
125
125
  def same_as? other
126
126
  bbox("=", other)
127
127
  end
128
- end
128
+ end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  # #
2
3
  #
3
4
  # COMMON GEOMETRICAL FUNCTIONS
@@ -19,7 +20,7 @@ module PostgisFunctions
19
20
  # (it must be noted ST_OrderingEquals is a little more stringent than
20
21
  # simply verifying order of points are the same).
21
22
  #
22
- # This function will return false if either geometry is invalid even
23
+ # This function will return false if either geometry is invalid even
23
24
  # if they are binary equal.
24
25
  #
25
26
  # Returns Boolean ST_Equals(geometry A, geometry B);
@@ -74,9 +75,9 @@ module PostgisFunctions
74
75
  def centroid
75
76
  postgis_calculate(:centroid, self)
76
77
  end
77
-
78
+
78
79
  #
79
- # Returns the closure of the combinatorial boundary of this Geometry.
80
+ # Returns the closure of the combinatorial boundary of this Geometry.
80
81
  # The combinatorial boundary is defined as described in section 3.12.3.2 of the
81
82
  # OGC SPEC. Because the result of this function is a closure, and hence topologically
82
83
  # closed, the resulting boundary can be represented using representational
@@ -100,7 +101,7 @@ module PostgisFunctions
100
101
  def distance_to(other)
101
102
  postgis_calculate(:distance, [self, other]).to_f
102
103
  end
103
-
104
+
104
105
  #
105
106
  # True if geometry A is completely inside geometry B.
106
107
  #
@@ -136,11 +137,11 @@ module PostgisFunctions
136
137
  postgis_calculate(:dwithin, [self, other], margin)
137
138
  end
138
139
  alias_method "in_bounds?", "d_within?"
139
-
140
+
140
141
  #
141
- # True if geometry B is completely inside geometry A.
142
+ # True if geometry B is completely inside geometry A.
142
143
  #
143
- # For this function to make sense, the source geometries must both be of the same
144
+ # For this function to make sense, the source geometries must both be of the same
144
145
  # coordinate projection, having the same SRID. 'contains?' is the inverse of 'within?'.
145
146
  #
146
147
  # So a.contains?(b) is like b.within?(a) except in the case of invalid
@@ -156,7 +157,7 @@ module PostgisFunctions
156
157
  def contains? other
157
158
  postgis_calculate(:contains, [self, other])
158
159
  end
159
-
160
+
160
161
  #
161
162
  # True if no point in Geometry A is outside Geometry B
162
163
  #
@@ -177,7 +178,7 @@ module PostgisFunctions
177
178
  postgis_calculate(:coveredby, [self, other])
178
179
  end
179
180
  alias_method "inside?", "covered_by?"
180
-
181
+
181
182
  #
182
183
  # Eye-candy. See 'covered_by?'.
183
184
  #
@@ -230,8 +231,8 @@ module PostgisFunctions
230
231
  def simplify(tolerance=0.1)
231
232
  postgis_calculate(:simplify, self, tolerance)
232
233
  end
233
-
234
-
234
+
235
+
235
236
  def simplify!(tolerance=0.1)
236
237
  #FIXME: not good..
237
238
  self.update_attribute(get_column_name, simplify)
@@ -255,7 +256,7 @@ module PostgisFunctions
255
256
  #
256
257
  # True if Geometries "spatially intersect", share any portion of space.
257
258
  # False if they don't (they are Disjoint).
258
- #
259
+ #
259
260
  # 'overlaps?', 'touches?', 'within?' all imply spatial intersection.
260
261
  # If any of the aforementioned returns true, then the geometries also
261
262
  # spatially intersect. 'disjoint?' implies false for spatial intersection.
@@ -344,11 +345,11 @@ module PostgisFunctions
344
345
  def convex_hull
345
346
  postgis_calculate(:convexhull, self)
346
347
  end
347
-
348
+
348
349
  #
349
350
  # Creates an areal geometry formed by the constituent linework of given geometry.
350
- # The return type can be a Polygon or MultiPolygon, depending on input.
351
- # If the input lineworks do not form polygons NULL is returned. The inputs can
351
+ # The return type can be a Polygon or MultiPolygon, depending on input.
352
+ # If the input lineworks do not form polygons NULL is returned. The inputs can
352
353
  # be LINESTRINGS, MULTILINESTRINGS, POLYGONS, MULTIPOLYGONS, and GeometryCollections.
353
354
  #
354
355
  # Returns Boolean ST_BuildArea(geometry A);
@@ -356,7 +357,7 @@ module PostgisFunctions
356
357
  def build_area
357
358
  postgis_calculate(:buildarea, self)
358
359
  end
359
-
360
+
360
361
  #
361
362
  # Returns true if this Geometry has no anomalous geometric points, such as
362
363
  # self intersection or self tangency.
@@ -369,10 +370,10 @@ module PostgisFunctions
369
370
  alias_method "simple?", "is_simple?"
370
371
 
371
372
  #
372
- # Aggregate. Creates a GeometryCollection containing possible polygons formed
373
+ # Aggregate. Creates a GeometryCollection containing possible polygons formed
373
374
  # from the constituent linework of a set of geometries.
374
375
  #
375
- # Geometry Collections are often difficult to deal with with third party tools,
376
+ # Geometry Collections are often difficult to deal with with third party tools,
376
377
  # so use ST_Polygonize in conjunction with ST_Dump to dump the polygons out into
377
378
  # individual polygons.
378
379
  #
@@ -381,75 +382,84 @@ module PostgisFunctions
381
382
  def polygonize#(geom)
382
383
  postgis_calculate(:polygonize, self)
383
384
  end
384
-
385
+
385
386
  #
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,
387
+ # Returns true if this Geometry is spatially related to anotherGeometry,
388
+ # by testing for intersections between the Interior, Boundary and Exterior
389
+ # of the two geometries as specified by the values in the
390
+ # intersectionPatternMatrix. If no intersectionPatternMatrix is passed in,
390
391
  # 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
392
+ #
393
+ #
394
+ # Version 1: Takes geomA, geomB, intersectionMatrix and Returns 1 (TRUE) if
395
+ # this Geometry is spatially related to anotherGeometry, by testing for
396
+ # intersections between the Interior, Boundary and Exterior of the two
396
397
  # geometries as specified by the values in the intersectionPatternMatrix.
397
- #
398
- # This is especially useful for testing compound checks of intersection,
398
+ #
399
+ # This is especially useful for testing compound checks of intersection,
399
400
  # crosses, etc in one step.
400
- #
401
+ #
401
402
  # Do not call with a GeometryCollection as an argument
402
- #
403
- # This is the "allowable" version that returns a boolean, not an integer.
403
+ #
404
+ # This is the "allowable" version that returns a boolean, not an integer.
404
405
  # 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
406
+ # This DOES NOT automagically include an index call. The reason for that
407
+ # is some relationships are anti e.g. Disjoint. If you are using a relationship
407
408
  # pattern that requires intersection, then include the && index call.
408
- #
409
- # Version 2: Takes geomA and geomB and returns the DE-9IM
409
+ #
410
+ # Version 2: Takes geomA and geomB and returns the DE-9IM
410
411
  # (dimensionally extended nine-intersection matrix)
411
- #
412
+ #
412
413
  # Do not call with a GeometryCollection as an argument
413
414
  # Not in OGC spec, but implied. see s2.1.13.2
414
- #
415
+ #
415
416
  # Both Performed by the GEOS module
416
- #
417
+ #
417
418
  # Returns:
418
419
  #
419
- # text ST_Relate(geometry geomA, geometry geomB);
420
- # boolean ST_Relate(geometry geomA, geometry geomB, text intersectionPatternMatrix);
420
+ # String ST_Relate(geometry geomA, geometry geomB);
421
+ # Boolean ST_Relate(geometry geomA, geometry geomB, text intersectionPatternMatrix);
421
422
  #
422
423
  def relate?(other, m = nil)
423
424
  # Relate is case sentitive.......
424
425
  m = "'#{m}'" if m
425
426
  postgis_calculate("Relate", [self, other], m)
426
- end
427
+ end
427
428
 
428
- #
429
- # Transform the geometry into a different spatial reference system.
430
429
  #
431
- # Return geometry ST_Transform(geometry g1, integer srid);
432
- # Returns a new geometry with its coordinates transformed to spatial reference system referenced by the SRID integer parameter. The destination SRID must exist in the SPATIAL_REF_SYS table.
433
- # ST_Transform is often confused with ST_SetSRID(). ST_Transform actually changes the coordinates of a geometry from one spatial reference system to another, while ST_SetSRID() simply changes the SRID identifier of the geometry
434
- # Requires PostGIS be compiled with Proj support. Use PostGIS_Full_Version to confirm you have proj support compiled in.
435
- #
436
- # If using more than one transformation, it is useful to have a functional index on the commonly used transformations to take advantage of index usage.
430
+ # Transform the geometry into a different spatial reference system.
431
+ # The destination SRID must exist in the SPATIAL_REF_SYS table.
437
432
  #
438
- # Prior to 1.3.4, this function crashes if used with geometries that contain CURVES. This is fixed in 1.3.4+
439
433
  # This method implements the OpenGIS Simple Features Implementation Specification for SQL.
440
- # This method supports Circular Strings and Curves
434
+ # This method supports Circular Strings and Curves (PostGIS 1.3.4+)
435
+ #
436
+ # Requires PostGIS be compiled with Proj support.
437
+ #
438
+ # Return Geometry ST_Transform(geometry g1, integer srid);
441
439
  #
442
440
  def transform(new_srid)
443
441
  postgis_calculate("Transform", self, new_srid)
444
442
  end
445
-
443
+
444
+ #
445
+ # Returns a modified geometry having no segment longer than the given distance.
446
+ # Distance computation is performed in 2d only.
447
+ #
448
+ # This will only increase segments. It will not lengthen segments shorter than max length
449
+ #
450
+ # Return Geometry ST_Segmentize(geometry geomA, float max_length);
451
+ #
452
+ def segmentize(max_length=1.0)
453
+ postgis_calculate("segmentize", self, max_length)
454
+ end
455
+
446
456
  #
447
457
  # LINESTRING
448
458
  #
449
459
  #
450
460
  #
451
461
  module LineStringFunctions
452
-
462
+
453
463
  #
454
464
  # Returns the 2D length of the geometry if it is a linestring, multilinestring,
455
465
  # ST_Curve, ST_MultiCurve. 0 is returned for areal geometries. For areal geometries
@@ -548,12 +558,12 @@ module PostgisFunctions
548
558
  def locate_point point
549
559
  postgis_calculate(:line_locate_point, [self, point]).to_f
550
560
  end
551
-
561
+
552
562
  #
553
- # Return a derived geometry collection value with elements that match the
563
+ # Return a derived geometry collection value with elements that match the
554
564
  # specified measure. Polygonal elements are not supported.
555
565
  #
556
- # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for
566
+ # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for
557
567
  # Continuation CD Editing Meeting
558
568
  #
559
569
  # Returns geometry ST_Locate_Along_Measure(geometry ageom_with_measure, float a_measure);
@@ -561,9 +571,9 @@ module PostgisFunctions
561
571
  def locate_along_measure(measure)
562
572
  postgis_calculate(:locate_along_measure, self, measure)
563
573
  end
564
-
574
+
565
575
  #
566
- # Return a derived geometry collection value with elements that match the
576
+ # Return a derived geometry collection value with elements that match the
567
577
  # specified range of measures inclusively. Polygonal elements are not supported.
568
578
  #
569
579
  # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for Continuation CD Editing Meeting
@@ -573,7 +583,7 @@ module PostgisFunctions
573
583
  def locate_between_measures(a, b)
574
584
  postgis_calculate(:locate_between_measures, self, [a,b])
575
585
  end
576
-
586
+
577
587
  #
578
588
  # Returns a point interpolated along a line. First argument must be a LINESTRING.
579
589
  # Second argument is a float8 between 0 and 1 representing fraction of total
@@ -603,7 +613,7 @@ module PostgisFunctions
603
613
  postgis_calculate(:line_substring, self, [s, e])
604
614
  end
605
615
 
606
- ###
616
+ ###
607
617
  #Not implemented in postgis yet
608
618
  # ST_max_distance Returns the largest distance between two line strings.
609
619
  #def max_distance other
@@ -699,7 +709,7 @@ module PostgisFunctions
699
709
  end
700
710
 
701
711
  end
702
-
712
+
703
713
  ###
704
714
  ##
705
715
  #
@@ -713,10 +723,12 @@ module PostgisFunctions
713
723
  # Return the area measurement of an ST_Surface or ST_MultiSurface value.
714
724
  # Area is in the units of the spatial reference system.
715
725
  #
726
+ # Accepts optional parameter, the srid to transform to.
727
+ #
716
728
  # Returns Float ST_Area(geometry g1);
717
729
  #
718
- def area
719
- postgis_calculate(:area, self).to_f
730
+ def area transform=nil
731
+ postgis_calculate(:area, self, { :transform => transform }).to_f
720
732
  end
721
733
 
722
734
  #
@@ -725,10 +737,12 @@ module PostgisFunctions
725
737
  # use 'length'. Measurements are in the units of the spatial reference system of
726
738
  # the geometry.
727
739
  #
740
+ # Accepts optional parameter, the srid to transform to.
741
+ #
728
742
  # Returns Float ST_Perimeter(geometry g1);
729
743
  #
730
- def perimeter
731
- postgis_calculate(:perimeter, self).to_f
744
+ def perimeter transform=nil
745
+ postgis_calculate(:perimeter, self, { :transform => transform }).to_f
732
746
  end
733
747
 
734
748
  #
@@ -775,7 +789,7 @@ module PostgisFunctions
775
789
  end
776
790
 
777
791
  end
778
-
792
+
779
793
  end
780
794
 
781
795
  # NEW
@@ -1,9 +1,8 @@
1
- # #
1
+ # -*- coding: utf-8 -*-
2
2
  #
3
3
  # PostGIS Adapter - http://github.com/nofxx/postgis_adapter
4
4
  #
5
- # Hope you enjoy this plugin.
6
- #
5
+ # Hope you enjoy this plugin.
7
6
  #
8
7
  #
9
8
  # Post any bugs/suggestions to the lighthouse tracker:
@@ -16,12 +15,11 @@
16
15
  # Earth Spheroid - http://en.wikipedia.org/wiki/Figure_of_the_Earth
17
16
  #
18
17
  #
19
- #
20
18
  module PostgisFunctions
21
19
  EARTH_SPHEROID = "'SPHEROID[\"GRS-80\",6378137,298.257222101]'" # SRID => 4326
22
- #EARTH_SPHEROID = "'SPHEROID[\"IERS_2003\",6378136.6,298.25642]'" # SRID =>
20
+ #EARTH_SPHEROID = "'SPHEROID[\"IERS_2003\",6378136.6,298.25642]'" # SRID =>
23
21
 
24
- def postgis_calculate(operation, subjects, options = nil)
22
+ def postgis_calculate(operation, subjects, options = {})
25
23
  subjects = [subjects] unless subjects.respond_to?(:map)
26
24
  return execute_geometrical_calculation(operation, subjects, options)
27
25
  rescue Exception => e
@@ -33,14 +31,14 @@ module PostgisFunctions
33
31
  def get_column_name
34
32
  @geo_column ||= postgis_geoms[:columns].first
35
33
  end
36
-
34
+
35
+ #
37
36
  # Construct the postgis sql query
38
37
  #
39
38
  # Area return in square feet
40
39
  # Distance/DWithin/Length/Perimeter — in projected units.
41
40
  # DistanceSphere/Spheroid — in meters.
42
41
  #
43
- #
44
42
  def construct_geometric_sql(type,geoms,options)
45
43
 
46
44
  tables = geoms.map do |t| {
@@ -48,16 +46,24 @@ module PostgisFunctions
48
46
  :uid => unique_identifier,
49
47
  :id => t[:id] }
50
48
  end
51
-
52
- fields = tables.map { |f| "#{f[:uid]}.#{get_column_name}" } # W1.geom
53
- conditions = tables.map { |f| "#{f[:uid]}.id = #{f[:id]}" } # W1.id = 5
54
- tables.map! { |f| "#{f[:class]} #{f[:uid]}" } # streets W1
55
49
 
50
+ # Implement a better way for options?
51
+ if options.instance_of? Hash
52
+ transform = options.delete(:transform)
53
+ options = nil
54
+ end
55
+
56
+ fields = tables.map { |f| "#{f[:uid]}.#{get_column_name}" } # W1.geom
57
+ fields.map! { |f| "ST_Transform(#{f}, #{transform})" } if transform # ST_Transform(W1.geom,x)
58
+ conditions = tables.map { |f| "#{f[:uid]}.id = #{f[:id]}" } # W1.id = 5
59
+ tables.map! { |f| "#{f[:class]} #{f[:uid]}" } # streets W1
60
+
56
61
  #
57
- # Data => SELECT Func(A,B)
58
- # BBox => SELECT (A <=> B)
59
- #
60
- unless type == :bbox
62
+ # Data => SELECT Func(A,B)
63
+ # BBox => SELECT (A <=> B)
64
+ # Func => SELECT Func(Func(A))
65
+ #
66
+ if type != :bbox
61
67
  opcode = type.to_s
62
68
  opcode = "ST_#{opcode}" unless opcode =~ /th3d|pesinter/
63
69
  fields << options if options
@@ -85,7 +91,7 @@ module PostgisFunctions
85
91
  value = connection.select_value(construct_geometric_sql(operation, subject, options))
86
92
  return nil unless value
87
93
  if value =~ /t|f/
88
- {"f" => false, "t" => true}[value]
94
+ {"f" => false, "t" => true}[value]
89
95
  else
90
96
  GeoRuby::SimpleFeatures::Geometry.from_hex_ewkb(value) rescue value
91
97
  end
@@ -143,7 +149,7 @@ end
143
149
  #ST_AsGML
144
150
  #ST_AsKML
145
151
  #ST_AsSVG
146
- #
152
+ #
147
153
  # def distance_convert(value, unit, from = nil)
148
154
  # factor = case unit
149
155
  # when :km, :kilo then 1
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{postgis_adapter}
5
- s.version = "0.2.1"
5
+ s.version = "0.2.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Marcos Piccinini"]
9
- s.date = %q{2009-01-10}
9
+ s.date = %q{2009-02-16}
10
10
  s.description = %q{Postgis Adapter for Activer Record}
11
11
  s.email = ["x@nofxx.com"]
12
12
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
@@ -1,51 +1,45 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
 
3
-
4
3
  describe "Point" do
5
4
 
6
- before(:all) do
7
- @c1 ||= City.create!(:data => "City1", :geom => Polygon.from_coordinates([[[12,45],[45,41],[4,1],[12,45]],[[2,5],[5,1],[14,1],[2,5]]],4326))
8
- @c2 ||= City.create!(:data => "City1", :geom => Polygon.from_coordinates([[[22,66],[65,65],[20,10],[22,66]],[[10,15],[15,11],[34,14],[10,15]]],4326))
9
- @c3 ||= City.create!(:data => "City3", :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]]],4326))
10
- @s1 ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[1,1],[2,2]],4326))
11
- @s2 ||= Street.create!(:data => "Street2", :geom => LineString.from_coordinates([[4,4],[7,7]],4326))
12
- @s3 ||= Street.create!(:data => "Street3", :geom => LineString.from_coordinates([[8,8],[18,18],[20,20],[25,25],[30,30],[38,38]],4326))
13
- @s4 ||= Street.create!(:data => "Street3", :geom => LineString.from_coordinates([[10,8],[15,18]],4326))
14
- @p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(1,1,4326))
15
- @p2 ||= Position.create!(:data => "Point2", :geom => Point.from_x_y(5,5,4326))
16
- @p3 ||= Position.create!(:data => "Point3", :geom => Point.from_x_y(8,8,4326))
17
- end
18
-
19
- describe "BBox operations" do
20
-
21
- it "should check stricly left" do
22
- @p1.bbox("<<", @c1).should be_true
23
- end
24
-
25
- it "should check stricly right" do
26
- @p1.bbox(">>", @c1).should be_false
27
- end
28
-
29
- it do @p1.should be_strictly_left_of(@c1) end
30
- it do @p1.should_not be_strictly_right_of(@c1) end
31
- it do @p1.should_not be_overlaps_or_right_of(@c1) end
32
- it do @p1.should be_overlaps_or_left_of(@c1) end
33
- it do @p1.should_not be_completely_contained_by(@c1) end
34
- it do @c2.completely_contains?(@p1).should be_false end
35
- it do @p1.should be_overlaps_or_above(@c1) end
36
- it do @p1.should be_overlaps_or_below(@c1) end
37
- it do @p1.should_not be_strictly_above(@c1) end
38
- it do @p1.should_not be_strictly_below(@c1) end
39
- it do @p1.interacts_with?(@c1).should be_false end
40
-
41
- it do
42
- @p1.binary_equal?(@c1).should be_false
43
- end
44
-
45
- it do
46
- @p1.same_as?(@c1).should be_false
47
- end
48
-
49
- end
50
-
51
- end
5
+ before(:all) do
6
+ @c1 ||= City.create!(:data => "City1", :geom => Polygon.from_coordinates([[[12,45],[45,41],[4,1],[12,45]],[[2,5],[5,1],[14,1],[2,5]]],4326))
7
+ @c2 ||= City.create!(:data => "City1", :geom => Polygon.from_coordinates([[[22,66],[65,65],[20,10],[22,66]],[[10,15],[15,11],[34,14],[10,15]]],4326))
8
+ @c3 ||= City.create!(:data => "City3", :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]]],4326))
9
+ @s1 ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[1,1],[2,2]],4326))
10
+ @s2 ||= Street.create!(:data => "Street2", :geom => LineString.from_coordinates([[4,4],[7,7]],4326))
11
+ @s3 ||= Street.create!(:data => "Street3", :geom => LineString.from_coordinates([[8,8],[18,18],[20,20],[25,25],[30,30],[38,38]],4326))
12
+ @s4 ||= Street.create!(:data => "Street3", :geom => LineString.from_coordinates([[10,8],[15,18]],4326))
13
+ @p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(1,1,4326))
14
+ @p2 ||= Position.create!(:data => "Point2", :geom => Point.from_x_y(5,5,4326))
15
+ @p3 ||= Position.create!(:data => "Point3", :geom => Point.from_x_y(8,8,4326))
16
+ end
17
+
18
+ describe "BBox operations" do
19
+
20
+ it "should check stricly left" do
21
+ @p1.bbox("<<", @c1).should be_true
22
+ end
23
+
24
+ it "should check stricly right" do
25
+ @p1.bbox(">>", @c1).should be_false
26
+ end
27
+
28
+ it { @p1.should be_strictly_left_of(@c1) }
29
+ it { @p1.should_not be_strictly_right_of(@c1) }
30
+ it { @p1.should_not be_overlaps_or_right_of(@c1) }
31
+ it { @p1.should be_overlaps_or_left_of(@c1) }
32
+ it { @p1.should_not be_completely_contained_by(@c1) }
33
+ it { @c2.completely_contains?(@p1).should be_false }
34
+ it { @p1.should be_overlaps_or_above(@c1) }
35
+ it { @p1.should be_overlaps_or_below(@c1) }
36
+ it { @p1.should_not be_strictly_above(@c1) }
37
+ it { @p1.should_not be_strictly_below(@c1) }
38
+ it { @p1.interacts_with?(@c1).should be_false }
39
+
40
+ it { @p1.binary_equal?(@c1).should be_false }
41
+ it { @p1.same_as?(@c1).should be_false }
42
+
43
+ end
44
+
45
+ end
@@ -39,28 +39,28 @@ describe "Common Functions" do
39
39
  it { @p1.distance_spheroid_to(@p2).should be_close(627129.50,0.01) }
40
40
  it { @p1.distance_spheroid_to(@p2).should be_close(627129.502639041, 0.000001) }
41
41
  it { @p1.distance_spheroid_to(@p3).should be_close(1096324.48117672, 0.000001) }
42
-
42
+
43
43
  it { @p1.should_not be_inside(@c1) }
44
44
  it { @p1.should be_outside(@c1) }
45
45
  it { @p1.should be_inside_circle(2.0,2.0,20.0) }
46
46
  it { @p1.should_not be_inside_circle(50,50,2) }
47
47
  it { @p1.should be_in_bounds(@s1) }
48
48
  it { @p3.should_not be_in_bounds(@s1, 1) }
49
- it { @p4.in_bounds?(@s3, 0.01).should be_false }
50
-
49
+ it { @p4.in_bounds?(@s3, 0.01).should be_false }
50
+
51
51
  it { @p1.azimuth(@p2).should be_close(0.785398163397448,0.000001) }
52
52
  it { @p1.azimuth(@s2).should raise_error }
53
53
  it { @p1.disjoint?(@s2).should be_true }
54
54
  it { @p3.polygonize.geometries.should be_empty }
55
- it { @p4.where_on_line(@s3).should be_close(0.335, 0.0001) }
55
+ it { @p4.where_on_line(@s3).should be_close(0.335, 0.0001) }
56
56
  it { @s3.locate_point(@p4).should be_close(0.335, 0.1)}
57
57
  it { @s3.interpolate_point(0.335).x.should be_close(18.05, 0.01) }
58
-
58
+
59
59
  it { @p1.relate?(@s3, "T*T***FF*").should be_false }
60
60
  it { @p1.relate?(@s3).should eql("FF0FFF102") }
61
61
 
62
62
  it "should transform srid" do
63
- @p1.geom = @p1.transform(29101)
63
+ @p1.geom = @p1.transform(29101)
64
64
  @p1.geom.srid.should eql(29101)
65
65
  end
66
66
 
@@ -68,6 +68,10 @@ describe "Common Functions" do
68
68
  @p1.where_on_line(@s1).should eql(0.0)
69
69
  end
70
70
 
71
+ it "should see in what fraction of the ls it is" do
72
+ @p2.where_on_line(@s2).should be_close(0.3333, 0.1)
73
+ end
74
+
71
75
  end
72
76
 
73
77
  describe "Polygon" do
@@ -83,14 +87,18 @@ describe "Common Functions" do
83
87
  it "should find one city (first) that contains a point" do
84
88
  City.contain(@p4.geom, 4326).data.should eql("City1")
85
89
  end
86
-
90
+
87
91
  it { @c2.should be_closed }
92
+ it { @c2.dimension.should eql(2) }
93
+
88
94
  it { @c3.area.should be_close(1093.270089, 0.1) }
89
95
  it { @c2.area.should be_close(1159.5, 0.1) }
96
+ it { @c2.area(32640).should be_close(5852791139841.2, 0.01) }
90
97
 
91
- it { @c2.dimension.should eql(2) }
92
98
  it { @c2.perimeter.should be_close(219.770013855493, 0.1) }
99
+ it { @c2.perimeter(32640).should be_close(23061464.4268903, 0.1) }
93
100
  it { @c2.perimeter3d.should be_close(219.770013855493, 0.1) }
101
+
94
102
  it { @c1.contains?(@p1).should be_false }
95
103
  it { @c1.contains?(@p4).should be_true }
96
104
 
@@ -143,9 +151,14 @@ describe "Common Functions" do
143
151
  it { @c2.disjoint?(@p2).should be_true }
144
152
  it { @c3.polygonize.should have(2).geometries }
145
153
 
154
+ it "should acts as jack" do
155
+ @c2.segmentize(0.1).should be_instance_of(Polygon)
156
+ end
157
+
158
+
146
159
  # weird...
147
160
  # it do
148
- # @c1.disjoint?(@s2).should be_true
161
+ # @c1.disjoint?(@p2).should be_true
149
162
  # end
150
163
 
151
164
  end
@@ -241,7 +254,7 @@ describe "Common Functions" do
241
254
 
242
255
  it do @s1.locate_point(@p1).should eql(0.0) end
243
256
  it do @s1.locate_point(@p2).should eql(1.0) end
244
-
257
+
245
258
  it "should simplify a line" do
246
259
  @s3.simplify.points.length.should eql(2)
247
260
  end
@@ -258,7 +271,7 @@ describe "Common Functions" do
258
271
  it { @s1.overlaps?(@s2).should be_false }
259
272
  it { @s1.convex_hull.should be_instance_of(LineString) }
260
273
  it { @s1.line_substring(0.2,0.5).should be_instance_of(LineString) }
261
-
274
+
262
275
  it do
263
276
  @s1.interpolate_point(0.7).should be_instance_of(Point)
264
277
  @s1.interpolate_point(0.7).x.should be_close(1.7,0.1)
@@ -275,7 +288,10 @@ describe "Common Functions" do
275
288
  @s2.build_area.should be_nil
276
289
  end
277
290
 
291
+ it "should acts as jack" do
292
+ @s2.segmentize(0.1).should be_instance_of(LineString)
293
+ end
294
+
278
295
  end
279
296
 
280
297
  end
281
-
@@ -2,22 +2,32 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
3
  describe "PostgisFunctions" do
4
4
  before(:all) do
5
- #load_schema
6
- @c1 ||= City.create!(:data => "City1", :geom => Polygon.from_coordinates([[[12,45],[45,41],[4,1],[12,45]],[[2,5],[5,1],[14,1],[2,5]]],4326))
5
+ #load_schema
6
+ @c1 ||= City.create!(:data => "City1", :geom => Polygon.from_coordinates([[[12,45],[45,42],[4,1],[12,45]],[[2,5],[5,1],[14,1],[2,5]]],4326))
7
7
  @s1 ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[-43,-20],[-42,-28]],4326))
8
- @p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(-43,-22,4326))
8
+ @p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(-43,-22,4326))
9
9
  end
10
10
 
11
11
  describe "Common Mix" do
12
-
12
+
13
13
  it "should calculate distance point to line" do
14
14
  @p1.distance_to(@s1).should be_close(0.248069469178417, 0.00000001)
15
15
  end
16
-
16
+
17
17
  it "should calculate inside a city" do
18
18
  @p1.should_not be_inside(@c1)
19
19
  end
20
-
20
+
21
+ it { @c1.area(32640).should be_close(9165235788987.37, 0.01) }
22
+
23
+ it { @c1.area.should be_close(720.0, 0.1) }
24
+
25
+ it { @p1.should be_strictly_left_of(@c1) }
26
+
27
+ it { @s1.length.should be_close(8.06225774829855, 0.001) }
28
+
29
+ it { @s1.length_spheroid.should be_close(891883.597963462,0.0001) }
30
+
21
31
  end
22
32
 
23
33
  #TODO is sorted rspec helper
data/spec/spec.opts CHANGED
@@ -2,4 +2,4 @@
2
2
  --format RspecSpinner::Spinner
3
3
  --timeout
4
4
  20
5
- --diff
5
+ --diff
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postgis_adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
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: 2009-01-10 00:00:00 -02:00
12
+ date: 2009-02-16 00:00:00 -03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency