mongoid-geospatial 4.0.0 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +2 -0
- data/.rspec +3 -0
- data/.travis.yml +1 -1
- data/Gemfile +11 -10
- data/README.md +21 -32
- data/lib/mongoid/geospatial.rb +46 -13
- data/lib/mongoid/geospatial/fields/{line.rb → line_string.rb} +1 -1
- data/lib/mongoid/geospatial/fields/point.rb +90 -40
- data/lib/mongoid/geospatial/{fields/geometry_field.rb → geometry_field.rb} +30 -3
- data/lib/mongoid/geospatial/version.rb +2 -2
- data/lib/mongoid/geospatial/wrappers/georuby.rb +12 -4
- data/lib/mongoid/geospatial/wrappers/rgeo.rb +16 -9
- data/mongoid-geospatial.gemspec +1 -4
- data/spec/models/river.rb +1 -1
- data/spec/mongoid/geospatial/fields/{line_spec.rb → line_string_spec.rb} +13 -6
- data/spec/mongoid/geospatial/helpers/delegate_spec.rb +4 -4
- data/spec/mongoid/geospatial/wrappers/rgeo_spec.rb +3 -3
- data/spec/spec_helper.rb +2 -1
- metadata +10 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3610388899a7280b932823c0541ac28e1590bc4a
|
4
|
+
data.tar.gz: 884000ab8ac5263b1fde24db7d966e823f9fa554
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cab14e04b4353673b88bafa569743546809c8f7d179f0272ccec68390dd03f6a98923a062ff749043d8ef66a810ad5db20d21d8acc07f10570d0b1b6b92abb5f
|
7
|
+
data.tar.gz: 519caf325d7896a2db2ef706c60e166f67b793a827c0fb2b56965527c6c388b6ffd1ae6364d9602c12fbebe984e74444fcfc60c19bcff0870796a66b65f8a837
|
data/.hound.yml
ADDED
data/.rspec
ADDED
data/.travis.yml
CHANGED
@@ -14,7 +14,7 @@ jdk:
|
|
14
14
|
- oraclejdk7
|
15
15
|
- openjdk7
|
16
16
|
|
17
|
-
env: JRUBY_OPTS="--server -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -J-Xms512m -J-Xmx1024m"
|
17
|
+
env: CI="travis" JRUBY_OPTS="--server -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -J-Xms512m -J-Xmx1024m"
|
18
18
|
|
19
19
|
matrix:
|
20
20
|
allow_failures:
|
data/Gemfile
CHANGED
@@ -2,23 +2,24 @@ source 'http://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec # Specify gem's dependencies in mongoid_geospatial.gemspec
|
4
4
|
|
5
|
-
gem 'pry'
|
6
5
|
gem 'rake'
|
7
|
-
gem 'yard'
|
8
|
-
gem 'mongoid' #, github: 'mongoid/mongoid'
|
9
6
|
|
10
|
-
|
11
|
-
gem '
|
12
|
-
gem '
|
13
|
-
gem '
|
7
|
+
group :test do
|
8
|
+
gem 'pry'
|
9
|
+
gem 'yard'
|
10
|
+
gem 'nokogiri'
|
11
|
+
|
12
|
+
gem 'dbf'
|
13
|
+
gem 'rgeo'
|
14
|
+
gem 'georuby'
|
14
15
|
|
15
|
-
if ENV['CI']
|
16
|
-
gem 'coveralls', require: false
|
17
|
-
else
|
18
16
|
gem 'rspec'
|
17
|
+
|
19
18
|
gem 'rubocop'
|
20
19
|
gem 'fuubar'
|
21
20
|
gem 'guard'
|
22
21
|
gem 'guard-rubocop'
|
23
22
|
gem 'guard-rspec'
|
23
|
+
|
24
|
+
gem 'coveralls', require: false if ENV['CI']
|
24
25
|
end
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
Mongoid Geospatial
|
2
2
|
==================
|
3
3
|
|
4
|
-
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nofxx/mongoid-geospatial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
4
|
|
6
5
|
A Mongoid Extension that simplifies the use of MongoDB spatial features.
|
7
6
|
|
@@ -21,6 +20,7 @@ If you need to: require 'mongoid/geospatial'
|
|
21
20
|
[![Gem Version](https://badge.fury.io/rb/mongoid-geospatial.png)](http://badge.fury.io/rb/mongoid-geospatial)
|
22
21
|
[![Code Climate](https://codeclimate.com/github/nofxx/mongoid-geospatial.png)](https://codeclimate.com/github/nofxx/mongoid-geospatial)
|
23
22
|
[![Coverage Status](https://coveralls.io/repos/nofxx/mongoid-geospatial/badge.png)](https://coveralls.io/r/nofxx/mongoid-geospatial)
|
23
|
+
[![Dependency Status](https://gemnasium.com/nofxx/mongoid-geospatial.svg)](https://gemnasium.com/nofxx/mongoid-geospatial)
|
24
24
|
[![Build Status](https://travis-ci.org/nofxx/mongoid-geospatial.png?branch=master)](https://travis-ci.org/nofxx/mongoid-geospatial)
|
25
25
|
|
26
26
|
|
@@ -60,26 +60,26 @@ A place to illustrate Point, Line and Polygon
|
|
60
60
|
|
61
61
|
For geo points, an extra macro `geo_field` is available
|
62
62
|
|
63
|
-
|
64
63
|
geo_field :location
|
65
|
-
|
64
|
+
|
65
|
+
Will generate:
|
66
|
+
|
66
67
|
field :location, type: Point, spatial: true
|
67
68
|
|
68
69
|
|
69
70
|
|
70
|
-
Generate indexes on MongoDB:
|
71
|
+
Generate indexes on MongoDB via rake:
|
71
72
|
|
72
73
|
|
73
74
|
rake db:mongoid:create_indexes
|
74
75
|
|
75
76
|
|
76
|
-
|
77
|
+
Or programatically:
|
77
78
|
|
78
79
|
|
79
|
-
|
80
|
+
Place.create_indexes
|
80
81
|
|
81
82
|
|
82
|
-
This is fx useful when running specs or when working with spatials on a gem or engine.
|
83
83
|
|
84
84
|
|
85
85
|
Points
|
@@ -125,13 +125,12 @@ Conventions:
|
|
125
125
|
|
126
126
|
This lib uses #x and #y everywhere.
|
127
127
|
It's shorter than lat or lng or another variation that also confuses.
|
128
|
-
A point is a 2D mathematical notation, longitude/latitude is when you
|
129
|
-
|
130
|
-
|
131
|
-
In the eyes of a moralist it's not even a valid position point, it does not have #z or #m.
|
128
|
+
A point is a 2D mathematical notation, longitude/latitude is when you
|
129
|
+
use that notation to map an sphere. In other words:
|
130
|
+
All longitudes are 'xs' where not all 'xs' are longitudes.
|
132
131
|
|
133
132
|
Distance and other geometrical calculations are delegated to the external
|
134
|
-
library
|
133
|
+
library of your choice. More info about using RGeo or GeoRuby below.
|
135
134
|
Some built in helpers for mongoid queries:
|
136
135
|
|
137
136
|
# Returns middle point + radius
|
@@ -153,7 +152,7 @@ And for polygons and lines:
|
|
153
152
|
Query
|
154
153
|
-----
|
155
154
|
|
156
|
-
Before you read about
|
155
|
+
Before you read about this gem have sure you read this:
|
157
156
|
|
158
157
|
http://mongoid.org/en/origin/docs/selection.html#standard
|
159
158
|
|
@@ -172,6 +171,10 @@ You can use Geometry instance directly on any query:
|
|
172
171
|
* Bar.where(:location.near_sphere => person.house)
|
173
172
|
|
174
173
|
|
174
|
+
### Not supported (until Mongoid 5.0.0)
|
175
|
+
Those have been dropped from moped, should return on mongoid 5.
|
176
|
+
Sad story.
|
177
|
+
|
175
178
|
* within_box
|
176
179
|
* Bar.within_box(location: hood.area)
|
177
180
|
|
@@ -188,6 +191,7 @@ You can use Geometry instance directly on any query:
|
|
188
191
|
* Bar.within_polygon(location: city.area)
|
189
192
|
|
190
193
|
|
194
|
+
|
191
195
|
External Libraries
|
192
196
|
------------------
|
193
197
|
|
@@ -200,16 +204,12 @@ It'll require more stuff installed to compile/work.
|
|
200
204
|
|
201
205
|
|
202
206
|
Use GeoRuby?
|
203
|
-
https://github.com/nofxx/
|
207
|
+
https://github.com/nofxx/georuby
|
204
208
|
|
205
209
|
GeoRuby is a pure Ruby Geometry Library.
|
206
210
|
It's perfect if you want simple calculations and/or keep your stack in pure ruby.
|
207
211
|
Albeit not full featured in maths it has a handful of methods and good import/export helpers.
|
208
212
|
|
209
|
-
Use Nothing?
|
210
|
-
|
211
|
-
This lib won't stand in your way.
|
212
|
-
Write your own wrapper if you want.
|
213
213
|
|
214
214
|
|
215
215
|
Geometry Helpers
|
@@ -503,21 +503,10 @@ Indexes need to be created. Execute command:
|
|
503
503
|
|
504
504
|
rake db:mongoid:create_indexes
|
505
505
|
|
506
|
-
Using mongoid-geospatial (or mongoid for that matter) without rails?
|
507
|
-
|
508
|
-
https://github.com/kristianmandrup/mongoid_indexing
|
509
|
-
|
510
|
-
You need a way to create indexes easily, check out the gem above.
|
511
|
-
|
512
|
-
|
513
506
|
|
514
507
|
Contributing
|
515
508
|
------------
|
516
509
|
|
517
|
-
*
|
518
|
-
*
|
519
|
-
*
|
520
|
-
* Start a feature/bugfix branch
|
521
|
-
* Commit and push until you are happy with your contribution
|
522
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
523
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
510
|
+
* Have mongod running
|
511
|
+
* Install dev gems with `bundle install`
|
512
|
+
* Run `rake spec`, `spec spec` or `guard`
|
data/lib/mongoid/geospatial.rb
CHANGED
@@ -5,28 +5,39 @@ require 'mongoid/geospatial/helpers/spatial'
|
|
5
5
|
require 'mongoid/geospatial/helpers/sphere'
|
6
6
|
require 'mongoid/geospatial/helpers/delegate'
|
7
7
|
|
8
|
-
require 'mongoid/geospatial/fields/geometry_field'
|
9
|
-
|
10
|
-
%w(point circle line box polygon).each do |type|
|
11
|
-
require "mongoid/geospatial/fields/#{type}"
|
12
|
-
end
|
13
|
-
|
14
8
|
module Mongoid
|
9
|
+
|
15
10
|
#
|
16
11
|
# Main Geospatial module
|
17
12
|
#
|
18
13
|
# include Mongoid::Geospatial
|
19
14
|
#
|
20
15
|
module Geospatial
|
16
|
+
autoload :GeometryField, 'mongoid/geospatial/geometry_field'
|
17
|
+
|
18
|
+
autoload :Point, 'mongoid/geospatial/fields/point'
|
19
|
+
autoload :LineString, 'mongoid/geospatial/fields/line_string'
|
20
|
+
autoload :Polygon, 'mongoid/geospatial/fields/polygon'
|
21
|
+
|
22
|
+
autoload :Box, 'mongoid/geospatial/fields/box'
|
23
|
+
autoload :Circle, 'mongoid/geospatial/fields/circle'
|
24
|
+
|
25
|
+
autoload :VERSION, 'mongoid/geospatial/version'
|
26
|
+
|
21
27
|
extend ActiveSupport::Concern
|
22
28
|
|
29
|
+
# Symbols accepted as 'longitude', 'x'...
|
23
30
|
LNG_SYMBOLS = [:x, :lon, :long, :lng, :longitude,
|
24
31
|
'x', 'lon', 'long', 'lng', 'longitude']
|
32
|
+
|
33
|
+
# Symbols accepted as 'latitude', 'y'...
|
25
34
|
LAT_SYMBOLS = [:y, :lat, :latitude, 'y', 'lat', 'latitude']
|
26
35
|
|
36
|
+
# For distance spherical calculations
|
27
37
|
EARTH_RADIUS_KM = 6371 # taken directly from mongodb
|
28
38
|
RAD_PER_DEG = Math::PI / 180
|
29
39
|
|
40
|
+
# Earth radius in multiple units
|
30
41
|
EARTH_RADIUS = {
|
31
42
|
m: EARTH_RADIUS_KM * 1000,
|
32
43
|
km: EARTH_RADIUS_KM,
|
@@ -59,26 +70,42 @@ module Mongoid
|
|
59
70
|
require 'mongoid/geospatial/wrappers/georuby'
|
60
71
|
end
|
61
72
|
|
62
|
-
module ClassMethods
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# create spatial index for given field
|
73
|
+
module ClassMethods
|
74
|
+
#
|
75
|
+
# Create Spatial index for given field
|
76
|
+
#
|
77
|
+
#
|
69
78
|
# @param [String,Symbol] name
|
70
79
|
# @param [Hash] options options for spatial_index
|
80
|
+
#
|
71
81
|
# http://www.mongodb.org/display/DOCS/Geospatial+Indexing#GeospatialIndexing-geoNearCommand
|
82
|
+
#
|
72
83
|
def spatial_index(name, options = {})
|
73
84
|
spatial_fields_indexed << name
|
74
85
|
index({ name => '2d' }, options)
|
75
86
|
end
|
76
87
|
|
88
|
+
#
|
89
|
+
# Creates Sphere index for given field
|
90
|
+
#
|
91
|
+
#
|
92
|
+
# @param [String,Symbol] name
|
93
|
+
# @param [Hash] options options for spatial_index
|
94
|
+
#
|
95
|
+
# http://www.mongodb.org/display/DOCS/Geospatial+Indexing#GeospatialIndexing-geoNearCommand
|
77
96
|
def sphere_index(name, options = {})
|
78
97
|
spatial_fields_indexed << name
|
79
98
|
index({ name => '2dsphere' }, options)
|
80
99
|
end
|
81
100
|
|
101
|
+
#
|
102
|
+
# Creates Sphere index for given field
|
103
|
+
#
|
104
|
+
#
|
105
|
+
# @param [String,Symbol] name
|
106
|
+
# @param [Hash] options options for spatial_index
|
107
|
+
#
|
108
|
+
# http://www.mongodb.org/display/DOCS/Geospatial+Indexing#GeospatialIndexing-geoNearCommand
|
82
109
|
def spatial_scope(field, _opts = {})
|
83
110
|
singleton_class.class_eval do
|
84
111
|
# define_method(:close) do |args|
|
@@ -87,6 +114,12 @@ module Mongoid
|
|
87
114
|
end
|
88
115
|
end
|
89
116
|
end
|
117
|
+
|
118
|
+
private
|
119
|
+
def geo_field(name, options = {})
|
120
|
+
field name, { type: Mongoid::Geospatial::Point,
|
121
|
+
spatial: true }.merge(options)
|
122
|
+
end
|
90
123
|
end
|
91
124
|
end
|
92
125
|
end
|
@@ -6,12 +6,14 @@ module Mongoid
|
|
6
6
|
include Enumerable
|
7
7
|
attr_reader :x, :y
|
8
8
|
|
9
|
-
def initialize(x, y)
|
10
|
-
@x, @y = x, y
|
9
|
+
def initialize(x, y, z = nil)
|
10
|
+
@x, @y, @z = x, y, z
|
11
11
|
end
|
12
12
|
|
13
13
|
# Object -> Database
|
14
14
|
# Let's store NilClass if we are invalid.
|
15
|
+
#
|
16
|
+
# @return (Array)
|
15
17
|
def mongoize
|
16
18
|
return nil unless x && y
|
17
19
|
[x, y]
|
@@ -27,28 +29,44 @@ module Mongoid
|
|
27
29
|
yield x
|
28
30
|
yield y
|
29
31
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
#
|
33
|
+
# Point representation as a Hash
|
34
|
+
#
|
35
|
+
# @return (Hash)
|
35
36
|
def to_hsh(xl = :x, yl = :y)
|
36
37
|
{ xl => x, yl => y }
|
37
38
|
end
|
38
39
|
alias_method :to_hash, :to_hsh
|
39
40
|
|
41
|
+
# Helper for [self, radius]
|
40
42
|
def radius(r = 1)
|
41
43
|
[mongoize, r]
|
42
44
|
end
|
43
45
|
|
46
|
+
# Helper for [self, radius / earth radius]
|
44
47
|
def radius_sphere(r = 1, unit = :km)
|
45
48
|
radius r.to_f / Mongoid::Geospatial.earth_radius[unit]
|
46
49
|
end
|
47
50
|
|
51
|
+
#
|
52
|
+
# Am I valid?
|
53
|
+
#
|
54
|
+
# Validates that x & y are `Numeric`
|
55
|
+
#
|
48
56
|
def valid?
|
49
57
|
x && y && x.is_a?(Numeric) && y.is_a?(Numeric)
|
50
58
|
end
|
51
59
|
|
60
|
+
#
|
61
|
+
# Point definition as string
|
62
|
+
#
|
63
|
+
# "x, y"
|
64
|
+
#
|
65
|
+
# @return [String] Point as comma separated String
|
66
|
+
def to_s
|
67
|
+
"#{x}, #{y}"
|
68
|
+
end
|
69
|
+
|
52
70
|
#
|
53
71
|
# Distance calculation methods. Thinking about not using it
|
54
72
|
# One needs to choose and external lib. GeoRuby or RGeo
|
@@ -78,21 +96,80 @@ module Mongoid
|
|
78
96
|
# end
|
79
97
|
|
80
98
|
class << self
|
99
|
+
#
|
100
|
+
# Database -> Object
|
101
|
+
# Get it back
|
102
|
+
def demongoize(obj)
|
103
|
+
obj && Point.new(*obj)
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Object -> Database
|
108
|
+
# Send it to MongoDB
|
109
|
+
def mongoize(obj)
|
110
|
+
case obj
|
111
|
+
when Point then obj.mongoize
|
112
|
+
when String then from_string(obj)
|
113
|
+
when Array then from_array(obj)
|
114
|
+
when Hash then from_hash(obj)
|
115
|
+
when NilClass then nil
|
116
|
+
else
|
117
|
+
return obj.to_xy if obj.respond_to?(:to_xy)
|
118
|
+
fail 'Invalid Point'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Converts the object that was supplied to a criteria
|
123
|
+
# into a database friendly form.
|
124
|
+
def evolve(obj)
|
125
|
+
obj.respond_to?(:x) ? obj.mongoize : obj
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
#
|
131
|
+
# Sanitize a `Point` from a `String`
|
132
|
+
#
|
81
133
|
# Makes life easier:
|
82
|
-
# ""
|
134
|
+
# "" -> []
|
135
|
+
# "1, 2" -> [1.0, 2.0]
|
136
|
+
# "1.1 2.2" -> [1.1, 2.2]
|
137
|
+
#
|
138
|
+
# @return (Array)
|
139
|
+
#
|
83
140
|
def from_string(str)
|
84
141
|
return nil if str.empty?
|
85
142
|
str.split(/,|\s/).reject(&:empty?).map(&:to_f)
|
86
143
|
end
|
87
144
|
|
145
|
+
#
|
146
|
+
# Sanitize a `Point` from an `Array`
|
147
|
+
#
|
88
148
|
# Also makes life easier:
|
89
|
-
# []
|
149
|
+
# [] -> []
|
150
|
+
# [1,2] -> [1.0, 2.0]
|
151
|
+
#
|
152
|
+
# @return (Array)
|
153
|
+
#
|
90
154
|
def from_array(ary)
|
91
155
|
return nil if ary.empty?
|
92
|
-
ary[0..1].map(&:to_f)
|
156
|
+
ary.flatten[0..1].map(&:to_f)
|
93
157
|
end
|
94
158
|
|
95
|
-
#
|
159
|
+
#
|
160
|
+
# Sanitize a `Point` from a `Hash`
|
161
|
+
#
|
162
|
+
# Uses Mongoid::Geospatial.lat_symbols & lng_symbols
|
163
|
+
#
|
164
|
+
# Also makes life easier:
|
165
|
+
# {x: 1.0, y: 2.0} -> [1.0, 2.0]
|
166
|
+
# {lat: 1.0, lon: 2.0} -> [1.0, 2.0]
|
167
|
+
# {lat: 1.0, long: 2.0} -> [1.0, 2.0]
|
168
|
+
#
|
169
|
+
# Throws error if hash has less than 2 items.
|
170
|
+
#
|
171
|
+
# @return (Array)
|
172
|
+
#
|
96
173
|
def from_hash(hsh)
|
97
174
|
fail 'Hash must have at least 2 items' if hsh.size < 2
|
98
175
|
[from_hash_x(hsh), from_hash_y(hsh)]
|
@@ -101,40 +178,13 @@ module Mongoid
|
|
101
178
|
def from_hash_y(hsh)
|
102
179
|
v = (Mongoid::Geospatial.lat_symbols & hsh.keys).first
|
103
180
|
return hsh[v].to_f if !v.nil? && hsh[v]
|
104
|
-
fail "Hash must contain #{Mongoid::Geospatial.lat_symbols.inspect}
|
105
|
-
fail "Hash cannot contain #{Mongoid::Geospatial.lng_symbols.inspect} as the second item if there is no #{Mongoid::Geospatial.lat_symbols.inspect}" if Mongoid::Geospatial.lng_symbols.index(hsh.keys[1])
|
106
|
-
hsh.values[1].to_f
|
181
|
+
fail "Hash must contain #{Mongoid::Geospatial.lat_symbols.inspect}"
|
107
182
|
end
|
108
183
|
|
109
184
|
def from_hash_x(hsh)
|
110
185
|
v = (Mongoid::Geospatial.lng_symbols & hsh.keys).first
|
111
186
|
return hsh[v].to_f if !v.nil? && hsh[v]
|
112
|
-
fail "Hash
|
113
|
-
hsh.values[0].to_f
|
114
|
-
end
|
115
|
-
|
116
|
-
# Database -> Object
|
117
|
-
def demongoize(object)
|
118
|
-
Point.new(*object) if object
|
119
|
-
end
|
120
|
-
|
121
|
-
def mongoize(object)
|
122
|
-
case object
|
123
|
-
when Point then object.mongoize
|
124
|
-
when String then from_string(object)
|
125
|
-
when Array then from_array(object)
|
126
|
-
when Hash then from_hash(object)
|
127
|
-
when NilClass then nil
|
128
|
-
else
|
129
|
-
return object.to_xy if object.respond_to?(:to_xy)
|
130
|
-
fail 'Invalid Point'
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# Converts the object that was supplied to a criteria
|
135
|
-
# into a database friendly form.
|
136
|
-
def evolve(object)
|
137
|
-
object.respond_to?(:x) ? object.mongoize : object
|
187
|
+
fail "Hash must contain #{Mongoid::Geospatial.lng_symbols.inspect}"
|
138
188
|
end
|
139
189
|
end # << self
|
140
190
|
end # Point
|
@@ -1,8 +1,16 @@
|
|
1
1
|
module Mongoid
|
2
2
|
module Geospatial
|
3
|
+
#
|
3
4
|
# Main Geometry Array
|
4
|
-
#
|
5
|
+
#
|
6
|
+
# All multi point classes inherit from this one:
|
7
|
+
# LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon
|
8
|
+
#
|
5
9
|
class GeometryField < Array
|
10
|
+
#
|
11
|
+
# Determines the multi point geometry bounding box.
|
12
|
+
# Useful to find map boundaries, and fit to screen.
|
13
|
+
#
|
6
14
|
def bounding_box
|
7
15
|
max_x, min_x = -Float::MAX, Float::MAX
|
8
16
|
max_y, min_y = -Float::MAX, Float::MAX
|
@@ -16,24 +24,43 @@ module Mongoid
|
|
16
24
|
end
|
17
25
|
alias_method :bbox, :bounding_box
|
18
26
|
|
27
|
+
#
|
28
|
+
# Determines the center point of a multi point geometry.
|
29
|
+
# Geometry may be closed or not.
|
30
|
+
#
|
19
31
|
def center_point
|
20
32
|
min, max = *bbox
|
21
33
|
[(min[0] + max[0]) / 2.0, (min[1] + max[1]) / 2.0]
|
22
34
|
end
|
23
35
|
alias_method :center, :center_point
|
24
36
|
|
37
|
+
#
|
38
|
+
# Generates a radius from the point
|
39
|
+
#
|
40
|
+
# @param [Numeric] r radius
|
41
|
+
# @return [Array] [point, r] point and radius in mongoid format
|
25
42
|
def radius(r = 1)
|
26
43
|
[center, r]
|
27
44
|
end
|
28
45
|
|
46
|
+
#
|
47
|
+
# Generates a spherical radius from the point
|
48
|
+
#
|
49
|
+
# point.radius(x) -> [point, x / earth radius]
|
50
|
+
#
|
51
|
+
# @see Point#radius
|
52
|
+
# @return (Float)
|
53
|
+
#
|
29
54
|
def radius_sphere(r = 1, unit = :km)
|
30
55
|
radius r.to_f / Mongoid::Geospatial.earth_radius[unit]
|
31
56
|
end
|
32
57
|
|
33
58
|
class << self
|
59
|
+
#
|
34
60
|
# Database -> Object
|
35
|
-
|
36
|
-
|
61
|
+
#
|
62
|
+
def demongoize(obj)
|
63
|
+
obj && new(obj)
|
37
64
|
end
|
38
65
|
end
|
39
66
|
end
|
@@ -3,28 +3,36 @@ require 'geo_ruby'
|
|
3
3
|
module Mongoid
|
4
4
|
module Geospatial
|
5
5
|
# Wrapper to GeoRuby's Point
|
6
|
-
|
6
|
+
Point.class_eval do
|
7
7
|
# delegate :distance, to: :to_geo
|
8
8
|
|
9
|
+
#
|
10
|
+
# With GeoRuby support
|
11
|
+
#
|
12
|
+
# @return (GeoRuby::SimpleFeatures::Point)
|
9
13
|
def to_geo
|
10
14
|
return unless valid?
|
11
15
|
GeoRuby::SimpleFeatures::Point.xy(x, y)
|
12
16
|
end
|
13
17
|
|
18
|
+
#
|
19
|
+
# With GeoRuby support
|
20
|
+
#
|
21
|
+
# @return (Float)
|
14
22
|
def geo_distance(other)
|
15
23
|
to_geo.spherical_distance(other.to_geo)
|
16
24
|
end
|
17
25
|
end
|
18
26
|
|
19
|
-
# Wrapper to GeoRuby's
|
20
|
-
|
27
|
+
# Wrapper to GeoRuby's LineString
|
28
|
+
LineString.class_eval do
|
21
29
|
def to_geo
|
22
30
|
GeoRuby::SimpleFeatures::LineString.from_coordinates(self)
|
23
31
|
end
|
24
32
|
end
|
25
33
|
|
26
34
|
# Wrapper to GeoRuby's Polygon
|
27
|
-
|
35
|
+
Polygon.class_eval do
|
28
36
|
def to_geo
|
29
37
|
GeoRuby::SimpleFeatures::Polygon.from_coordinates(self)
|
30
38
|
end
|
@@ -4,19 +4,26 @@ require 'mongoid/geospatial/ext/rgeo_spherical_point_impl'
|
|
4
4
|
module Mongoid
|
5
5
|
module Geospatial
|
6
6
|
# Wrapper to Rgeo's Point
|
7
|
-
|
7
|
+
Point.class_eval do
|
8
|
+
#
|
9
|
+
# With RGeo support
|
10
|
+
#
|
11
|
+
# @return (RGeo::SphericalFactory::Point)
|
8
12
|
def to_rgeo
|
9
13
|
RGeo::Geographic.spherical_factory.point x, y
|
10
14
|
end
|
11
15
|
|
16
|
+
#
|
17
|
+
# Distance with RGeo
|
18
|
+
#
|
19
|
+
# @return (Float)
|
12
20
|
def rgeo_distance(other)
|
13
21
|
to_rgeo.distance other.to_rgeo
|
14
22
|
end
|
15
23
|
end
|
16
24
|
|
17
25
|
# Rgeo's GeometryField concept
|
18
|
-
|
19
|
-
private
|
26
|
+
GeometryField.class_eval do
|
20
27
|
|
21
28
|
def points
|
22
29
|
map do |pair|
|
@@ -25,18 +32,18 @@ module Mongoid
|
|
25
32
|
end
|
26
33
|
end
|
27
34
|
|
28
|
-
# Wrapper to Rgeo's
|
29
|
-
|
35
|
+
# Wrapper to Rgeo's LineString
|
36
|
+
LineString.class_eval do
|
30
37
|
def to_rgeo
|
31
|
-
RGeo::Geographic.spherical_factory.line_string
|
38
|
+
RGeo::Geographic.spherical_factory.line_string(points)
|
32
39
|
end
|
33
40
|
end
|
34
41
|
|
35
42
|
# Wrapper to Rgeo's Polygon
|
36
|
-
|
43
|
+
Polygon.class_eval do
|
37
44
|
def to_rgeo
|
38
|
-
ring = RGeo::Geographic.spherical_factory.linear_ring
|
39
|
-
RGeo::Geographic.spherical_factory.polygon
|
45
|
+
ring = RGeo::Geographic.spherical_factory.linear_ring(points)
|
46
|
+
RGeo::Geographic.spherical_factory.polygon(ring)
|
40
47
|
end
|
41
48
|
end
|
42
49
|
end
|
data/mongoid-geospatial.gemspec
CHANGED
@@ -8,7 +8,6 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.summary = 'Mongoid Extension that simplifies MongoDB Geospatial Operations.'
|
9
9
|
gem.homepage = 'https://github.com/nofxx/mongoid-geospatial'
|
10
10
|
|
11
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
12
11
|
gem.files = `git ls-files`.split("\n")
|
13
12
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
13
|
gem.name = 'mongoid-geospatial'
|
@@ -16,7 +15,5 @@ Gem::Specification.new do |gem|
|
|
16
15
|
gem.version = Mongoid::Geospatial::VERSION
|
17
16
|
gem.license = 'MIT'
|
18
17
|
|
19
|
-
gem.add_dependency('mongoid', ['>=
|
20
|
-
gem.add_dependency('activemodel', ['>= 3.2'])
|
21
|
-
gem.add_dependency('activesupport', ['>= 3.2'])
|
18
|
+
gem.add_dependency('mongoid', ['>= 4.0.0'])
|
22
19
|
end
|
data/spec/models/river.rb
CHANGED
@@ -6,7 +6,7 @@ class River
|
|
6
6
|
field :name, type: String
|
7
7
|
field :length, type: Integer
|
8
8
|
field :discharge, type: Integer
|
9
|
-
field :course, type:
|
9
|
+
field :course, type: LineString, spatial: true
|
10
10
|
# set return_array to true if you do not want a hash returned all the time
|
11
11
|
field :source, type: Point, spatial: true
|
12
12
|
field :mouth, type: Point, spatial: { lat: 'latitude', lng: 'longitude' }
|
@@ -1,35 +1,42 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Mongoid::Geospatial::
|
3
|
+
describe Mongoid::Geospatial::LineString do
|
4
4
|
describe '(de)mongoize' do
|
5
5
|
it 'should support a field mapped as linestring' do
|
6
6
|
river = River.new(course: [[5, 5], [6, 5], [6, 6], [5, 6]])
|
7
|
-
expect(river.course).to be_a Mongoid::Geospatial::
|
7
|
+
expect(river.course).to be_a Mongoid::Geospatial::LineString
|
8
8
|
expect(river.course).to eq([[5, 5], [6, 5], [6, 6], [5, 6]])
|
9
9
|
end
|
10
10
|
|
11
|
+
it 'should update line string too' do
|
12
|
+
river = River.create!(name: 'Amazonas')
|
13
|
+
river.course = [[1, 1], [1, 1], [9, 9], [9, 9]]
|
14
|
+
river.save
|
15
|
+
expect(River.first.course).to eq(river.course)
|
16
|
+
end
|
17
|
+
|
11
18
|
it 'should support a field mapped as linestring' do
|
12
19
|
River.create!(course: [[5, 5], [6, 5], [6, 6], [5, 6]])
|
13
20
|
expect(River.first.course).to eq([[5, 5], [6, 5], [6, 6], [5, 6]])
|
14
21
|
end
|
15
22
|
|
16
23
|
it 'should have a bounding box' do
|
17
|
-
geom = Mongoid::Geospatial::
|
24
|
+
geom = Mongoid::Geospatial::LineString.new [[1, 5], [6, 5], [6, 6], [5, 6]]
|
18
25
|
expect(geom.bbox).to eq([[1, 5], [6, 6]])
|
19
26
|
end
|
20
27
|
|
21
28
|
it 'should have a center point' do
|
22
|
-
geom = Mongoid::Geospatial::
|
29
|
+
geom = Mongoid::Geospatial::LineString.new [[1, 1], [1, 1], [9, 9], [9, 9]]
|
23
30
|
expect(geom.center).to eq([5.0, 5.0])
|
24
31
|
end
|
25
32
|
|
26
33
|
it 'should have a radius helper' do
|
27
|
-
geom = Mongoid::Geospatial::
|
34
|
+
geom = Mongoid::Geospatial::LineString.new [[1, 1], [1, 1], [9, 9], [9, 9]]
|
28
35
|
expect(geom.radius(10)).to eq([[5.0, 5.0], 10])
|
29
36
|
end
|
30
37
|
|
31
38
|
it 'should have a radius sphere' do
|
32
|
-
geom = Mongoid::Geospatial::
|
39
|
+
geom = Mongoid::Geospatial::LineString.new [[1, 1], [1, 1], [9, 9], [9, 9]]
|
33
40
|
expect(geom.radius_sphere(10)[1]).to be_within(0.001).of(0.001569)
|
34
41
|
end
|
35
42
|
end
|
@@ -30,16 +30,16 @@ describe Mongoid::Fields do
|
|
30
30
|
|
31
31
|
it 'should set instance methods x= and y=' do
|
32
32
|
bus = Bus.create!(name: 'B', location: [7, 7])
|
33
|
-
bus.x =
|
33
|
+
bus.x = 8
|
34
34
|
bus.y = 9
|
35
|
-
expect(bus.location.to_a).to eq([
|
35
|
+
expect(bus.location.to_a).to eq([8, 9])
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'should work fine with default values' do
|
39
39
|
event = Event.create!(name: 'Bvent')
|
40
|
-
event.x =
|
40
|
+
event.x = 8
|
41
41
|
event.y = 9
|
42
|
-
expect(event.location.to_a).to eq([
|
42
|
+
expect(event.location.to_a).to eq([8, 9])
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'should not work fine with nils' do
|
@@ -25,7 +25,7 @@ describe 'RGeo Wrapper' do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
describe Mongoid::Geospatial::
|
28
|
+
describe Mongoid::Geospatial::LineString do
|
29
29
|
it 'should not interfer with mongoid' do
|
30
30
|
River.create!(name: 'Mississippi')
|
31
31
|
expect(River.count).to eql(1)
|
@@ -99,10 +99,10 @@ describe 'RGeo Wrapper' do
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
describe Mongoid::Geospatial::
|
102
|
+
describe Mongoid::Geospatial::LineString do
|
103
103
|
it 'should mongoize array' do
|
104
104
|
geom = River.create!(course: [[5, 5], [6, 5], [6, 6], [5, 6]]).course
|
105
|
-
expect(geom.class).to eql(Mongoid::Geospatial::
|
105
|
+
expect(geom.class).to eql(Mongoid::Geospatial::LineString)
|
106
106
|
expect(geom.to_rgeo.class).to eql(RGeo::Geographic::SphericalLineStringImpl)
|
107
107
|
expect(geom.to_rgeo.to_s)
|
108
108
|
.to eq 'LINESTRING (5.0 5.0, 6.0 5.0, 6.0 6.0, 5.0 6.0)'
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-geospatial
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Ong
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-04-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|
@@ -17,42 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
20
|
+
version: 4.0.0
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version:
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: activemodel
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - ">="
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '3.2'
|
35
|
-
type: :runtime
|
36
|
-
prerelease: false
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '3.2'
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: activesupport
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - ">="
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '3.2'
|
49
|
-
type: :runtime
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '3.2'
|
27
|
+
version: 4.0.0
|
56
28
|
description: Mongoid Extension that simplifies MongoDB casting and operations on spatial
|
57
29
|
Ruby objects.
|
58
30
|
email:
|
@@ -63,6 +35,8 @@ extra_rdoc_files: []
|
|
63
35
|
files:
|
64
36
|
- ".coveralls.yml"
|
65
37
|
- ".gitignore"
|
38
|
+
- ".hound.yml"
|
39
|
+
- ".rspec"
|
66
40
|
- ".travis.yml"
|
67
41
|
- Gemfile
|
68
42
|
- Guardfile
|
@@ -74,10 +48,10 @@ files:
|
|
74
48
|
- lib/mongoid/geospatial/ext/rgeo_spherical_point_impl.rb
|
75
49
|
- lib/mongoid/geospatial/fields/box.rb
|
76
50
|
- lib/mongoid/geospatial/fields/circle.rb
|
77
|
-
- lib/mongoid/geospatial/fields/
|
78
|
-
- lib/mongoid/geospatial/fields/line.rb
|
51
|
+
- lib/mongoid/geospatial/fields/line_string.rb
|
79
52
|
- lib/mongoid/geospatial/fields/point.rb
|
80
53
|
- lib/mongoid/geospatial/fields/polygon.rb
|
54
|
+
- lib/mongoid/geospatial/geometry_field.rb
|
81
55
|
- lib/mongoid/geospatial/helpers/delegate.rb
|
82
56
|
- lib/mongoid/geospatial/helpers/spatial.rb
|
83
57
|
- lib/mongoid/geospatial/helpers/sphere.rb
|
@@ -97,7 +71,7 @@ files:
|
|
97
71
|
- spec/models/river.rb
|
98
72
|
- spec/mongoid/geospatial/fields/box_spec.rb
|
99
73
|
- spec/mongoid/geospatial/fields/circle_spec.rb
|
100
|
-
- spec/mongoid/geospatial/fields/
|
74
|
+
- spec/mongoid/geospatial/fields/line_string_spec.rb
|
101
75
|
- spec/mongoid/geospatial/fields/point_spec.rb
|
102
76
|
- spec/mongoid/geospatial/fields/polygon_spec.rb
|
103
77
|
- spec/mongoid/geospatial/geospatial_spec.rb
|
@@ -148,7 +122,7 @@ test_files:
|
|
148
122
|
- spec/models/river.rb
|
149
123
|
- spec/mongoid/geospatial/fields/box_spec.rb
|
150
124
|
- spec/mongoid/geospatial/fields/circle_spec.rb
|
151
|
-
- spec/mongoid/geospatial/fields/
|
125
|
+
- spec/mongoid/geospatial/fields/line_string_spec.rb
|
152
126
|
- spec/mongoid/geospatial/fields/point_spec.rb
|
153
127
|
- spec/mongoid/geospatial/fields/polygon_spec.rb
|
154
128
|
- spec/mongoid/geospatial/geospatial_spec.rb
|