Skip to content

Commit

Permalink
Merge branch 'master' of github.com:nofxx/postgis_adapter
Browse files Browse the repository at this point in the history
* 'master' of github.com:nofxx/postgis_adapter:
  fix AR new records fail and bump
  bump version
  add merge line
  fix specs
  added precision and bounding box support for as_geo_json (http://postgis.refractions.net/documentation/manual-svn/ST_AsGeoJSON.html)

Conflicts:
	spec/spec_helper.rb
  • Loading branch information
nofxx committed Feb 26, 2010
2 parents 0d1913b + 0575fc2 commit b2b0301
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 36 deletions.
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
0.7.2
0.7.8
2 changes: 1 addition & 1 deletion lib/postgis_adapter/acts_as_geom.rb
Expand Up @@ -23,7 +23,7 @@ def has_geom(*geom)
send :include, case geom[0].values[0]
when :point then PointFunctions
when :polygon then PolygonFunctions
when :line_string then LineStringFunctions
when :line_string, :multi_line_string then LineStringFunctions
end unless geom[0].kind_of? Symbol
end
alias :acts_as_geom :has_geom
Expand Down
10 changes: 7 additions & 3 deletions lib/postgis_functions.rb
Expand Up @@ -38,7 +38,8 @@ def geo_columns
# DistanceSphere/Spheroid => meters
#
def construct_geometric_sql(type,geoms,options)
not_db, on_db = geoms.partition { |g| g.is_a? Geometry }
not_db, on_db = geoms.partition { |g| g.is_a?(Geometry) || g.new_record? }
not_db.map! {|o| o.respond_to?(:new_record?) ? o.geom : o }

tables = on_db.map do |t| {
:name => t.class.table_name,
Expand All @@ -50,13 +51,15 @@ def construct_geometric_sql(type,geoms,options)
# Implement a better way for options?
if options.instance_of? Hash
transform = options.delete(:transform)
stcollect = options.delete(:stcollect)
options = nil
end

fields = tables.map { |f| "#{f[:uid]}.#{f[:column]}" } # W1.geom
fields << not_db.map { |g| "'#{g.as_hex_ewkb}'::geometry"} unless not_db.empty?
fields.map! { |f| "ST_Transform(#{f}, #{transform})" } if transform # ST_Transform(W1.geom,x)
conditions = tables.map { |f| "#{f[:uid]}.id = #{f[:id]}" } # W1.id = 5
fields.map! { |f| "ST_Union(#{f})" } if stcollect # ST_Transform(W1.geom,x)
conditions = tables.map {|f| "#{f[:uid]}.id = #{f[:id]}" } # W1.id = 5
tables.map! { |f| "#{f[:name]} #{f[:uid]}" } # streets W1

#
Expand All @@ -73,6 +76,7 @@ def construct_geometric_sql(type,geoms,options)
fields = fields.join(" #{options} ")
end


sql = "SELECT #{opcode}(#{fields}) "
sql << "FROM #{tables.join(",")} " unless tables.empty?
sql << "WHERE #{conditions.join(" AND ")}" unless conditions.empty?
Expand Down Expand Up @@ -100,7 +104,7 @@ def execute_geometrical_calculation(operation, subject, options) #:nodoc:
GeoRuby::SimpleFeatures::Geometry.from_hex_ewkb(value) rescue value
end
rescue Exception => e
raise StandardError, "#{e}"
raise StandardError, e.to_s #+ e.backtrace.inspect
end

# Get a unique ID for tables
Expand Down
19 changes: 16 additions & 3 deletions lib/postgis_functions/common.rb
Expand Up @@ -329,6 +329,9 @@ def touches? other
postgis_calculate(:touches, [self, other])
end

def st_collect(other=nil)
postgis_calculate(:collect, [self, other])
end
#
# The convex hull of a geometry represents the minimum closed geometry that
# encloses all geometries within the set.
Expand Down Expand Up @@ -506,8 +509,8 @@ def to_utm
#
# http://geojson.org/
#
def as_geo_json
postgis_calculate(:AsGeoJSON, self)
def as_geo_json(precision=15, bbox=0)
postgis_calculate(:AsGeoJSON, self, [precision, bbox])
end


Expand Down Expand Up @@ -687,9 +690,19 @@ def line_substring(s,e)
# #float ST_Max_Distance(geometry g1, geometry g2);
# postgis_calculate(:max_distance, [self, other])
#end
end

#
# Returns a (set of) LineString(s) formed by sewing together a MULTILINESTRING.
#
# Only use with MULTILINESTRING/LINESTRINGs. If you feed a polygon or geometry collection into this function, it will return an empty GEOMETRYCOLLECTION
#
# Returns geometry ST_LineMerge(geometry amultilinestring);
#
def line_merge
postgis_calculate(:LineMerge, self, { :stcollect => self})
end

end
#
#
#
Expand Down
15 changes: 8 additions & 7 deletions postgis_adapter.gemspec
@@ -1,15 +1,15 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-

Gem::Specification.new do |s|
s.name = %q{postgis_adapter}
s.version = "0.7.2"
s.version = "0.7.7"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Marcos Piccinini"]
s.date = %q{2009-10-18}
s.date = %q{2010-01-29}
s.description = %q{Execute PostGIS functions on Active Record}
s.email = %q{x@nofxx.com}
s.extra_rdoc_files = [
Expand Down Expand Up @@ -55,12 +55,12 @@ Gem::Specification.new do |s|
"spec/db/schema_postgis.rb",
"spec/postgis_adapter/acts_as_geom_spec.rb",
"spec/postgis_adapter/common_spatial_adapter_spec.rb",
"spec/postgis_functions_spec.rb",
"spec/spec_helper.rb",
"spec/postgis_adapter_spec.rb",
"spec/postgis_functions/bbox_spec.rb",
"spec/postgis_functions/class_spec.rb",
"spec/postgis_functions/common_spec.rb",
"spec/postgis_functions/bbox_spec.rb"
"spec/postgis_functions_spec.rb",
"spec/spec_helper.rb"
]

if s.respond_to? :specification_version then
Expand All @@ -73,3 +73,4 @@ Gem::Specification.new do |s|
else
end
end

4 changes: 4 additions & 0 deletions spec/db/models_postgis.rb
Expand Up @@ -52,6 +52,10 @@ class Street < ActiveRecord::Base
acts_as_geom :geom => :line_string
end

class Road < ActiveRecord::Base
acts_as_geom :geom => :multi_line_string
end

class CommonGeo < ActiveRecord::Base
acts_as_geom :geom => :point
end
Expand Down
30 changes: 18 additions & 12 deletions spec/db/schema_postgis.rb
Expand Up @@ -3,53 +3,53 @@

create_table "table_points", :force => true do |t|
t.string "data"
t.point "geom", :null=>false
t.point "geom", :null=>false, :srid => 4326
end

create_table "table_keyword_column_points", :force => true do |t|
t.point "location", :null => false
t.point "location", :null => false, :srid => 4326
end

create_table "table_line_strings", :force => true do |t|
t.integer "value"
t.line_string "geom", :null=>false
t.line_string "geom", :null=>false, :srid => 4326
end

create_table "table_polygons", :force => true do |t|
t.polygon "geom", :null=>false
t.polygon "geom", :null=>false, :srid => 4326
end

create_table "table_multi_points", :force => true do |t|
t.multi_point "geom", :null=>false
t.multi_point "geom", :null=>false, :srid => 4326
end

create_table "table_multi_line_strings", :force => true do |t|
t.multi_line_string "geom", :null=>false
t.multi_line_string "geom", :null=>false, :srid => 4326
end

create_table "table_multi_polygons", :force => true do |t|
t.multi_polygon "geom", :null=>false
t.multi_polygon "geom", :null=>false, :srid => 4326
end

create_table "table_geometries", :force => true do |t|
t.geometry "geom", :null=>false
t.geometry "geom", :null=>false, :srid => 4326
end

create_table "table_geometry_collections", :force => true do |t|
t.geometry_collection "geom", :null=>false
t.geometry_collection "geom", :null=>false, :srid => 4326
end

create_table "table3dz_points", :force => true do |t|
t.column "data", :string
t.point "geom", :null => false , :with_z => true
t.point "geom", :null => false , :with_z => true, :srid => 4326
end

create_table "table3dm_points", :force => true do |t|
t.point "geom", :null => false , :with_m => true
t.point "geom", :null => false , :with_m => true, :srid => 4326
end

create_table "table4d_points", :force => true do |t|
t.point "geom", :null => false, :with_m => true, :with_z => true
t.point "geom", :null => false, :with_m => true, :with_z => true, :srid => 4326
end

create_table "table_srid_line_strings", :force => true do |t|
Expand Down Expand Up @@ -78,6 +78,12 @@
t.line_string :geom, :null => false, :srid => 4326
end

create_table :roads, :force => true do |t|
t.string :data, :limit => 100
t.integer :value
t.multi_line_string :geom, :null => false, :srid => 4326
end

create_table :common_geos, :force => true do |t|
t.string :data, :limit => 100
t.integer :value
Expand Down
8 changes: 4 additions & 4 deletions spec/postgis_adapter/common_spatial_adapter_spec.rb
Expand Up @@ -40,7 +40,7 @@ class Viewpark < ActiveRecord::Base; end

before(:all)do
ActiveRecord::Schema.define do
add_column "parks","geom2", :multi_point
add_column "parks","geom2", :multi_point, :srid => 4326
end
end

Expand All @@ -55,7 +55,7 @@ class Viewpark < ActiveRecord::Base; end
col.geometry_type.should eql(:multi_point)
col.type.should eql(:geometry)
col.null.should be_true
col.srid.should eql(-1)
col.srid.should eql(4326)
col.with_z.should be_false
col.with_m.should be_false
end
Expand Down Expand Up @@ -159,7 +159,7 @@ class Viewpark < ActiveRecord::Base; end
create_table "parks", :force => true do |t|
t.column "data" , :string, :limit => 100
t.column "value", :integer
t.column "geom", :point,:null=>false
t.column "geom", :point,:null=>false, :srid => 4326
end
end

Expand Down Expand Up @@ -246,7 +246,7 @@ class Viewpark < ActiveRecord::Base; end
[144.819402,13.568565],[144.822373,13.572223],[144.8242032,13.57381149],
[144.82634,13.575666],[144.83416,13.590365],[144.83514,13.595657],
[144.834284,13.59652],[144.834024,13.598031],[144.83719,13.598061],
[144.857742,13.598263]]]).to_fixture_format.split(/\s+/).should eql(["0103000020FFFFFFFF0100000020000000FBCC599F721B62404ED026874F322B40056A3178981B6240BF61A2410A2E2B406B10E676AF1B6240E486DF4DB72C2B40BC7A15199D1B6240F701486DE22C2B40CE893DB48F1B62400E828E56B52C2B40BA84436F711B624054C37E4FAC2B2B407862D68B211B62408F183DB7D0252B40D8817346141B6240C51D6FF25B242B40BFB7E9CFFE1A624071FF91E9D0212B401EA33CF3F21A624024F1F274AE202B408EEA7420EB1A6240ED4ACB48BD1F2B4058E20165D31A6240BEBC00FBE81C2B40A3586E69B51A6240E6E5B0FB8E192B40452BF702B31A6240FE2B2B4D4A192B40CA32C4B1AE1A624084B872F6CE182B403291D26C9E1A62408B8C0E48C2162B4072E14048961A624014B35E0CE5142B403FA88B144A1A6240732EC55565172B405CBA38E0E9196240344179C48D1A2B402C2AE274121A624005C58F31771D2B40892650C4221A62406D62793EA01F2B40FDBD141E341A62405D328E91EC212B40DD088B8A381A6240EC4CA1F31A232B40A1832EE1501A6240BB09BE69FA242B4046A863DF5F1A6240F23C9F9ECA252B400D6C9560711A624099D6A6B1BD262B4034F44F70B11A6240F5673F52442E2B409B728577B91A624056444DF4F9302B406FF25B74B21A6240E1D1C6116B312B4088821953B01A624005FD851E31322B4039D1AE42CA1A6240AF06280D35322B40FBCC599F721B62404ED026874F322B40"])
[144.857742,13.598263]]]).to_fixture_format.split(/\s+/).should eql(["0103000020E61000000100000020000000FBCC599F721B62404ED026874F322B40056A3178981B6240BF61A2410A2E2B406B10E676AF1B6240E486DF4DB72C2B40BC7A15199D1B6240F701486DE22C2B40CE893DB48F1B62400E828E56B52C2B40BA84436F711B624054C37E4FAC2B2B407862D68B211B62408F183DB7D0252B40D8817346141B6240C51D6FF25B242B40BFB7E9CFFE1A624071FF91E9D0212B401EA33CF3F21A624024F1F274AE202B408EEA7420EB1A6240ED4ACB48BD1F2B4058E20165D31A6240BEBC00FBE81C2B40A3586E69B51A6240E6E5B0FB8E192B40452BF702B31A6240FE2B2B4D4A192B40CA32C4B1AE1A624084B872F6CE182B403291D26C9E1A62408B8C0E48C2162B4072E14048961A624014B35E0CE5142B403FA88B144A1A6240732EC55565172B405CBA38E0E9196240344179C48D1A2B402C2AE274121A624005C58F31771D2B40892650C4221A62406D62793EA01F2B40FDBD141E341A62405D328E91EC212B40DD088B8A381A6240EC4CA1F31A232B40A1832EE1501A6240BB09BE69FA242B4046A863DF5F1A6240F23C9F9ECA252B400D6C9560711A624099D6A6B1BD262B4034F44F70B11A6240F5673F52442E2B409B728577B91A624056444DF4F9302B406FF25B74B21A6240E1D1C6116B312B4088821953B01A624005FD851E31322B4039D1AE42CA1A6240AF06280D35322B40FBCC599F721B62404ED026874F322B40"])
end

end
Expand Down
49 changes: 48 additions & 1 deletion spec/postgis_functions/common_spec.rb
Expand Up @@ -8,6 +8,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))
@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))
@s1 ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[1,1],[2,2]],4326))
@sx ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[2,2],[4,4]],4326))
@s2 ||= Street.create!(:data => "Street2", :geom => LineString.from_coordinates([[4,4],[7,7]],4326))
@s3 ||= Street.create!(:data => "Street3", :geom => LineString.from_coordinates([[8,8],[18,18],[20,20],[25,25],[30,30],[38,38]],4326))
@s4 ||= Street.create!(:data => "Street4", :geom => LineString.from_coordinates([[10,8],[15,18]],4326))
Expand All @@ -16,6 +17,9 @@
@p3 ||= Position.create!(:data => "Point3", :geom => Point.from_x_y(8,8,4326))
@p4 ||= Position.create!(:data => "Point4", :geom => Point.from_x_y(18.1,18,4326))
@p5 ||= Position.create!(:data => "Point5", :geom => Point.from_x_y(30,30,4326))
@m1 ||= Road.create(:data => "MG-050", :geom => MultiLineString.from_line_strings([@s1.geom, @sx.geom]))
@m2 ||= Road.create(:data => "MG-050", :geom => MultiLineString.from_line_strings([@s3.geom, @s4.geom]))
@p6 ||= Position.create!(:data => "Point6", :geom => Point.from_x_y(30.9999,30.9999,4326))
end

describe "Point" do
Expand Down Expand Up @@ -102,9 +106,18 @@
it "should export as GeoJSON" do
@p1.as_geo_json.should eql("{\"type\":\"Point\",\"coordinates\":[1,1]}")
end

it "should export as GeoJSON with variable precision" do
@p6.as_geo_json(1).should eql("{\"type\":\"Point\",\"coordinates\":[31,31]}")
end

it "should export as GeoJSON with variable precision and bounding box" do
@p6.as_geo_json(1,1).should eql("{\"type\":\"Point\",\"bbox\":[31.0,31.0,31.0,31.0],\"coordinates\":[31,31]}")
end
end



# it { @p3.x.should be_close(8.0, 0.1) }
# it { @p3.y.should be_close(8.0, 0.1) }
# it { @p3.z.should be_close(0.0, 0.1) }
Expand Down Expand Up @@ -239,6 +252,10 @@
end
end

it "should have 1 geometry" do
@s1.should_not respond_to(:geometries)
end

it "should intersect with linestring" do
@s4.intersects?(@s3).should be_true
end
Expand Down Expand Up @@ -293,7 +310,6 @@
@s1.as_geo_json.should eql("{\"type\":\"LineString\",\"coordinates\":[[1,1],[2,2]]}")
end
end

end

describe "More Distance" do
Expand Down Expand Up @@ -370,6 +386,37 @@
str.geom[1].x.should be_close(7,0.0000001)
str.geom[1].y.should be_close(7,0.0000001)
end

describe "MultiLineString" do

it "should write nicely" do
@m1.geom.should be_instance_of(MultiLineString)
end

it "should have 2 geometries" do
@m1.geom.should have(2).geometries
end

it "should have 2 points on the geometry" do
@m1.geom.geometries[0].length.should eql(2)
end

it "should calculate multi line string length" do
@m1.length_spheroid.should be_close(470464.54, 0.01)
end

it "should line merge!" do
merged = @m1.line_merge
merged.should be_instance_of(LineString)
merged.length.should eql(3)
end

it "should line merge collect" do
pending
co = @m2.line_merge
co.should be_instance_of(LineString)
end
end
end

end
9 changes: 8 additions & 1 deletion spec/postgis_functions_spec.rb
Expand Up @@ -31,11 +31,18 @@
@p1.distance_to(Point.from_x_y(5,5,4326)).should be_close(55.0726792520575, 0.001)
end

it "should work with unsaved objects" do
ss = Street.new(:data => "Street1", :geom => LineString.from_coordinates([[-44,-21],[-43,-29]],4326))
ss.length_spheroid.should be_close(891908.39, 0.01)
end

it { @c1.area(32640).should be_close(9165235788987.37, 0.01) }

it { @c1.area.should be_close(720.0, 0.1) }

it { @p1.should be_strictly_left_of(@c1) }
it "should be strictly left of city" do
@p1.should be_strictly_left_of(@c1)
end

it { @s1.length.should be_close(8.06225774829855, 0.001) }

Expand Down

0 comments on commit b2b0301

Please sign in to comment.