From 1b67defd54a3ba8cd0a2fb191810bd064d59304b Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Tue, 28 May 2013 23:05:08 +0200 Subject: [PATCH] proper rgeo .to_geo for lines and polygons, with specs fixes #24 --- lib/mongoid_geospatial/wrappers/rgeo.rb | 15 ++- spec/mongoid_geospatial/wrappers/rgeo_spec.rb | 114 +++++++++++++----- 2 files changed, 95 insertions(+), 34 deletions(-) diff --git a/lib/mongoid_geospatial/wrappers/rgeo.rb b/lib/mongoid_geospatial/wrappers/rgeo.rb index 6a586f2..e2f48ab 100644 --- a/lib/mongoid_geospatial/wrappers/rgeo.rb +++ b/lib/mongoid_geospatial/wrappers/rgeo.rb @@ -5,7 +5,6 @@ module Mongoid module Geospatial class Point - def to_geo RGeo::Geographic.spherical_factory.point x, y end @@ -25,23 +24,27 @@ def self.mongoize(obj) end end + class GeometryField + private + def points + self.map do |pair| + RGeo::Geographic.spherical_factory.point(*pair) + end + end + end class Line < GeometryField def to_geo - RGeo::Geographic.spherical_factory.line_string self + RGeo::Geographic.spherical_factory.line_string points end end class Polygon < GeometryField def to_geo - points = self.map do |pair| - RGeo::Geographic.spherical_factory.point *pair - end ring = RGeo::Geographic.spherical_factory.linear_ring points RGeo::Geographic.spherical_factory.polygon ring end - end end end diff --git a/spec/mongoid_geospatial/wrappers/rgeo_spec.rb b/spec/mongoid_geospatial/wrappers/rgeo_spec.rb index 9e78aa0..d001a7e 100644 --- a/spec/mongoid_geospatial/wrappers/rgeo_spec.rb +++ b/spec/mongoid_geospatial/wrappers/rgeo_spec.rb @@ -1,61 +1,119 @@ require "spec_helper" -describe Mongoid::Geospatial::Point do +describe "RGeo Wrapper" do before(:all) do Mongoid::Geospatial.send(:remove_const, 'Point') + Mongoid::Geospatial.send(:remove_const, 'Polygon') + Mongoid::Geospatial.send(:remove_const, 'Line') + load "#{File.dirname(__FILE__)}/../../../lib/mongoid_geospatial/fields/point.rb" + load "#{File.dirname(__FILE__)}/../../../lib/mongoid_geospatial/fields/polygon.rb" + load "#{File.dirname(__FILE__)}/../../../lib/mongoid_geospatial/fields/line.rb" + Object.send(:remove_const, 'Bar') load "#{File.dirname(__FILE__)}/../../models/bar.rb" + + Object.send(:remove_const, 'Farm') + load "#{File.dirname(__FILE__)}/../../models/farm.rb" + + Object.send(:remove_const, 'River') + load "#{File.dirname(__FILE__)}/../../models/river.rb" end - it "should not inferfer with mongoid" do - Bar.create!(name: "Moe's") - Bar.count.should eql(1) + describe Mongoid::Geospatial::Point do + it "should not inferfer with mongoid" do + Bar.create!(name: "Moe's") + Bar.count.should eql(1) + end + + it "should not respond to distance before loading external" do + bar = Bar.create!(location: [5,5]) + bar.location.should_not respond_to(:distance) + end end - it "should not respond to distance before loading external" do - bar = Bar.create!(location: [5,5]) - bar.location.should_not respond_to(:distance) + describe Mongoid::Geospatial::Polygon do + it "should not inferfer with mongoid" do + Farm.create!(name: "Springfield Nuclear Power Plant") + Farm.count.should eql(1) + end + + it "should not respond to to_geo before loading external" do + farm = Farm.create!(area: [[5,5],[6,5],[6,6],[5,6]]) + farm.area.should_not respond_to(:to_geo) + end end + describe Mongoid::Geospatial::Line do + it "should not inferfer with mongoid" do + River.create!(name: "Mississippi") + River.count.should eql(1) + end + + it "should not respond to to_geo before loading external" do + river = River.create!(source: [[5,5],[6,5],[6,6],[5,6]]) + river.source.should_not respond_to(:to_geo) + end + end describe "queryable" do before do Mongoid::Geospatial.use_rgeo Bar.create_indexes + Farm.create_indexes + River.create_indexes end describe "(de)mongoize" do - it "should mongoize array" do - geom = Bar.new(location: [10, -9]).location - geom.class.should eql(Mongoid::Geospatial::Point) - geom.to_geo.class.should eql(RGeo::Geographic::SphericalPointImpl) - geom.x.should be_within(0.1).of(10) - geom.to_geo.y.should be_within(0.1).of(-9) - end + describe Mongoid::Geospatial::Point do + it "should mongoize array" do + geom = Bar.new(location: [10, -9]).location + geom.class.should eql(Mongoid::Geospatial::Point) + geom.to_geo.class.should eql(RGeo::Geographic::SphericalPointImpl) + geom.x.should be_within(0.1).of(10) + geom.to_geo.y.should be_within(0.1).of(-9) + end - it "should mongoize hash" do - geom = Bar.new(location: {x: 10, y: -9}).location - geom.class.should eql(Mongoid::Geospatial::Point) - geom.to_geo.class.should eql(RGeo::Geographic::SphericalPointImpl) - end + it "should mongoize hash" do + geom = Bar.new(location: {x: 10, y: -9}).location + geom.class.should eql(Mongoid::Geospatial::Point) + geom.to_geo.class.should eql(RGeo::Geographic::SphericalPointImpl) + end - it "should accept an RGeo object" do - point = RGeo::Geographic.spherical_factory.point 1, 2 - bar = Bar.create!(location: point) - bar.location.x.should be_within(0.1).of(1) - bar.location.y.should be_within(0.1).of(2) + it "should accept an RGeo object" do + point = RGeo::Geographic.spherical_factory.point 1, 2 + bar = Bar.create!(location: point) + bar.location.x.should be_within(0.1).of(1) + bar.location.y.should be_within(0.1).of(2) + end + + it "should calculate 3d distances by default" do + bar = Bar.create! location: [-73.77694444, 40.63861111 ] + bar2 = Bar.create! location: [-118.40, 33.94] #,:unit=>:mi, :spherical => true) + bar.location.distance(bar2.location).to_i.should be_within(1).of(3978262) + end end - it "should calculate 3d distances by default" do - bar = Bar.create! location: [-73.77694444, 40.63861111 ] - bar2 = Bar.create! location: [-118.40, 33.94] #,:unit=>:mi, :spherical => true) - bar.location.distance(bar2.location).to_i.should be_within(1).of(3978262) + describe Mongoid::Geospatial::Polygon do + it "should mongoize array" do + geom = Farm.create!(area: [[5,5],[6,5],[6,6],[5,6]]).area + geom.class.should eql(Mongoid::Geospatial::Polygon) + geom.to_geo.class.should eql(RGeo::Geographic::SphericalPolygonImpl) + geom.to_geo.to_s.should eq "POLYGON ((5.0 5.0, 6.0 5.0, 6.0 6.0, 5.0 6.0, 5.0 5.0))" + end end + describe Mongoid::Geospatial::Line do + it "should mongoize array" do + geom = River.create!(source: [[5,5],[6,5],[6,6],[5,6]]).source + geom.class.should eql(Mongoid::Geospatial::Line) + geom.to_geo.class.should eql(RGeo::Geographic::SphericalLineStringImpl) + geom.to_geo.to_s.should eq "LINESTRING (5.0 5.0, 6.0 5.0, 6.0 6.0, 5.0 6.0)" + end + end end end end