postgis_adapter 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/MIT-LICENSE +21 -0
- data/Manifest.txt +36 -0
- data/README.rdoc +311 -0
- data/Rakefile +100 -0
- data/init.rb +1 -0
- data/install.rb +0 -0
- data/lib/postgis_adapter.rb +388 -0
- data/lib/postgis_adapter/acts_as_geom.rb +39 -0
- data/lib/postgis_adapter/common_spatial_adapter.rb +179 -0
- data/lib/postgis_functions.rb +158 -0
- data/lib/postgis_functions/bbox.rb +128 -0
- data/lib/postgis_functions/class.rb +64 -0
- data/lib/postgis_functions/common.rb +438 -0
- data/lib/postgis_functions/linestring.rb +172 -0
- data/lib/postgis_functions/point.rb +89 -0
- data/lib/postgis_functions/polygon.rb +78 -0
- data/postgis_adapter.gemspec +38 -0
- data/rails/init.rb +8 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/acts_as_geom_spec.rb +15 -0
- data/spec/common_spatial_adapter_spec.rb +254 -0
- data/spec/db/database_postgis.yml +4 -0
- data/spec/db/models_postgis.rb +56 -0
- data/spec/db/schema_postgis.rb +86 -0
- data/spec/postgis_adapter_spec.rb +174 -0
- data/spec/postgis_functions/bbox_spec.rb +84 -0
- data/spec/postgis_functions/linestring_spec.rb +219 -0
- data/spec/postgis_functions/point_spec.rb +136 -0
- data/spec/postgis_functions/polygon_spec.rb +146 -0
- data/spec/postgis_functions_spec.rb +51 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +25 -0
- data/uninstall.rb +0 -0
- metadata +121 -0
data/History.txt
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Spatial Adapter Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+georuby@gmail.com>
|
2
|
+
PostGis Adapter Functions (c) 2008 Marcos Piccinini <nofxx>
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
History.txt
|
2
|
+
MIT-LICENSE
|
3
|
+
Manifest.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
init.rb
|
7
|
+
install.rb
|
8
|
+
lib/postgis_adapter.rb
|
9
|
+
lib/postgis_adapter/acts_as_geom.rb
|
10
|
+
lib/postgis_adapter/common_spatial_adapter.rb
|
11
|
+
lib/postgis_functions.rb
|
12
|
+
lib/postgis_functions/bbox.rb
|
13
|
+
lib/postgis_functions/class.rb
|
14
|
+
lib/postgis_functions/common.rb
|
15
|
+
lib/postgis_functions/linestring.rb
|
16
|
+
lib/postgis_functions/point.rb
|
17
|
+
lib/postgis_functions/polygon.rb
|
18
|
+
postgis_adapter.gemspec
|
19
|
+
rails/init.rb
|
20
|
+
script/console
|
21
|
+
script/destroy
|
22
|
+
script/generate
|
23
|
+
spec/acts_as_geom_spec.rb
|
24
|
+
spec/common_spatial_adapter_spec.rb
|
25
|
+
spec/db/database_postgis.yml
|
26
|
+
spec/db/models_postgis.rb
|
27
|
+
spec/db/schema_postgis.rb
|
28
|
+
spec/postgis_adapter_spec.rb
|
29
|
+
spec/postgis_functions/bbox_spec.rb
|
30
|
+
spec/postgis_functions/linestring_spec.rb
|
31
|
+
spec/postgis_functions/point_spec.rb
|
32
|
+
spec/postgis_functions/polygon_spec.rb
|
33
|
+
spec/postgis_functions_spec.rb
|
34
|
+
spec/spec.opts
|
35
|
+
spec/spec_helper.rb
|
36
|
+
uninstall.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
= PostgisAdapter
|
2
|
+
|
3
|
+
A plugin for ActiveRecord which manages the PostGIS geometric columns
|
4
|
+
in a transparent way (that is like the other base data type columns).
|
5
|
+
It also provides a way to manage these columns in migrations.
|
6
|
+
|
7
|
+
This fork adds handy methods to make geometrical calculations on postgis.
|
8
|
+
|
9
|
+
Postgis Manual - http://postgis.refractions.net/documentation/manual-svn
|
10
|
+
|
11
|
+
*PostGIS and Rails 2+ only*.
|
12
|
+
|
13
|
+
|
14
|
+
=== Install
|
15
|
+
|
16
|
+
If you are using Spatial Adapter, *remove it first*.
|
17
|
+
|
18
|
+
|
19
|
+
==== Dependencies
|
20
|
+
|
21
|
+
- georuby
|
22
|
+
- postgres 8.3+
|
23
|
+
- postgis 1.3+
|
24
|
+
|
25
|
+
|
26
|
+
==== As gem:
|
27
|
+
|
28
|
+
sudo gem sources --add http://gems.github.com
|
29
|
+
sudo gem install nofxx-postgis_adapter
|
30
|
+
|
31
|
+
config.gem "nofxx-postgis_adapter", :lib => "postgis_adapter", :source => "http://gems.github.com"
|
32
|
+
|
33
|
+
|
34
|
+
==== As plugin:
|
35
|
+
|
36
|
+
script/plugin install git://github.com/nofxx/postgis_adapter.git
|
37
|
+
|
38
|
+
|
39
|
+
=== How to Use
|
40
|
+
|
41
|
+
Geometric columns in your ActiveRecord models now appear just like
|
42
|
+
any other column of other basic data types. They can also be dumped
|
43
|
+
in ruby schema mode and loaded in migrations the same way as columns
|
44
|
+
of basic types.
|
45
|
+
|
46
|
+
|
47
|
+
=== Model
|
48
|
+
|
49
|
+
class TablePoint < ActiveRecord::Base
|
50
|
+
end
|
51
|
+
|
52
|
+
That was easy! As you see, there is no need to declare a column as geometric.
|
53
|
+
The plugin will get this information by itself.
|
54
|
+
|
55
|
+
Here is an example of PostGIS row creation and access, using the
|
56
|
+
model and the table defined above :
|
57
|
+
|
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
|
63
|
+
|
64
|
+
|
65
|
+
== PostGIS Functions
|
66
|
+
|
67
|
+
Here are this fork additions. To use it:
|
68
|
+
|
69
|
+
|
70
|
+
class Street < ActiveRecord::Base
|
71
|
+
acts_as_geom :line
|
72
|
+
end
|
73
|
+
|
74
|
+
...
|
75
|
+
|
76
|
+
@place = Poi.new( :data => **Point** )
|
77
|
+
@park = Park.new( :area => **Polygon** )
|
78
|
+
@street = Street.new( :line => **LineString** )
|
79
|
+
|
80
|
+
|
81
|
+
=== Play!
|
82
|
+
|
83
|
+
@place.inside?(@park)
|
84
|
+
=> true
|
85
|
+
|
86
|
+
@place.in_bounds?(@park, 0.5) # margin
|
87
|
+
=> false
|
88
|
+
|
89
|
+
@place.outside?(@park)
|
90
|
+
|
91
|
+
@street.crosses?(@park)
|
92
|
+
|
93
|
+
@area.contains?(@place)
|
94
|
+
|
95
|
+
|
96
|
+
Polygons:
|
97
|
+
|
98
|
+
@park.area
|
99
|
+
=> 1345
|
100
|
+
|
101
|
+
@park.contains?(@point)
|
102
|
+
=> true
|
103
|
+
|
104
|
+
@park.overlaps?(@other_park)
|
105
|
+
=> false
|
106
|
+
|
107
|
+
|
108
|
+
Line Strings:
|
109
|
+
|
110
|
+
@street_east.intersects?(@street_west)
|
111
|
+
=> false
|
112
|
+
|
113
|
+
@street_central.length
|
114
|
+
=> 4508.53636
|
115
|
+
|
116
|
+
@street_central.length(:miles)
|
117
|
+
=> 2.81798593
|
118
|
+
|
119
|
+
@street.length_spheroid
|
120
|
+
=> 4.40853636
|
121
|
+
|
122
|
+
|
123
|
+
=== And for classes:
|
124
|
+
|
125
|
+
City.close_to(@point)
|
126
|
+
=> [Array of cities in order by distance...
|
127
|
+
|
128
|
+
Street.close_to(@point)
|
129
|
+
=> [Array streets in order by distance...
|
130
|
+
|
131
|
+
Country.contain(@point)
|
132
|
+
=> The Conutry that contains the point
|
133
|
+
|
134
|
+
Areas.contains(@point)
|
135
|
+
=> [Array of areas contains the point...
|
136
|
+
|
137
|
+
|
138
|
+
=== BBox Support
|
139
|
+
|
140
|
+
@area.strictly_left_of? @point
|
141
|
+
|
142
|
+
@area.overlaps_or_above? @street
|
143
|
+
|
144
|
+
...
|
145
|
+
|
146
|
+
completely_contained_by?
|
147
|
+
completely_contains?
|
148
|
+
overlaps_or_above?
|
149
|
+
overlaps_or_below?
|
150
|
+
overlaps_or_left_of?
|
151
|
+
overlaps_or_right_of?
|
152
|
+
strictly_above?
|
153
|
+
strictly_below?
|
154
|
+
strictly_left_of?
|
155
|
+
strictly_right_of?
|
156
|
+
interacts_with?
|
157
|
+
binary_equal?
|
158
|
+
same_as?
|
159
|
+
|
160
|
+
|
161
|
+
Or use a (almost) postgis like notation:
|
162
|
+
|
163
|
+
@area.bbox "<<", @point
|
164
|
+
|
165
|
+
@area.bbox "|>>", @point
|
166
|
+
|
167
|
+
@area.bbox "@", @park
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
=== Warning
|
172
|
+
|
173
|
+
*To be fixed:*
|
174
|
+
|
175
|
+
This only supports one geom column per model. Still looking for the best way to
|
176
|
+
implement a multi geom.
|
177
|
+
|
178
|
+
http://nofxx.lighthouseapp.com/projects/20712/tickets/3-multiple-geoms-in-model
|
179
|
+
|
180
|
+
|
181
|
+
=== Wiki
|
182
|
+
|
183
|
+
Check out the wiki pages (http://github.com/nofxx/postgis_adapter/wikis).
|
184
|
+
For all functions.
|
185
|
+
|
186
|
+
|
187
|
+
=== Find_by
|
188
|
+
|
189
|
+
find_by_*column* has been redefined when column is of a geometric type.
|
190
|
+
Instead of using the Rails default '=' operator, for which I can't see
|
191
|
+
a definition for MySql spatial datatypes and which performs a bounding
|
192
|
+
box equality test in PostGIS, it uses a bounding box intersection:
|
193
|
+
&& in PostGIS and MBRIntersects in MySQL, which can both make use
|
194
|
+
of a spatial index if one is present to speed up the queries.
|
195
|
+
You could use this query, for example, if you need to display data
|
196
|
+
from the database: You would want only the geometries which are in
|
197
|
+
the screen rectangle and you could use a bounding box query for that.
|
198
|
+
Since this is a common case, it is the default. You have 2 ways to use
|
199
|
+
the find_by_*geom_column*: Either by passing a geometric object directly,
|
200
|
+
or passing an array with the 2 opposite corners of a bounding box
|
201
|
+
(with 2 or 3 coordinates depending of the dimension of the data).
|
202
|
+
|
203
|
+
Park.find_by_geom(LineString.from_coordinates([[1.4,5.6],[2.7,8.9],[1.6,5.6]]))
|
204
|
+
|
205
|
+
or
|
206
|
+
|
207
|
+
Park.find_by_geom([[3,5.6],[19.98,5.9]])
|
208
|
+
|
209
|
+
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
|
+
|
211
|
+
Park.find_by_geom([[3,5.6],[19.98,5.9],123])
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
== Database Tools
|
216
|
+
|
217
|
+
=== Migrations
|
218
|
+
|
219
|
+
Here is an example of code for the creation of a table with a
|
220
|
+
geometric column in PostGIS, along with the addition of a spatial
|
221
|
+
index on the column :
|
222
|
+
|
223
|
+
ActiveRecord::Schema.define do
|
224
|
+
create_table :places do |t|
|
225
|
+
t.string :name
|
226
|
+
t.point :geom, :srid => 123, :with_z => true, :null => false
|
227
|
+
|
228
|
+
t.timestamps
|
229
|
+
end
|
230
|
+
add_index :table_points, :geom, :spatial=>true
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
=== Fixtures
|
235
|
+
|
236
|
+
If you use fixtures for your unit tests, at some point,
|
237
|
+
you will want to input a geometry. You could transform your
|
238
|
+
geometries to a form suitable for YAML yourself everytime but
|
239
|
+
the spatial adapter provides a method to do it for you: +to_yaml+.
|
240
|
+
It works for both MySQL and PostGIS (although the string returned
|
241
|
+
is different for each database). You would use it like this, if
|
242
|
+
the geometric column is a point:
|
243
|
+
|
244
|
+
fixture:
|
245
|
+
id: 1
|
246
|
+
data: HELLO
|
247
|
+
geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>
|
248
|
+
|
249
|
+
|
250
|
+
=== Annotate
|
251
|
+
|
252
|
+
If you are using annotate_models, check out this fork which adds geometrical annotations for PostgisAdapter and SpatialAdapter:
|
253
|
+
|
254
|
+
http://github.com/nofxx/annotate_models
|
255
|
+
|
256
|
+
|
257
|
+
== Geometric data types
|
258
|
+
|
259
|
+
Ruby geometric datatypes are currently made available only through
|
260
|
+
the GeoRuby library (http://georuby.rubyforge.org): This is where the
|
261
|
+
*Point.from_x_y* in the example above comes from. It is a goal
|
262
|
+
of a future release of the Spatial Adapter to support additional
|
263
|
+
geometric datatype libraries, such as Ruby/GEOS, as long as they
|
264
|
+
can support reading and writing of EWKB.
|
265
|
+
|
266
|
+
|
267
|
+
|
268
|
+
=== Warning
|
269
|
+
|
270
|
+
- Since ActiveRecord seems to keep only the string values directly
|
271
|
+
returned from the database, it translates from these to the correct
|
272
|
+
types everytime an attribute is read, which is probably ok for simple
|
273
|
+
types, but might be less than efficient for geometries, since the EWKB
|
274
|
+
string has to be parsed everytime. Also it means you cannot modify the
|
275
|
+
geometry object returned from an attribute directly :
|
276
|
+
|
277
|
+
place = Place.first
|
278
|
+
place.the_geom.y=123456.7
|
279
|
+
|
280
|
+
- Since the translation to a geometry is performed everytime the_geom
|
281
|
+
is read, the change to y will not be saved! You would have to do
|
282
|
+
something like this :
|
283
|
+
|
284
|
+
place = Place.first
|
285
|
+
the_geom = place.the_geom
|
286
|
+
the_geom.y=123456.7
|
287
|
+
place.the_geom = the_geom
|
288
|
+
|
289
|
+
|
290
|
+
== License
|
291
|
+
|
292
|
+
Spatial Adapter for Rails is released under the MIT license.
|
293
|
+
Postgis Adapter is released under the MIT license.
|
294
|
+
|
295
|
+
|
296
|
+
== Support
|
297
|
+
|
298
|
+
Tested using rails 2.2.2 / postgresql 8.3.5 / postgis 1.3.3 / linux / osx
|
299
|
+
|
300
|
+
Any questions, enhancement proposals, bug notifications or corrections:
|
301
|
+
|
302
|
+
|
303
|
+
=== PostgisAdapter
|
304
|
+
|
305
|
+
Project Tracker http://nofxx.lighthouseapp.com/projects/20712-postgis_adapter
|
306
|
+
|
307
|
+
|
308
|
+
=== SpatialAdapter
|
309
|
+
|
310
|
+
|
311
|
+
guilhem.vellut+georuby@gmail.com.
|
data/Rakefile
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
#$:.unshift(File.join(File.dirname(__FILE__) ,'../../gems/georuby/lib/'))
|
2
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
3
|
+
require 'rake'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'active_record'
|
7
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
8
|
+
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
9
|
+
require File.dirname(__FILE__) + '/lib/postgis_adapter'
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)PostgisAdapter::VERSION
|
13
|
+
$hoe = Hoe.new('postgis_adapter', PostgisAdapter::VERSION) do |p|
|
14
|
+
p.developer('Marcos Piccinini', 'x@nofxx.com')
|
15
|
+
p.summary = "Postgis Adapter for Activer Record"
|
16
|
+
p.description = "Postgis Adapter for Activer Record"
|
17
|
+
p.url = "http://github.com/nofxx/postgis_adapter"
|
18
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
19
|
+
# p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
20
|
+
p.rubyforge_name = "postgis_adapter" # TODO this is default value
|
21
|
+
p.extra_deps = [
|
22
|
+
['activerecord','>= 2.0.2'],
|
23
|
+
]
|
24
|
+
p.extra_dev_deps = [
|
25
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
26
|
+
]
|
27
|
+
|
28
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
29
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
30
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
31
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
35
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
36
|
+
|
37
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
38
|
+
# task :default => [:spec, :features]
|
39
|
+
|
40
|
+
desc 'Default: run specs.'
|
41
|
+
task :default => :spec
|
42
|
+
|
43
|
+
desc "Run all specs"
|
44
|
+
Spec::Rake::SpecTask.new do |t|
|
45
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
46
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
47
|
+
unless ENV['NO_RCOV']
|
48
|
+
t.rcov = true
|
49
|
+
t.rcov_dir = 'coverage'
|
50
|
+
t.rcov_opts = ['--html', '--exclude', "\.autotest,schema.rb,init.rb,\.gitignore,spec\/spec_helper.rb,spec\/db/*,#{ENV['GEM_HOME']}"]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Look for TODO and FIXME tags in the code"
|
55
|
+
task :todo do
|
56
|
+
egrep /(FIXME|TODO|TBD)/
|
57
|
+
end
|
58
|
+
|
59
|
+
namespace :db do
|
60
|
+
task :migrate do
|
61
|
+
load('spec/db/schema_postgis.rb')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Generate the documentation"
|
66
|
+
Rake::RDocTask::new do |rdoc|
|
67
|
+
rdoc.rdoc_dir = 'doc/'
|
68
|
+
rdoc.title = "PostGIS Adapter for Rails Documentation"
|
69
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
70
|
+
rdoc.rdoc_files.include('README.rdoc')
|
71
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
72
|
+
end
|
73
|
+
|
74
|
+
# From Rspec Rakefile
|
75
|
+
#
|
76
|
+
def egrep(pattern)
|
77
|
+
Dir['**/*.rb'].each do |fn|
|
78
|
+
count = 0
|
79
|
+
open(fn) do |f|
|
80
|
+
while line = f.gets
|
81
|
+
count += 1
|
82
|
+
if line =~ pattern
|
83
|
+
puts "#{fn}:#{count}:#{line}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
desc "verify_committed, verify_rcov, post_news, release"
|
91
|
+
task :complete_release => [:verify_committed, :post_news, :release]
|
92
|
+
|
93
|
+
desc "Verifies that there is no uncommitted code"
|
94
|
+
task :verify_committed do
|
95
|
+
IO.popen('git status') do |io|
|
96
|
+
io.each_line do |line|
|
97
|
+
raise "\n!!! Do a git commit first !!!\n\n" if line =~ /^#\s*modified:/
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|