mongoid-geospatial 7.0.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +109 -33
- data/lib/mongoid/geospatial/config/point.rb +5 -2
- data/lib/mongoid/geospatial/config.rb +2 -0
- data/lib/mongoid/geospatial/ext/rgeo_spherical_point_impl.rb +2 -0
- data/lib/mongoid/geospatial/fields/box.rb +2 -0
- data/lib/mongoid/geospatial/fields/circle.rb +2 -2
- data/lib/mongoid/geospatial/fields/line_string.rb +2 -0
- data/lib/mongoid/geospatial/fields/point.rb +59 -50
- data/lib/mongoid/geospatial/fields/polygon.rb +2 -0
- data/lib/mongoid/geospatial/geometry_field.rb +4 -2
- data/lib/mongoid/geospatial/helpers/delegate.rb +2 -0
- data/lib/mongoid/geospatial/helpers/geom.rb +22 -0
- data/lib/mongoid/geospatial/helpers/spatial.rb +2 -0
- data/lib/mongoid/geospatial/helpers/sphere.rb +2 -0
- data/lib/mongoid/geospatial/keys.rb +20 -0
- data/lib/mongoid/geospatial/version.rb +3 -1
- data/lib/mongoid/geospatial/wrappers/georuby.rb +2 -0
- data/lib/mongoid/geospatial/wrappers/rgeo.rb +2 -0
- data/lib/mongoid/geospatial.rb +196 -16
- metadata +7 -75
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -49
- data/.hound.yml +0 -2
- data/.rspec +0 -3
- data/.rubocop.yml +0 -8
- data/.travis.yml +0 -33
- data/CHANGELOG.md +0 -23
- data/CONTRIBUTING.md +0 -118
- data/Gemfile +0 -17
- data/Guardfile +0 -16
- data/RELEASING.md +0 -62
- data/Rakefile +0 -20
- data/mongoid-geospatial.gemspec +0 -18
- data/spec/bench +0 -64
- data/spec/models/address.rb +0 -69
- data/spec/models/alarm.rb +0 -12
- data/spec/models/bar.rb +0 -14
- data/spec/models/bus.rb +0 -12
- data/spec/models/event.rb +0 -18
- data/spec/models/farm.rb +0 -13
- data/spec/models/person.rb +0 -91
- data/spec/models/phone.rb +0 -8
- data/spec/models/place.rb +0 -13
- data/spec/models/river.rb +0 -22
- data/spec/mongoid/geospatial/config_spec.rb +0 -22
- data/spec/mongoid/geospatial/fields/box_spec.rb +0 -8
- data/spec/mongoid/geospatial/fields/circle_spec.rb +0 -8
- data/spec/mongoid/geospatial/fields/line_string_spec.rb +0 -78
- data/spec/mongoid/geospatial/fields/point_spec.rb +0 -296
- data/spec/mongoid/geospatial/fields/polygon_spec.rb +0 -87
- data/spec/mongoid/geospatial/geospatial_spec.rb +0 -222
- data/spec/mongoid/geospatial/helpers/core_spec.rb +0 -35
- data/spec/mongoid/geospatial/helpers/delegate_spec.rb +0 -67
- data/spec/mongoid/geospatial/helpers/spatial_spec.rb +0 -40
- data/spec/mongoid/geospatial/helpers/sphere_spec.rb +0 -31
- data/spec/mongoid/geospatial/wrappers/georuby_spec.rb +0 -63
- data/spec/mongoid/geospatial/wrappers/rgeo_spec.rb +0 -115
- data/spec/mongoid.yml +0 -298
- data/spec/spec_helper.rb +0 -42
- data/spec/support/authentication.rb +0 -28
- data/spec/support/mongod.conf +0 -3
- data/spec/support/mongoid.yml +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4bc532f8201a1c7c0f43c63d051a073dd5658ab8ffa561ea852e14a0fcf1c243
|
|
4
|
+
data.tar.gz: 9af8f1e4e1ef5f2514e3214f5e0bc66c0f56fbb7e9a1cbdf3fd152e89b11cbad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 154e488426770257945cd93d36138d238d5b1bf75e308b62b568ba897f9835f921faf26d50f14e71c9f3f43f0ce9be761586f228a788819a0ed7f2662274fbc3
|
|
7
|
+
data.tar.gz: 1fbd1713b7121edc2bc8f171a5cf66f63befc5668369d1f833d0be1d0783844bb41ffdf62e618172324e15bb2cfb4e905a3cd91896ec9b7d28a46142a06b6769
|
data/README.md
CHANGED
|
@@ -46,6 +46,14 @@ class Place
|
|
|
46
46
|
end
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
A pin named `geom` on a 2dsphere index is one include:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
include Mongoid::Geospatial::Geom # field :geom, type: Point, sphere: true
|
|
53
|
+
# or a named one:
|
|
54
|
+
geom :pick_up
|
|
55
|
+
```
|
|
56
|
+
|
|
49
57
|
Generate indexes on MongoDB via rake:
|
|
50
58
|
|
|
51
59
|
```
|
|
@@ -94,6 +102,15 @@ If you need a hash
|
|
|
94
102
|
cafe.location.to_hsh # => { x: -74.026667, y: 40.703056 }
|
|
95
103
|
```
|
|
96
104
|
|
|
105
|
+
Commonly used
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
cafe.location.to_lat_lon # => { lat: 40.703056, lon: -74.026667 }
|
|
109
|
+
cafe.location.lat # => 40.703056
|
|
110
|
+
cafe.location.lng # => -74.026667
|
|
111
|
+
cafe.location.distance(other) # => km, haversine
|
|
112
|
+
```
|
|
113
|
+
|
|
97
114
|
If you are using GeoRuby or RGeo
|
|
98
115
|
|
|
99
116
|
```ruby
|
|
@@ -108,7 +125,7 @@ This lib uses #x and #y everywhere.
|
|
|
108
125
|
It's shorter than lat or lng or another variation that also confuses.
|
|
109
126
|
A point is a 2D mathematical notation, longitude/latitude is when you use that notation to map an sphere. In other words: all longitudes are 'xs' where not all 'xs' are longitudes.
|
|
110
127
|
|
|
111
|
-
Distance
|
|
128
|
+
Distance is `Point#distance` (haversine, km). Projections and heavier geometry still go to RGeo or GeoRuby. Some built in helpers for mongoid queries:
|
|
112
129
|
|
|
113
130
|
```ruby
|
|
114
131
|
# Returns middle point + radius
|
|
@@ -176,26 +193,6 @@ field :location, type: Point, delegate: true
|
|
|
176
193
|
|
|
177
194
|
Now instead of `instance.location.x` you may call `instance.x`.
|
|
178
195
|
|
|
179
|
-
## Nearby
|
|
180
|
-
|
|
181
|
-
You can add a `spatial_scope` on your models. So you can query:
|
|
182
|
-
|
|
183
|
-
```ruby
|
|
184
|
-
Bar.nearby(my.location)
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
instead of
|
|
188
|
-
|
|
189
|
-
```ruby
|
|
190
|
-
Bar.near(location: my.location)
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
Good when you're drunk. Just add to your model:
|
|
194
|
-
|
|
195
|
-
```ruby
|
|
196
|
-
spatial_scope :<field>
|
|
197
|
-
```
|
|
198
|
-
|
|
199
196
|
## Geometry
|
|
200
197
|
|
|
201
198
|
You can also store Circle, Box, Line (LineString) and Polygons.
|
|
@@ -219,30 +216,95 @@ polygon.radius_sphere(5) # [[1.0, 1.0], 0.00048..]
|
|
|
219
216
|
|
|
220
217
|
## Query
|
|
221
218
|
|
|
222
|
-
Before you proceed, make sure you have read this:
|
|
223
|
-
|
|
224
|
-
http://mongoid.github.io/old/en/origin/docs/selection.html#standard
|
|
225
|
-
|
|
226
|
-
All MongoDB queries are handled by Mongoid/Origin.
|
|
227
|
-
|
|
228
|
-
http://www.rubydoc.info/github/mongoid/origin/Origin/Selectable
|
|
229
|
-
|
|
230
219
|
You can use Geometry instance directly on any query:
|
|
231
220
|
|
|
232
|
-
|
|
221
|
+
### near
|
|
233
222
|
|
|
234
223
|
```ruby
|
|
235
224
|
Bar.near(location: person.house)
|
|
236
225
|
Bar.where(:location.near => person.house)
|
|
237
226
|
```
|
|
238
227
|
|
|
239
|
-
|
|
228
|
+
### near_sphere
|
|
240
229
|
|
|
241
230
|
```ruby
|
|
242
231
|
Bar.near_sphere(location: person.house)
|
|
243
232
|
Bar.where(:location.near_sphere => person.house)
|
|
244
233
|
```
|
|
245
234
|
|
|
235
|
+
### nearby / within
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
Bar.nearby(person.house)
|
|
239
|
+
Bar.nearby(person.house, km: 30)
|
|
240
|
+
Bar.within(person.house, 30) # same question, km required
|
|
241
|
+
City.where(:geom.near_sphere => Mongoid::Geospatial.near_query(geom, 50))
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`within` is `$nearSphere` + `$maxDistance` in metres. Nearest first, chainable.
|
|
245
|
+
|
|
246
|
+
**Don't call `#first` or `#last` on a `$near` criteria.** Mongoid sorts by
|
|
247
|
+
`_id` when a criteria carries no sort of its own, and that replaces the
|
|
248
|
+
distance order Mongo put there. Walk the criteria instead — `.to_a.first` —
|
|
249
|
+
or use `geo_near`, which returns the distance as a field you can sort on.
|
|
250
|
+
|
|
251
|
+
You can add a `spatial_scope` on your models. So you can query:
|
|
252
|
+
|
|
253
|
+
```ruby
|
|
254
|
+
Bar.nearby(my.location)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
instead of
|
|
258
|
+
|
|
259
|
+
```ruby
|
|
260
|
+
Bar.near(location: my.location)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Good when you're drunk. Just add to your model:
|
|
264
|
+
|
|
265
|
+
```ruby
|
|
266
|
+
spatial_scope :<field>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### geo_near
|
|
270
|
+
|
|
271
|
+
The `geo_near` class method provides a more powerful way to query for documents based on proximity,
|
|
272
|
+
using MongoDB's `$geoNear` aggregation pipeline stage. This method allows for more complex
|
|
273
|
+
options and returns the distance to each matched document.
|
|
274
|
+
|
|
275
|
+
```ruby
|
|
276
|
+
# Find places near [10, 20], using spherical calculations, up to 5km away,
|
|
277
|
+
# and get the distance.
|
|
278
|
+
# The :distanceField option specifies the name of the field that will contain the distance.
|
|
279
|
+
# The :limit option is applied as a separate $limit stage in the aggregation.
|
|
280
|
+
Place.geo_near(:location, [10, 20],
|
|
281
|
+
spherical: true,
|
|
282
|
+
maxDistance: 5000, # 5 kilometers in meters for spherical queries
|
|
283
|
+
distanceField: 'dist.calculated', # Default is 'distance'
|
|
284
|
+
query: { category: 'restaurant' }, # Optional: filter documents before geoNear
|
|
285
|
+
limit: 10)
|
|
286
|
+
|
|
287
|
+
# Iterate over results
|
|
288
|
+
Place.geo_near(:location, [10, 20], spherical: true).each do |place|
|
|
289
|
+
# 'place.distance' will be available if distanceField was 'distance' (the default)
|
|
290
|
+
# or 'place.dist_calculated' if distanceField was 'dist.calculated'
|
|
291
|
+
puts "#{place.name} is #{place.distance || place.dist_calculated} meters away."
|
|
292
|
+
end
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Key features and options for `geo_near`:
|
|
296
|
+
|
|
297
|
+
- `:spherical` (Boolean): If `true`, calculates distances using spherical geometry. Defaults to `false`.
|
|
298
|
+
- `:distanceField` (String): Name of the output field for the calculated distance. Defaults to `'distance'`.
|
|
299
|
+
- `:maxDistance` (Numeric): Maximum distance from the center point. (Meters for spherical, units of coordinates for planar).
|
|
300
|
+
- `:minDistance` (Numeric): Minimum distance from the center point.
|
|
301
|
+
- `:query` (Hash): A query to filter documents _before_ the `$geoNear` stage.
|
|
302
|
+
- `:limit` (Integer): Maximum number of documents to return (applied as a separate `$limit` stage).
|
|
303
|
+
- `:distanceMultiplier` (Numeric): A factor to multiply all distances.
|
|
304
|
+
- `:includeLocs` (String): Name of an output field that will contain the exact location on the document used for the distance calculation. Useful for multi-location fields or complex GeoJSON geometries.
|
|
305
|
+
|
|
306
|
+
The `geo_near` method returns an array of instantiated Mongoid documents, with the `distanceField` and `includeLocs` field (if specified) available as dynamic attributes on each model instance.
|
|
307
|
+
|
|
246
308
|
- within_polygon
|
|
247
309
|
|
|
248
310
|
```ruby
|
|
@@ -251,6 +313,20 @@ Bar.within_polygon(location: [[[x,y],...[x,y]]])
|
|
|
251
313
|
Bar.within_polygon(location: street.bbox)
|
|
252
314
|
```
|
|
253
315
|
|
|
316
|
+
- within_circle / within_spherical_circle
|
|
317
|
+
|
|
318
|
+
Mongoid ships `within_polygon` and `within_box` and stopped there; this gem
|
|
319
|
+
registers the two circle shapes, which is what `radius` and `radius_sphere`
|
|
320
|
+
have been building arguments for all along.
|
|
321
|
+
|
|
322
|
+
```ruby
|
|
323
|
+
Bar.where(:location.within_spherical_circle => cafe.location.radius_sphere(5, :km))
|
|
324
|
+
Bar.where(:location.within_circle => cafe.location.radius(0.05)) # degrees, flat
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`$centerSphere` reads radians (`radius_sphere` hands it those); `$center`
|
|
328
|
+
reads the coordinate system's own units — degrees on a legacy pair.
|
|
329
|
+
|
|
254
330
|
- intersects_line
|
|
255
331
|
- intersects_point
|
|
256
332
|
- intersects_polygon
|
|
@@ -264,7 +340,7 @@ external library corresponding object.
|
|
|
264
340
|
|
|
265
341
|
### Use RGeo?
|
|
266
342
|
|
|
267
|
-
https://github.com/dazuma/rgeo
|
|
343
|
+
<https://github.com/dazuma/rgeo>
|
|
268
344
|
|
|
269
345
|
RGeo is a Ruby wrapper for Proj/GEOS.
|
|
270
346
|
It's perfect when you need to work with complex calculations and projections.
|
|
@@ -272,7 +348,7 @@ It'll require more stuff installed to compile/work.
|
|
|
272
348
|
|
|
273
349
|
### Use GeoRuby?
|
|
274
350
|
|
|
275
|
-
https://github.com/nofxx/georuby
|
|
351
|
+
<https://github.com/nofxx/georuby>
|
|
276
352
|
|
|
277
353
|
GeoRuby is a pure Ruby Geometry Library.
|
|
278
354
|
It's perfect if you want simple calculations and/or keep your stack in pure ruby.
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mongoid
|
|
2
4
|
module Geospatial
|
|
3
5
|
module Config
|
|
4
6
|
module Point
|
|
5
7
|
extend self
|
|
6
8
|
|
|
7
|
-
attr_accessor :x
|
|
8
|
-
attr_accessor :y
|
|
9
|
+
attr_accessor :x, :y
|
|
9
10
|
|
|
10
11
|
def reset!
|
|
12
|
+
# Now self.x and self.y refer to the public module accessors
|
|
11
13
|
self.x = Mongoid::Geospatial.lng_symbols
|
|
12
14
|
self.y = Mongoid::Geospatial.lat_symbols
|
|
13
15
|
end
|
|
14
16
|
|
|
17
|
+
# Initialize the configuration
|
|
15
18
|
reset!
|
|
16
19
|
end
|
|
17
20
|
end
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mongoid
|
|
2
4
|
module Geospatial
|
|
3
5
|
# Point
|
|
4
6
|
#
|
|
5
|
-
class Point
|
|
7
|
+
class Point # rubocop:disable Metrics/ClassLength
|
|
6
8
|
include Enumerable
|
|
7
|
-
attr_accessor :x, :y, :z
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
attr_accessor :x, :y, :z
|
|
11
|
+
alias lng x
|
|
12
|
+
alias lon x
|
|
13
|
+
alias lat y
|
|
14
|
+
alias lng= x=
|
|
15
|
+
alias lon= x=
|
|
16
|
+
alias lat= y=
|
|
17
|
+
|
|
18
|
+
def initialize(lon, lat, alt = nil)
|
|
19
|
+
@x = lon
|
|
20
|
+
@y = lat
|
|
21
|
+
@z = alt
|
|
13
22
|
end
|
|
14
23
|
|
|
15
24
|
# Object -> Database
|
|
@@ -23,6 +32,7 @@ module Mongoid
|
|
|
23
32
|
end
|
|
24
33
|
alias to_a mongoize
|
|
25
34
|
alias to_xy mongoize
|
|
35
|
+
alias to_lng_lat mongoize
|
|
26
36
|
|
|
27
37
|
def [](args)
|
|
28
38
|
mongoize[args]
|
|
@@ -33,23 +43,13 @@ module Mongoid
|
|
|
33
43
|
yield y
|
|
34
44
|
end
|
|
35
45
|
|
|
36
|
-
#
|
|
37
|
-
# Point representation as a Hash
|
|
38
|
-
#
|
|
39
|
-
# @return [Hash] with { xl => x, yl => y }
|
|
40
|
-
#
|
|
41
|
-
def to_hsh(xl = :x, yl = :y)
|
|
42
|
-
{ xl => x, yl => y }
|
|
43
|
-
end
|
|
44
|
-
alias to_hash to_hsh
|
|
45
|
-
|
|
46
46
|
#
|
|
47
47
|
# Helper for [self, radius]
|
|
48
48
|
#
|
|
49
49
|
# @return [Array] with [self, radius]
|
|
50
50
|
#
|
|
51
|
-
def radius(r = 1)
|
|
52
|
-
[
|
|
51
|
+
def radius(r = 1) # rubocop:disable Naming/MethodParameterName
|
|
52
|
+
[mongoize, r]
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
#
|
|
@@ -59,7 +59,7 @@ module Mongoid
|
|
|
59
59
|
#
|
|
60
60
|
# @return [Array] with [self, radius / earth radius]
|
|
61
61
|
#
|
|
62
|
-
def radius_sphere(r = 1, unit = :km)
|
|
62
|
+
def radius_sphere(r = 1, unit = :km) # rubocop:disable Naming/MethodParameterName
|
|
63
63
|
radius r.to_f / Mongoid::Geospatial.earth_radius[unit]
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -85,6 +85,26 @@ module Mongoid
|
|
|
85
85
|
"#{x}, #{y}"
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
#
|
|
89
|
+
# Point representation as a Hash
|
|
90
|
+
# Optional param: custom keys.
|
|
91
|
+
#
|
|
92
|
+
# @return [Hash] with { lng_key => x, lat_key => y }
|
|
93
|
+
#
|
|
94
|
+
def to_hsh(xkey = :x, ykey = :y)
|
|
95
|
+
{ xkey => x, ykey => y }
|
|
96
|
+
end
|
|
97
|
+
alias to_hash to_hsh
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# Point representation more commonly used
|
|
101
|
+
# Latitude, Longitude
|
|
102
|
+
#
|
|
103
|
+
# @return [Hash] with { latitude: y, longitude: x }
|
|
104
|
+
def to_lat_lon
|
|
105
|
+
{ latitude: y, longitude: x }
|
|
106
|
+
end
|
|
107
|
+
|
|
88
108
|
#
|
|
89
109
|
# Point definition as GeoJSON
|
|
90
110
|
#
|
|
@@ -94,7 +114,7 @@ module Mongoid
|
|
|
94
114
|
#
|
|
95
115
|
def to_geo_json
|
|
96
116
|
# Return a GeoJSON point hash that MongoDB can use
|
|
97
|
-
{ type:
|
|
117
|
+
{ type: 'Point', coordinates: [x, y] }
|
|
98
118
|
end
|
|
99
119
|
|
|
100
120
|
#
|
|
@@ -110,32 +130,21 @@ module Mongoid
|
|
|
110
130
|
end
|
|
111
131
|
|
|
112
132
|
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# # The user has to make sure using this distance makes sense
|
|
129
|
-
# (ie she should be in latlon coordinates)
|
|
130
|
-
# def spherical_distance(point,r=6370997.0)
|
|
131
|
-
# dlat = (point.lat - lat) * DEG2RAD / 2
|
|
132
|
-
# dlon = (point.lon - lon) * DEG2RAD / 2
|
|
133
|
-
|
|
134
|
-
# a = Math.sin(dlat)**2 + Math.cos(lat * DEG2RAD) *
|
|
135
|
-
# Math.cos(point.lat * DEG2RAD) * Math.sin(dlon)**2
|
|
136
|
-
# c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
|
|
137
|
-
# r * c
|
|
138
|
-
# end
|
|
133
|
+
# Crow-flies distance. Haversine, Mongo's earth radius (6371 km).
|
|
134
|
+
# RGeo/GeoRuby still win for projections; this is ETA and "how far".
|
|
135
|
+
#
|
|
136
|
+
def distance(other, unit = :km) # rubocop:disable Metrics/AbcSize
|
|
137
|
+
xy = other.is_a?(Point) ? [other.x, other.y] : self.class.mongoize(other)
|
|
138
|
+
raise ArgumentError, "Invalid point: #{other.inspect}" unless xy
|
|
139
|
+
|
|
140
|
+
dlat = (xy[1] - y) * RAD_PER_DEG
|
|
141
|
+
dlon = (xy[0] - x) * RAD_PER_DEG
|
|
142
|
+
a = (Math.sin(dlat / 2)**2) +
|
|
143
|
+
(Math.cos(y * RAD_PER_DEG) * Math.cos(xy[1] * RAD_PER_DEG) *
|
|
144
|
+
(Math.sin(dlon / 2)**2))
|
|
145
|
+
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
|
|
146
|
+
Mongoid::Geospatial.earth_radius[unit] * c
|
|
147
|
+
end
|
|
139
148
|
|
|
140
149
|
class << self
|
|
141
150
|
#
|
|
@@ -237,7 +246,7 @@ module Mongoid
|
|
|
237
246
|
|
|
238
247
|
raise "Hash must contain #{Mongoid::Geospatial::Config::Point.x.inspect}"
|
|
239
248
|
end
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mongoid
|
|
2
4
|
module Geospatial
|
|
3
5
|
#
|
|
@@ -63,7 +65,7 @@ module Mongoid
|
|
|
63
65
|
# @param [Numeric] r radius
|
|
64
66
|
# @return [Array] [point, r] point and radius in mongoid format
|
|
65
67
|
#
|
|
66
|
-
def radius(r = 1)
|
|
68
|
+
def radius(r = 1) # rubocop:disable Naming/MethodParameterName
|
|
67
69
|
[center, r]
|
|
68
70
|
end
|
|
69
71
|
|
|
@@ -75,7 +77,7 @@ module Mongoid
|
|
|
75
77
|
# @see Point#radius
|
|
76
78
|
# @return [Array]
|
|
77
79
|
#
|
|
78
|
-
def radius_sphere(r = 1, unit = :km)
|
|
80
|
+
def radius_sphere(r = 1, unit = :km) # rubocop:disable Naming/MethodParameterName
|
|
79
81
|
radius r.to_f / Mongoid::Geospatial.earth_radius[unit]
|
|
80
82
|
end
|
|
81
83
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mongoid
|
|
4
|
+
module Geospatial
|
|
5
|
+
#
|
|
6
|
+
# The pin, named `geom`, on a 2dsphere index.
|
|
7
|
+
#
|
|
8
|
+
module Geom
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
included do
|
|
12
|
+
include Mongoid::Geospatial
|
|
13
|
+
|
|
14
|
+
geom
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def located?
|
|
18
|
+
geom.present?
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# `$geoWithin` with a circle. Mongoid ships `within_polygon` and `within_box`
|
|
5
|
+
# and stopped there — the two circle shapes left with Origin, and `Point#radius`
|
|
6
|
+
# / `#radius_sphere` have been building their argument ever since.
|
|
7
|
+
#
|
|
8
|
+
# Bar.where(:location.within_circle => elvis.location.radius(0.05))
|
|
9
|
+
# Bar.where(:location.within_spherical_circle => elvis.location.radius_sphere(5, :km))
|
|
10
|
+
#
|
|
11
|
+
# `$center` reads its radius in the coordinate system's own units (degrees, for
|
|
12
|
+
# a legacy pair); `$centerSphere` reads radians, which is what `radius_sphere`
|
|
13
|
+
# returns. Guarded: if Mongoid ever registers these, its own wins.
|
|
14
|
+
#
|
|
15
|
+
%i[within_circle within_spherical_circle].each do |name|
|
|
16
|
+
next if Symbol.method_defined?(name)
|
|
17
|
+
|
|
18
|
+
operator = name == :within_circle ? '$center' : '$centerSphere'
|
|
19
|
+
Symbol.add_key(name, :override, '$geoWithin', operator)
|
|
20
|
+
end
|