mongoid_spacial 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.5
1
+ 0.2.6
@@ -19,15 +19,19 @@ module Mongoid
19
19
  LNG_SYMBOLS = [:x, :lon, :long, :lng, :longitude]
20
20
  LAT_SYMBOLS = [:y, :lat, :latitude]
21
21
 
22
- def self.distance(p1,p2,unit = nil, formula = nil)
23
- formula ||= @@distance_formula
24
-
22
+ def self.distance(p1,p2,opts = {})
23
+ opts[:formula] ||= (opts[:spherical]) ? @@spherical_distance_formula : :pythagorean_theorem
25
24
  p1 = p1.to_lng_lat if p1.respond_to?(:to_lng_lat)
26
25
  p2 = p2.to_lng_lat if p2.respond_to?(:to_lng_lat)
27
26
 
28
- unit = earth_radius[unit] if unit.kind_of?(Symbol) && earth_radius[unit]
29
- rads = Formulas.send(formula, p1, p2)
30
- (unit.kind_of?(Numeric)) ? unit*rads : rads
27
+ rads = Formulas.send(opts[:formula], p1, p2)
28
+
29
+ if unit = earth_radius[opts[:unit]]
30
+ opts[:unit] = (rads.instance_variable_get("@radian")) ? unit : unit * RAD_PER_DEG
31
+ end
32
+
33
+ rads *= opts[:unit].to_f if opts[:unit]
34
+ rads
31
35
  end
32
36
 
33
37
  mattr_accessor :lng_symbols
@@ -39,13 +43,14 @@ module Mongoid
39
43
  mattr_accessor :earth_radius
40
44
  @@earth_radius = EARTH_RADIUS.dup
41
45
 
42
- mattr_accessor :distance_formula
43
- @@distance_formula = :n_vector
44
-
45
- mattr_accessor :paginator
46
- @@paginator = :array
46
+ mattr_accessor :paginator
47
+ @@paginator = :array
47
48
 
48
49
  mattr_accessor :default_per_page
49
50
  @@default_per_page = 25
51
+
52
+ mattr_accessor :spherical_distance_formula
53
+ @@spherical_distance_formula = :n_vector
54
+
50
55
  end
51
56
  end
@@ -21,9 +21,9 @@ module Mongoid
21
21
  end
22
22
 
23
23
  module InstanceMethods #:nodoc:
24
- def distance_from(key,p2, unit = nil, formula = nil)
24
+ def distance_from(key,p2, opts = {})
25
25
  p1 = self.send(key)
26
- Mongoid::Spacial.distance(p1, p2, unit, formula = nil)
26
+ Mongoid::Spacial.distance(p1, p2, opts)
27
27
  end
28
28
  end
29
29
  end
@@ -1,42 +1,51 @@
1
1
  module Mongoid
2
2
  module Spacial
3
3
  module Formulas
4
+ class << self
5
+ def n_vector(point1,point2)
6
+ p1 = point1.map{|deg| deg * RAD_PER_DEG}
7
+ p2 = point2.map{|deg| deg * RAD_PER_DEG}
4
8
 
5
- def self.n_vector(point1,point2)
6
- p1 = point1.map{|deg| deg * RAD_PER_DEG}
7
- p2 = point2.map{|deg| deg * RAD_PER_DEG}
9
+ sin_x1 = Math.sin(p1[0])
10
+ cos_x1 = Math.cos(p1[0])
8
11
 
9
- sin_x1 = Math.sin(p1[0])
10
- cos_x1 = Math.cos(p1[0])
12
+ sin_y1 = Math.sin(p1[1])
13
+ cos_y1 = Math.cos(p1[1])
11
14
 
12
- sin_y1 = Math.sin(p1[1])
13
- cos_y1 = Math.cos(p1[1])
15
+ sin_x2 = Math.sin(p2[0])
16
+ cos_x2 = Math.cos(p2[0])
14
17
 
15
- sin_x2 = Math.sin(p2[0])
16
- cos_x2 = Math.cos(p2[0])
18
+ sin_y2 = Math.sin(p2[1])
19
+ cos_y2 = Math.cos(p2[1])
17
20
 
18
- sin_y2 = Math.sin(p2[1])
19
- cos_y2 = Math.cos(p2[1])
21
+ cross_prod = (cos_y1*cos_x1 * cos_y2*cos_x2) +
22
+ (cos_y1*sin_x1 * cos_y2*sin_x2) +
23
+ (sin_y1 * sin_y2)
20
24
 
21
- cross_prod = (cos_y1*cos_x1 * cos_y2*cos_x2) +
22
- (cos_y1*sin_x1 * cos_y2*sin_x2) +
23
- (sin_y1 * sin_y2)
25
+ return cross_prod > 0 ? 0 : Math::PI if (cross_prod >= 1 || cross_prod <= -1)
24
26
 
25
- return cross_prod > 0 ? 0 : Math::PI if (cross_prod >= 1 || cross_prod <= -1)
27
+ d = Math.acos(cross_prod)
28
+ d.instance_variable_set("@radian", true)
29
+ d
30
+ end
26
31
 
27
- Math.acos(cross_prod)
28
- end
32
+ def haversine(point1,point2)
33
+ p1 = point1.map{|deg| deg * RAD_PER_DEG}
34
+ p2 = point2.map{|deg| deg * RAD_PER_DEG}
29
35
 
30
- def self.haversine(point1,point2)
31
- p1 = point1.map{|deg| deg * RAD_PER_DEG}
32
- p2 = point2.map{|deg| deg * RAD_PER_DEG}
36
+ dlon = p2[0] - p1[0]
37
+ dlat = p2[1] - p1[1]
33
38
 
34
- dlon = p2[0] - p1[0]
35
- dlat = p2[1] - p1[1]
39
+ a = (Math.sin(dlat/2))**2 + Math.cos(p1[1]) * Math.cos(p2[1]) * (Math.sin(dlon/2))**2
36
40
 
37
- a = (Math.sin(dlat/2))**2 + Math.cos(p1[1]) * Math.cos(p2[1]) * (Math.sin(dlon/2))**2
41
+ d = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
42
+ d.instance_variable_set("@radian", true)
43
+ d
44
+ end
38
45
 
39
- 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
46
+ def pythagorean_theorem(p1, p2)
47
+ Math.sqrt(((p2[0] - p1[0]) ** 2) + ((p2[1] - p1[1]) ** 2))
48
+ end
40
49
  end
41
50
  end
42
51
  end
@@ -34,7 +34,7 @@ module Mongoid
34
34
  end
35
35
  @opts[:calculate].each do |key|
36
36
  key = (key.to_s+'_distance').to_sym
37
- res.geo[key] = res.distance_from(key,center, @opts[:distance_multiplier])
37
+ res.geo[key] = res.distance_from(key,center,{:unit =>@opts[:unit] || @opts[:distance_multiplier], :spherical => @opts[:spherical]} )
38
38
  res.geo[:distance] = res.geo[key] if primary && key == primary
39
39
  end
40
40
  end
@@ -51,7 +51,7 @@ module Mongoid
51
51
 
52
52
  def page(page, options = {})
53
53
  new_collection = self.dup
54
-
54
+
55
55
  options = self.opts.merge(options)
56
56
 
57
57
  options[:page] = page || 1
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoid_spacial}
8
- s.version = "0.2.5"
8
+ s.version = "0.2.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Ryan Ong}]
@@ -47,6 +47,7 @@ Gem::Specification.new do |s|
47
47
  "spec/functional/mongoid/contexts/mongo_spec.rb",
48
48
  "spec/functional/mongoid/criterion/inclusion_spec.rb",
49
49
  "spec/functional/mongoid/spacial/geo_near_results_spec.rb",
50
+ "spec/functional/mongoid/spacial_spec.rb",
50
51
  "spec/models/account.rb",
51
52
  "spec/models/acolyte.rb",
52
53
  "spec/models/address.rb",
@@ -122,7 +123,8 @@ Gem::Specification.new do |s|
122
123
  "spec/unit/mongoid/criterion/inclusion_spec.rb",
123
124
  "spec/unit/mongoid/criterion/near_spacial_spec.rb",
124
125
  "spec/unit/mongoid/criterion/within_spacial_spec.rb",
125
- "spec/unit/mongoid/spacial/formulas_spec.rb"
126
+ "spec/unit/mongoid/spacial/formulas_spec.rb",
127
+ "spec/unit/mongoid/spacial_spec.rb"
126
128
  ]
127
129
  s.homepage = %q{http://github.com/ryanong/mongoid_spacial}
128
130
  s.licenses = [%q{MIT}]
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Spacial do
4
+ describe '#distance' do
5
+ it "should calculate 2d by default" do
6
+ Mongoid::Spacial.distance([0,0],[3,4]).should == 5
7
+ end
8
+
9
+ it "should calculate 2d distances using degrees" do
10
+ Mongoid::Spacial.distance([0,0],[3,4], :unit=>:mi).should == 5*Mongoid::Spacial::EARTH_RADIUS[:mi]*Mongoid::Spacial::RAD_PER_DEG
11
+ end
12
+
13
+ it "should calculate 3d distances by default" do
14
+ Mongoid::Spacial.distance([-73.77694444, 40.63861111 ],[-118.40, 33.94],:unit=>:mi, :spherical => true).to_i.should be_within(1).of(2469)
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,6 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Spacial do
4
+ describe '#distance' do
5
+ end
6
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mongoid_spacial
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.5
5
+ version: 0.2.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ryan Ong
@@ -173,6 +173,7 @@ files:
173
173
  - spec/functional/mongoid/contexts/mongo_spec.rb
174
174
  - spec/functional/mongoid/criterion/inclusion_spec.rb
175
175
  - spec/functional/mongoid/spacial/geo_near_results_spec.rb
176
+ - spec/functional/mongoid/spacial_spec.rb
176
177
  - spec/models/account.rb
177
178
  - spec/models/acolyte.rb
178
179
  - spec/models/address.rb
@@ -249,6 +250,7 @@ files:
249
250
  - spec/unit/mongoid/criterion/near_spacial_spec.rb
250
251
  - spec/unit/mongoid/criterion/within_spacial_spec.rb
251
252
  - spec/unit/mongoid/spacial/formulas_spec.rb
253
+ - spec/unit/mongoid/spacial_spec.rb
252
254
  homepage: http://github.com/ryanong/mongoid_spacial
253
255
  licenses:
254
256
  - MIT
@@ -262,7 +264,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
264
  requirements:
263
265
  - - ">="
264
266
  - !ruby/object:Gem::Version
265
- hash: 4489034122612301384
267
+ hash: 1525314815871723941
266
268
  segments:
267
269
  - 0
268
270
  version: "0"