mongoid_geospatial 2.0.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/README.md +84 -60
- data/lib/mongoid_geospatial.rb +3 -7
- data/lib/mongoid_geospatial/{geospatial → extensions}/core_ext.rb +0 -0
- data/lib/mongoid_geospatial/field_option.rb +3 -4
- data/lib/mongoid_geospatial/fields/geometry_field.rb +34 -0
- data/lib/mongoid_geospatial/fields/line_string.rb +5 -7
- data/lib/mongoid_geospatial/fields/point.rb +18 -33
- data/lib/mongoid_geospatial/fields/polygon.rb +6 -14
- data/lib/mongoid_geospatial/geospatial.rb +20 -25
- data/lib/mongoid_geospatial/version.rb +1 -1
- data/lib/mongoid_geospatial/wrappers/georuby.rb +28 -0
- data/lib/mongoid_geospatial/wrappers/rgeo.rb +32 -0
- data/spec/models/farm.rb +5 -2
- data/spec/models/person.rb +4 -14
- data/spec/models/phone.rb +1 -3
- data/spec/mongoid_geospatial/extensions/core_ext_spec.rb +20 -0
- data/spec/mongoid_geospatial/field_option_spec.rb +11 -0
- data/spec/mongoid_geospatial/fields/line_string_spec.rb +40 -0
- data/spec/mongoid_geospatial/fields/point_spec.rb +136 -10
- data/spec/mongoid_geospatial/fields/polygon_spec.rb +75 -0
- data/spec/mongoid_geospatial/geospatial_spec.rb +88 -3
- data/spec/mongoid_geospatial/wrappers/rgeo_spec.rb +43 -0
- data/spec/spec_helper.rb +5 -21
- metadata +14 -26
- data/lib/mongoid_geospatial/contextual/mongo.rb +0 -118
- data/lib/mongoid_geospatial/criteria.rb +0 -10
- data/lib/mongoid_geospatial/criterion/complex.rb +0 -26
- data/lib/mongoid_geospatial/criterion/inclusion.rb +0 -14
- data/lib/mongoid_geospatial/criterion/near_spatial.rb +0 -52
- data/lib/mongoid_geospatial/criterion/within_spatial.rb +0 -62
- data/lib/mongoid_geospatial/extensions/symbol.rb +0 -46
- data/lib/mongoid_geospatial/finders.rb +0 -5
- data/lib/mongoid_geospatial/geospatial/geo_near_results.rb +0 -140
- data/spec/mongoid_geospatial/contextual/mongo_spec.rb +0 -135
- data/spec/mongoid_geospatial/criterion/complex_spec.rb +0 -15
- data/spec/mongoid_geospatial/criterion/inclusion_spec.rb +0 -375
- data/spec/mongoid_geospatial/criterion/near_spatial_spec.rb +0 -39
- data/spec/mongoid_geospatial/criterion/within_spatial_spec.rb +0 -54
- data/spec/mongoid_geospatial/geospatial/geo_near_results_spec.rb +0 -78
- data/spec/mongoid_geospatial/mongoid_geospatial_spec.rb +0 -83
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'georuby'
|
2
|
+
# require 'mongoid_geospatial/extensions/georuby'
|
3
|
+
|
4
|
+
module Mongoid
|
5
|
+
module Geospatial
|
6
|
+
|
7
|
+
class Point
|
8
|
+
def to_geo
|
9
|
+
GeoRuby::SimpleFeatures::Point.from_x_y(x, y)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
class LineString < Array
|
15
|
+
def to_geo
|
16
|
+
GeoRuby::SimpleFeatures::LineString.from_array(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class Polygon < GeometryField
|
22
|
+
def to_geo
|
23
|
+
GeoRuby::SimpleFeatures::Polygon.from_array(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rgeo'
|
2
|
+
require 'mongoid_geospatial/extensions/rgeo_spherical_point_impl'
|
3
|
+
|
4
|
+
module Mongoid
|
5
|
+
module Geospatial
|
6
|
+
|
7
|
+
class Point
|
8
|
+
def to_geo
|
9
|
+
RGeo::Geographic.spherical_factory.point x, y
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
class LineString < GeometryField
|
15
|
+
def to_geo
|
16
|
+
RGeo::Geographic.spherical_factory.line_string self
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class Polygon < GeometryField
|
22
|
+
def to_geo
|
23
|
+
points = self.map do |pair|
|
24
|
+
RGeo::Geographic.spherical_factory.point *pair
|
25
|
+
end
|
26
|
+
ring = RGeo::Geographic.spherical_factory.linear_ring points
|
27
|
+
RGeo::Geographic.spherical_factory.polygon ring
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/models/farm.rb
CHANGED
@@ -2,8 +2,11 @@ class Farm
|
|
2
2
|
include Mongoid::Document
|
3
3
|
include Mongoid::Geospatial
|
4
4
|
|
5
|
-
field :name,
|
6
|
-
field :
|
5
|
+
field :name, type: String
|
6
|
+
field :geom, type: Point, spatial: true
|
7
|
+
field :area, type: Polygon, spatial: true
|
8
|
+
field :m2, type: Fixnum
|
7
9
|
|
10
|
+
spatial_index :geom
|
8
11
|
spatial_index :area
|
9
12
|
end
|
data/spec/models/person.rb
CHANGED
@@ -3,6 +3,7 @@ class Person
|
|
3
3
|
include Mongoid::MultiParameterAttributes
|
4
4
|
include Mongoid::Timestamps
|
5
5
|
include Mongoid::Versioning
|
6
|
+
include Mongoid::Geospatial
|
6
7
|
|
7
8
|
attr_accessor :mode
|
8
9
|
|
@@ -27,6 +28,9 @@ class Person
|
|
27
28
|
field :reading, :type => Object
|
28
29
|
field :bson_id, :type => bson_object_id_class
|
29
30
|
|
31
|
+
# Geo
|
32
|
+
field :location, :type => Point
|
33
|
+
|
30
34
|
index age: 1
|
31
35
|
index addresses: 1
|
32
36
|
index dob: 1
|
@@ -49,21 +53,7 @@ class Person
|
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
52
|
-
# embeds_many :services
|
53
|
-
|
54
|
-
|
55
|
-
# has_many \
|
56
|
-
# :posts,
|
57
|
-
# :dependent => :delete,
|
58
|
-
# :order => :rating.desc do
|
59
|
-
# def extension
|
60
|
-
# "Testing"
|
61
|
-
# end
|
62
|
-
# end
|
63
|
-
|
64
56
|
accepts_nested_attributes_for :addresses
|
65
|
-
accepts_nested_attributes_for :name, :update_only => true
|
66
|
-
|
67
57
|
|
68
58
|
scope :minor, where(:age.lt => 18)
|
69
59
|
scope :without_ssn, without(:ssn)
|
data/spec/models/phone.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Core Extensions" do
|
4
|
+
|
5
|
+
describe Array do
|
6
|
+
|
7
|
+
it "should have a #to_xy method" do
|
8
|
+
[1,2,3].to_xy.should eql([1.0, 2.0])
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Hash do
|
14
|
+
|
15
|
+
it "should have a #to_xy method" do
|
16
|
+
{ x: 1.1, y: 2.1 }.to_xy.should eql([1.1, 2.1])
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Geospatial::LineString do
|
4
|
+
|
5
|
+
describe "(de)mongoize" do
|
6
|
+
|
7
|
+
it "should support a field mapped as linestring" do
|
8
|
+
river = River.new(source: [[5,5],[6,5],[6,6],[5,6]])
|
9
|
+
river.source.should be_a Mongoid::Geospatial::LineString
|
10
|
+
river.source.should eq([[5,5],[6,5],[6,6],[5,6]])
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should support a field mapped as linestring" do
|
14
|
+
River.create!(source: [[5,5],[6,5],[6,6],[5,6]])
|
15
|
+
River.first.source.should eq([[5,5],[6,5],[6,6],[5,6]])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have a bounding box" do
|
19
|
+
geom = Mongoid::Geospatial::LineString.new [[1,5],[6,5],[6,6],[5,6]]
|
20
|
+
geom.bbox.should eq([[1,5], [6,6]])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have a center point" do
|
24
|
+
geom = Mongoid::Geospatial::LineString.new [[1,1],[1,1],[9,9],[9,9]]
|
25
|
+
geom.center.should eq([5.5,5.5])
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have a radius helper" do
|
29
|
+
geom = Mongoid::Geospatial::LineString.new [[1,1],[1,1],[9,9],[9,9]]
|
30
|
+
geom.radius(10).should eq([[5.5,5.5], 10])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have a radius sphere" do
|
34
|
+
geom = Mongoid::Geospatial::LineString.new [[1,1],[1,1],[9,9],[9,9]]
|
35
|
+
geom.radius_sphere(10)[1].should be_within(0.001).of(0.001569)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -2,30 +2,156 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Mongoid::Geospatial::Point do
|
4
4
|
|
5
|
-
|
5
|
+
it "should not inferfer with mongoid" do
|
6
|
+
Bar.create!(name: "Moe's")
|
7
|
+
Bar.count.should eql(1)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "queryable" do
|
11
|
+
|
12
|
+
before do
|
13
|
+
Bar.create_indexes
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ":near :near_sphere" do
|
17
|
+
|
18
|
+
let!(:berlin) do
|
19
|
+
Bar.create(:name => :berlin, :location => [ 52.30, 13.25 ])
|
20
|
+
end
|
21
|
+
|
22
|
+
let!(:prague) do
|
23
|
+
Bar.create(:name => :prague, :location => [ 50.5, 14.26 ])
|
24
|
+
end
|
25
|
+
|
26
|
+
let!(:paris) do
|
27
|
+
Bar.create(:name => :paris, :location => [ 48.48, 2.20 ])
|
28
|
+
end
|
29
|
+
|
30
|
+
let!(:jim) do
|
31
|
+
Person.new(:location => [ 41.23, 2.9 ])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns the documents sorted closest to furthest" do
|
35
|
+
Bar.where(:location.near => jim.location).should == [ paris, prague, berlin ]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns the documents sorted closest to furthest sphere" do
|
39
|
+
person = Person.new(:location => [ 41.23, 2.9 ])
|
40
|
+
Bar.where(:location.near_sphere => jim.location).should == [ paris, prague, berlin ]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns the documents sorted closest to furthest with max" do
|
44
|
+
Bar.near(location: jim.location).max_distance(location: 10).to_a.should == [ paris ] #, prague, berlin ]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ":within_circle :within_spherical_circle" do
|
50
|
+
let!(:mile1) do
|
51
|
+
Bar.create(:name => 'mile1', :location => [-73.997345, 40.759382])
|
52
|
+
end
|
53
|
+
|
54
|
+
let!(:mile3) do
|
55
|
+
Bar.create(:name => 'mile3', :location => [-73.927088, 40.752151])
|
56
|
+
end
|
57
|
+
|
58
|
+
let!(:mile7) do
|
59
|
+
Bar.create(:name => 'mile7', :location => [-74.0954913, 40.7161472])
|
60
|
+
end
|
61
|
+
|
62
|
+
let!(:mile9) do
|
63
|
+
Bar.create(:name => 'mile9', :location => [-74.0604951, 40.9178011])
|
64
|
+
end
|
65
|
+
|
66
|
+
let!(:elvis) do
|
67
|
+
Person.new(:location => [-73.98, 40.75])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns the documents within a center_circle" do
|
71
|
+
Bar.where(:location.within_circle => [elvis.location, 250.0/Mongoid::Geospatial::EARTH_RADIUS_KM]).to_a.should == [ mile1 ]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns the documents within a center_circle" do
|
75
|
+
Bar.where(:location.within_circle => [elvis.location, 500.0/Mongoid::Geospatial::EARTH_RADIUS_KM]).to_a.should include(mile3)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns the documents within a center_sphere" do
|
79
|
+
Bar.where(:location.within_spherical_circle => [elvis.location, 0.0005]).to_a.should == [ mile1 ]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "returns the documents within a center_sphere" do
|
83
|
+
Bar.where(:location.within_spherical_circle => [elvis.location, 0.5]).to_a.should include(mile9)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "(de)mongoize" do
|
6
90
|
|
7
91
|
it "should mongoize array" do
|
8
92
|
bar = Bar.new(location: [10, -9])
|
9
|
-
bar.location.class.should eql(
|
93
|
+
bar.location.class.should eql(Mongoid::Geospatial::Point)
|
10
94
|
bar.location.x.should be_within(0.1).of(10)
|
11
95
|
bar.location.y.should be_within(0.1).of(-9)
|
12
96
|
end
|
13
97
|
|
14
98
|
it "should mongoize hash" do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
99
|
+
geom = Bar.new(location: {x: 10, y: -9}).location
|
100
|
+
geom.class.should eql(Mongoid::Geospatial::Point)
|
101
|
+
geom.x.should be_within(0.1).of(10)
|
102
|
+
geom.y.should be_within(0.1).of(-9)
|
19
103
|
end
|
20
104
|
|
21
|
-
describe "instantiated" do
|
22
105
|
|
23
|
-
|
106
|
+
describe "methods" do
|
107
|
+
|
108
|
+
it "should have a .to_a" do
|
109
|
+
bar = Bar.create!(location: [3,2])
|
110
|
+
bar.location.to_a[0..1].should == [3.0, 2.0]
|
111
|
+
end
|
24
112
|
|
25
|
-
it "should
|
26
|
-
bar.location
|
113
|
+
it "should have an array [] accessor" do
|
114
|
+
bar = Bar.create!(location: [3,2])
|
115
|
+
bar.location[0].should == 3.0
|
27
116
|
end
|
28
117
|
|
118
|
+
it "should have an ActiveModel symbol accessor" do
|
119
|
+
bar = Bar.create!(location: [3,2])
|
120
|
+
bar[:location].should == [3,2]
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should calculate distance between points" do
|
124
|
+
pending
|
125
|
+
bar = Bar.create!(location: [5,5])
|
126
|
+
bar2 = Bar.create!(location: [15,15])
|
127
|
+
bar.location.distance(bar2.location).should be_within(1).of(1561283.8)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should calculate 3d distances by default" do
|
131
|
+
pending
|
132
|
+
bar = Bar.create! location: [-73.77694444, 40.63861111 ]
|
133
|
+
bar2 = Bar.create! location: [-118.40, 33.94] #,:unit=>:mi, :spherical => true)
|
134
|
+
bar.location.distance(bar2.location).to_i.should be_within(1).of(2469)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
# should raise
|
140
|
+
# geom.to_geo
|
141
|
+
|
142
|
+
describe "with rgeo" do
|
143
|
+
|
144
|
+
describe "instantiated" do
|
145
|
+
|
146
|
+
let(:bar) { Bar.create!(name: 'Vitinho', location: [10,10]) }
|
147
|
+
|
148
|
+
it "should demongoize to rgeo" do
|
149
|
+
bar.location.class.should eql(Mongoid::Geospatial::Point)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
29
155
|
end
|
30
156
|
|
31
157
|
end
|
@@ -2,5 +2,80 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Mongoid::Geospatial::Polygon do
|
4
4
|
|
5
|
+
describe "(de)mongoize" do
|
6
|
+
|
7
|
+
it "should support a field mapped as polygon" do
|
8
|
+
farm = Farm.new(area: [[5,5],[6,5],[6,6],[5,6]])
|
9
|
+
farm.area.should eq([[5,5],[6,5],[6,6],[5,6]])
|
10
|
+
farm.area.should be_a Mongoid::Geospatial::Polygon
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should store as array on mongo" do
|
14
|
+
Farm.create(area: [[5,5],[6,5],[6,6],[5,6]])
|
15
|
+
Farm.first.area.should eq([[5,5],[6,5],[6,6],[5,6]])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have a bounding box" do
|
19
|
+
geom = Mongoid::Geospatial::Polygon.new [[1,5],[6,5],[6,6],[5,6]]
|
20
|
+
geom.bbox.should eq([[1,5], [6,6]])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have a center point" do
|
24
|
+
geom = Mongoid::Geospatial::Polygon.new [[1,1],[1,1],[9,9],[9,9]]
|
25
|
+
geom.center.should eq([5.5,5.5])
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have a radius helper" do
|
29
|
+
geom = Mongoid::Geospatial::Polygon.new [[1,1],[1,1],[9,9],[9,9]]
|
30
|
+
geom.radius(10).should eq([[5.5,5.5], 10])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have a radius sphere" do
|
34
|
+
geom = Mongoid::Geospatial::Polygon.new [[1,1],[1,1],[9,9],[9,9]]
|
35
|
+
geom.radius_sphere(10)[1].should be_within(0.001).of(0.001569)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
describe "with rgeo" do
|
40
|
+
# farm.area.should be_a RGeo::Geographic::SphericalPolygonImpl
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "query" do
|
46
|
+
|
47
|
+
context ":box, :polygon" do
|
48
|
+
|
49
|
+
before do
|
50
|
+
Farm.create_indexes
|
51
|
+
end
|
52
|
+
|
53
|
+
let!(:ranch) do
|
54
|
+
Farm.create(:name => 'Ranch', area: [[1, 1],[3, 3]], :geom => [2, 2])
|
55
|
+
end
|
56
|
+
|
57
|
+
let!(:farm) do
|
58
|
+
Farm.create(name: 'Farm', area: [[47, 1],[49, 1.5],[49, 3],[46, 5]], geom: [47.5, 2.26])
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns the documents within a box" do
|
62
|
+
Farm.where(:geom.within_box => ranch.area ).to_a.should == [ ranch ]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns the documents within a polygon" do
|
66
|
+
Farm.where(:geom.within_polygon => farm.area).to_a.should == [ farm ]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns the documents within a center" do
|
70
|
+
Farm.where(:geom.within_circle => [ranch.geom, 0.4]).first.should eq(ranch)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns the documents within a center_sphere" do
|
74
|
+
Farm.where(:geom.within_spherical_circle => [ranch.geom, 0.1]).first.should eq(ranch)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
5
80
|
|
6
81
|
end
|