Skip to content

Commit

Permalink
Put postgis errors on the exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
nofxx committed Dec 10, 2008
1 parent c90ac9e commit 4bf602c
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 96 deletions.
2 changes: 1 addition & 1 deletion README.markdown
Expand Up @@ -286,7 +286,7 @@ Any questions, enhancement proposals, bug notifications or corrections:

### PostGis Adapter

http://nofxx.lighthouseapp.com/projects/20712-postgis_adapter
[Project Tracker](http://nofxx.lighthouseapp.com/projects/20712-postgis_adapter)

### SpatialAdapter

Expand Down
35 changes: 20 additions & 15 deletions lib/postgis_functions.rb
Expand Up @@ -22,9 +22,11 @@ module PostgisFunctions

EARTH_SPHEROID = "'SPHEROID[\"IERS_2003\",6378136.6,298.25642]'"

def postgis_calculate(operation, subject, options = nil)
subject = [subject] unless subject.respond_to?(:map)
return execute_geometrical_calculation(operation, subject, options)
def postgis_calculate(operation, subjects, options = nil)
subjects = [subjects] unless subjects.respond_to?(:map)
return execute_geometrical_calculation(operation, subjects, options)
rescue Exception => e
raise StandardError, "#{e}"
end


Expand All @@ -47,25 +49,27 @@ def construct_geometric_sql(type,geoms,options)
:id => t[:id] }
end

fields = tables.map { |f| "#{f[:uid]}.geom" } # W1.geom
froms = tables.map { |f| "#{f[:class]} #{f[:uid]}" } # streets W1
wheres = tables.map { |f| "#{f[:uid]}.id = #{f[:id]}" } # W1.id = 5

# BBox => SELECT (A <> B)
# Data => SELECT Fun(A,B)
unless type == :bbox
fields = tables.map { |f| "#{f[:uid]}.geom" } # W1.geom
conditions = tables.map { |f| "#{f[:uid]}.id = #{f[:id]}" } # W1.id = 5
tables.map! { |f| "#{f[:class]} #{f[:uid]}" } # streets W1

#
# Data => SELECT Func(A,B)
# BBox => SELECT (A <=> B)
#
if type == :bbox
opcode = nil
s_join = " #{options} "
else
opcode = type.to_s
opcode = "ST_#{opcode}" unless opcode =~ /th3d|pesinter/
s_join = ","
fields << options if options
else
opcode = nil
s_join = " #{options} "
end

sql = "SELECT #{opcode}(#{fields.join(s_join)}) "
sql << "FROM #{froms.join(",")} " if froms
sql << "WHERE #{wheres.join(" AND ")}" if wheres
sql << "FROM #{tables.join(",")} " if tables
sql << "WHERE #{conditions.join(" AND ")}" if conditions
#p sql; sql
end

Expand All @@ -78,6 +82,7 @@ def construct_geometric_sql(type,geoms,options)
#
def execute_geometrical_calculation(operation, subject, options) #:nodoc:
value = connection.select_value(construct_geometric_sql(operation, subject, options))
return nil unless value
if value =~ /^\D/
{"f" => false, "t" => true}[value]
else
Expand Down
14 changes: 12 additions & 2 deletions lib/postgis_functions/common.rb
Expand Up @@ -294,8 +294,6 @@ def intersection other
#
def overlaps? other
postgis_calculate(:overlaps, [self, other])
rescue
ActiveRecord::StatementInvalid
end

# True if the geometries have at least one point in common,
Expand Down Expand Up @@ -329,6 +327,18 @@ def convex_hull
postgis_calculate(:convexhull, self)
end

#
# Creates an areal geometry formed by the constituent linework of given geometry.
# The return type can be a Polygon or MultiPolygon, depending on input.
# If the input lineworks do not form polygons NULL is returned. The inputs can
# be LINESTRINGS, MULTILINESTRINGS, POLYGONS, MULTIPOLYGONS, and GeometryCollections.
#
# Returns Boolean ST_BuildArea(geometry A);
#
def build_area
postgis_calculate(:buildarea, self)
end

#
# Returns true if this Geometry has no anomalous geometric points, such as
# self intersection or self tangency.
Expand Down
2 changes: 0 additions & 2 deletions lib/postgis_functions/point.rb
Expand Up @@ -70,8 +70,6 @@ def distance_sphere_to(other)
#
def distance_spheroid_to(other, spheroid = EARTH_SPHEROID)
postgis_calculate(:distance_spheroid, [self, other], spheroid)
rescue
ActiveRecord::StatementInvalid
end

#
Expand Down
164 changes: 92 additions & 72 deletions spec/postgis_functions/linestring_spec.rb
Expand Up @@ -24,23 +24,38 @@
Street.longest.data.should == "Street3"
end

it do
@s1.length.should be_close(1.4142135623731, 0.000001)
end
describe "Length" do

it do
@s1.length.should be_close(1.4142135623731, 0.000001)
end

it do
@s2.length.should be_close(4.2, 0.1)
end
it do
@s2.length.should be_close(4.2, 0.1)
end

it do
@s3.length.should be_close(42.4264068, 0.001)
it do
@s3.length.should be_close(42.4264068, 0.001)
end

it "3d length" do
@s1.length_3d.should be_close(1.4142135623731,0.0001)
end

it do
@s1.length_spheroid.should be_close(156876.1381,0.0001)
end

# it do
# @s1.length_spheroid.in_miles.should be_close(156.876,0.001)
# end
end

it do
@s1.crosses?(@s2).should_not be_true
it "should not cross s2" do
@s1.crosses?(@s2).should be_false
end

it do
it "should cross s3" do
@s4.crosses?(@s3).should be_true
end

Expand All @@ -52,83 +67,84 @@
@s4.touches?(@s3).should be_false
end

it do
it "should intersect with linestring" do
@s4.intersects?(@s3).should be_true
end

it do
it "should not intersect with this linestring" do
@s4.intersects?(@s1).should be_false
end

it do
@s1.envelope.should be_instance_of(Polygon)
end

it "should get a polygon for envelope" do
@s1.envelope.rings[0].points[0].should be_instance_of(Point)
end

it "should get the center" do
@s1.centroid.x.should be_close(1.5,0.01)
@s1.centroid.y.should be_close(1.5,0.01)
end

it "should get the center with the correct srid" do
@s1.centroid.srid.should eql(123)
end

it do
@s1.distance_to(@p3).should be_close(8.48528137423857,0.0001)
end

it do
@p1.distance_spheroid_to(@c3).should raise_error
end

it do
@p3.distance_spheroid_to(@s1).should raise_error
it "intersection with a point" do
@s1.intersection(@p2).should be_instance_of(GeometryCollection)
end


describe "Self" do

it do
@s1.envelope.should be_instance_of(Polygon)
end

it "should get a polygon for envelope" do
@s1.envelope.rings[0].points[0].should be_instance_of(Point)
end

it "should get the center" do
@s1.centroid.x.should be_close(1.5,0.01)
@s1.centroid.y.should be_close(1.5,0.01)
end

it "should get the center with the correct srid" do
@s1.centroid.srid.should eql(123)
end

it "number of points" do
@s3.num_points.should eql(6)
end

it do
@s1.distance_to(@p3).should be_close(8.48,0.01)
end
it "startpoint" do
@s3.start_point.should be_instance_of(Point)
@s3.start_point.x.should be_close(8.0, 0.1)
end

it "number of points" do
@s3.num_points.should eql(6)
end
it "endpoint" do
@s2.end_point.should be_instance_of(Point)
@s2.end_point.x.should be_close(7.0, 0.1)
end

it "startpoint" do
@s3.start_point.should be_instance_of(Point)
@s3.start_point.x.should be_close(8.0, 0.1)
end
it do
@s1.should_not be_envelopes_intersect(@s2)
end

it "endpoint" do
@s2.end_point.should be_instance_of(Point)
@s2.end_point.x.should be_close(7.0, 0.1)
end

it "3d length" do
@s1.length_3d.should be_close(1.4142135623731,0.0001)
it do
@s1.boundary.should be_instance_of(MultiPoint)
end

end

it do
@s1.length_spheroid.should be_close(156876.1381,0.0001)
end
describe "Distance" do

it do
@s1.distance_to(@p3).should be_close(8.48528137423857,0.0001)
end

# it do
# @s1.length_spheroid.in_miles.should be_close(156.876,0.001)
# end
it do
lambda { @p1.distance_spheroid_to(@c3) }.should raise_error
end

it do
@s1.should_not be_envelopes_intersect(@s2)
end
it do
lambda { @p3.distance_spheroid_to(@s1) }.should raise_error
end

it do
@s1.boundary.should be_instance_of(MultiPoint)
end
it do
@s1.distance_to(@p3).should be_close(8.48,0.01)
end



it "intersection with a point" do
@s1.intersection(@p2).should be_instance_of(GeometryCollection)
end

it "should locate a point" do
Expand Down Expand Up @@ -173,7 +189,7 @@
end

it do
@s1.simple?.should be_true
@s1.should be_simple #?.should be_true
end

it do
Expand All @@ -189,11 +205,15 @@
end

it do
@s2.locate_along_measure(1.6).should eql(0.0)
@s2.locate_along_measure(1.6).should be_nil
end

it do
@s2.locate_between_measures(0.1,0.3).should eql(0.0)
@s2.locate_between_measures(0.1,0.3).should be_nil
end

it "should build area" do
@s2.build_area.should be_nil
end

end
3 changes: 2 additions & 1 deletion spec/postgis_functions/point_spec.rb
Expand Up @@ -117,5 +117,6 @@
it do
@p3.polygonize.geometries.should be_empty
end
end

end

2 changes: 1 addition & 1 deletion spec/postgis_functions/polygon_spec.rb
Expand Up @@ -84,7 +84,7 @@
end

it "city overlaps point?" do
@c3.overlaps?(@c2).should raise_error # WHY??
lambda { @c3.overlaps?(@c2) }.should raise_error # WHY??
end

it "should get a polygon for envelope" do
Expand Down
17 changes: 15 additions & 2 deletions spec/postgis_functions_spec.rb
Expand Up @@ -4,10 +4,23 @@
before(:all) do
#load_schema
@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]]],123))
@s1 ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[1,1],[2,2]],123))
@p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(1,1,123))
@s1 ||= Street.create!(:data => "Street1", :geom => LineString.from_coordinates([[-43,-20],[-42,-28]],123))
@p1 ||= Position.create!(:data => "Point1", :geom => Point.from_x_y(-43,-22,123))
end

describe "Common Mix" do


it "should calculate distance point to line" do
@p1.distance_to(@s1).should be_close(0.248069469178417, 0.00000001)
end

it "should calculate inside a city" do
@p1.should_not be_inside(@c1)
end


end


#TODO is sorted rspec helper
Expand Down

0 comments on commit 4bf602c

Please sign in to comment.