cartier 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,24 +1,24 @@
1
- module Cartier
2
- class GPSLocation
3
- attr_accessor :latitude, :longitude, :decimal_notation, :imperial
1
+ module Cartier
2
+ class GPSLocation
3
+ attr_accessor :latitude, :longitude, :decimal_notation, :imperial
4
4
  #
5
5
  #
6
6
  # * *Args* :
7
- # - +latitude+ -> Latitude in Degree Notation (i.e. 37.0428759)
8
- # - +longitude+ -> Longitude in Degree Notation (i.e. 37.0428759)
9
- # - +decimal_notation+ -> Defaulting to true for now
10
- # - +imperial+ -> Defaulting to Imperial system instead of metric (for now)
7
+ # - +latitude+ -> Latitude in Degree Notation (i.e. 37.0428759)
8
+ # - +longitude+ -> Longitude in Degree Notation (i.e. -79.0428759)
9
+ # - +decimal_notation+ -> Defaulting to true for now
10
+ # - +imperial+ -> Defaulting metric system
11
11
  # * *Returns* :
12
12
  # - a GPSLocation object
13
13
  # * *Raises* :
14
14
  # - ++ ->
15
- #
16
- def initialize(latitude=nil, longitude=nil, decimal_notation=true, imperial=true)
17
- self.latitude = latitude
18
- self.longitude = longitude
19
- self.decimal_notation = decimal_notation
20
- self.imperial = imperial
21
- end
22
-
23
- end
15
+ #
16
+ def initialize(latitude=nil, longitude=nil, decimal_notation=true, imperial=false)
17
+ self.latitude = latitude
18
+ self.longitude = longitude
19
+ self.decimal_notation = decimal_notation
20
+ self.imperial = imperial
21
+ end
22
+
23
+ end
24
24
  end
@@ -1,62 +1,137 @@
1
- module Cartier
2
-
3
- # Encapsulating class for Navigation calculations
4
- class Navigation
5
- EARTH_RADIUS = 6371
6
-
7
- #
8
- #
9
- # * *Args* :
10
- # - +location+ -> GPSLocation object representing current location
11
- # - +longitude+ -> GPSLocation object representing current destination
12
- # * *Returns* :
13
- # - distance in miles
14
-
15
- def self.haversine_distance(location, destination)
16
- delta_lat = (destination.latitude.to_f - location.latitude.to_f) * Math::PI/180
17
- delta_long = (destination.longitude.to_f - location.longitude.to_f) * Math::PI/180
18
-
19
- latitude_1 = (location.latitude.to_f) * Math::PI/180
20
- latitude_2 = (destination.latitude.to_f) * Math::PI/180
21
-
22
- a = Math.sin(delta_lat/2)**2 + Math.sin(delta_long/2)**2 * Math.cos(latitude_1) * Math.cos(latitude_2)
23
- c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
24
- EARTH_RADIUS * c
25
- end
26
-
27
- #
28
- #
29
- # * *Args* :
30
- # - +location_here+ -> GPSLocation object representing current location
31
- # - +array_of_locations+ -> an Array of GPSLocation objects
32
- # * *Returns* :
33
- # - GPSLocation object representing closest location
34
- #
35
- def self.closest_point(location_here, array_of_locations=nil)
36
- array_of_locations.sort do |a, b|
37
- self.haversine_distance(location_here, a) <=> self.haversine_distance(location_here, b)
38
- end.first
39
- end
40
-
41
- #
42
- #
43
- # * *Args* :
44
- # - +location+ -> GPSLocation object representing current location
45
- # - +destination+ -> GPSLocation object representing destination
46
- # * *Returns* :
47
- # - Bearing in Degrees (not radians)
48
- #
49
- def self.get_bearing(location, destination)
50
- location_long = location.longitude.to_f
51
- location_latitude = location.latitude.to_f
52
- destination_long = destination.longitude.to_f
53
- destination_latitude = destination.latitude.to_f
54
-
55
- delta_long = (destination_long - location_long)
56
- y = Math.sin(delta_long) * Math.cos(destination_latitude)
57
- x = Math.cos(location_latitude) * Math.sin(destination_latitude) - Math.sin(location_latitude) * Math.cos(destination_latitude) * Math.cos(delta_long)
58
- (Math.atan2(y, x) / Math::PI) * 180
59
- end
60
-
61
- end
1
+ module Cartier
2
+
3
+ # Encapsulating class for Navigation calculations
4
+ class Navigation
5
+ #radius in km
6
+ EARTH_RADIUS = 6371
7
+ RADIANS = 57.29578
8
+
9
+ #
10
+ #
11
+ # * *Args* :
12
+ # - +location+ -> GPSLocation object representing current location
13
+ # - +longitude+ -> GPSLocation object representing current destination
14
+ # * *Returns* :
15
+ # - distance in km
16
+ def self.haversine_distance(location, destination)
17
+ delta_lat = (destination.latitude.to_f - location.latitude.to_f) * Math::PI/180
18
+ delta_long = (destination.longitude.to_f - location.longitude.to_f) * Math::PI/180
19
+
20
+ latitude_1 = (location.latitude.to_f) * Math::PI/180
21
+ latitude_2 = (destination.latitude.to_f) * Math::PI/180
22
+
23
+ a = Math.sin(delta_lat/2)**2 + Math.sin(delta_long/2)**2 * Math.cos(latitude_1) * Math.cos(latitude_2)
24
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
25
+ EARTH_RADIUS * c
26
+ end
27
+
28
+ #
29
+ #
30
+ # * *Args* :
31
+ # - +location+ -> GPSLocation object representing current location
32
+ # - +longitude+ -> GPSLocation object representing current destination
33
+ # * *Returns* :
34
+ # - distance in km
35
+ def self.equirectangular_projection(location, destination)
36
+ latitude_1 = (location.latitude.to_f) * Math::PI/180
37
+ latitude_2 = (destination.latitude.to_f) * Math::PI/180
38
+
39
+ longitude_1 = (location.longitude.to_f) * Math::PI/180
40
+ longitude_2 = (destination.longitude.to_f) * Math::PI/180
41
+
42
+ x = (longitude_2 - longitude_1) * Math.cos((latitude_1+latitude_2)/2)
43
+ y = latitude_2 - latitude_1
44
+ Math.sqrt(x*x + y*y) * EARTH_RADIUS
45
+ end
46
+
47
+ #
48
+ #
49
+ # * *Args* :
50
+ # - +location_here+ -> GPSLocation object representing current location
51
+ # - +array_of_locations+ -> an Array of GPSLocation objects
52
+ # * *Returns* :
53
+ # - GPSLocation object representing closest location
54
+ #
55
+ def self.closest_point(location_here, array_of_locations=nil)
56
+ array_of_locations.sort do |a, b|
57
+ self.haversine_distance(location_here, a) <=> self.haversine_distance(location_here, b)
58
+ end.first
59
+ end
60
+
61
+ #
62
+ #
63
+ # * *Args* :
64
+ # - +location+ -> GPSLocation object representing current location
65
+ # - +destination+ -> GPSLocation object representing destination
66
+ # * *Returns* :
67
+ # - Bearing in Degrees (not radians)
68
+ #
69
+ def self.get_bearing(location, destination)
70
+ location_long = location.longitude.to_f * Math::PI/180
71
+ location_latitude = location.latitude.to_f * Math::PI/180
72
+ destination_long = destination.longitude.to_f
73
+ destination_latitude = destination.latitude.to_f
74
+
75
+ delta_long = (destination_long - location_long) * Math::PI/180
76
+ y = Math.sin(delta_long) * Math.cos(destination_latitude)
77
+ x = Math.cos(location_latitude) * Math.sin(destination_latitude) - Math.sin(location_latitude) * Math.cos(destination_latitude) * Math.cos(delta_long)
78
+ theta = (Math.atan2(y, x) / Math::PI) * 180
79
+ (theta + 360) % 360
80
+ end
81
+
82
+
83
+ #
84
+ #
85
+ # * *Args* :
86
+ # - +location+ -> GPSLocation object representing current location
87
+ # - +destination+ -> GPSLocation object representing destination
88
+ # * *Returns* :
89
+ # - Cartier::GPSLocation object representing midpoint
90
+ #
91
+ def self.get_midpoint(location, destination)
92
+ latitude_1 = location.latitude.to_f * Math::PI/180
93
+ longitude_1 = location.longitude.to_f * Math::PI/180
94
+ latitude_2 = destination.latitude.to_f * Math::PI/180
95
+ delta_long = (destination.longitude.to_f - location.longitude.to_f) * Math::PI/180
96
+
97
+ bx = Math.cos(latitude_2) * Math.cos(delta_long)
98
+ by = Math.cos(latitude_2) * Math.sin(delta_long)
99
+
100
+ latitude_3 = Math.atan2(Math.sin(latitude_1) + Math.sin(latitude_2),
101
+ Math.sqrt( (Math.cos(latitude_1)+bx)*(Math.cos(latitude_1)+bx) + by*by))
102
+ longitude_3 = longitude_1 + Math.atan2(by, Math.cos(latitude_1) + bx)
103
+ longitude_3 = (longitude_3+3*Math::PI) % (2*Math::PI) - Math::PI
104
+
105
+ latitude_3 = latitude_3 * RADIANS
106
+ longitude_3 = longitude_3 * RADIANS
107
+ Cartier::GPSLocation.new(latitude_3.to_s, longitude_3.to_s)
108
+ end
109
+
110
+ #
111
+ #
112
+ # * *Args* :
113
+ # - +location+ -> Cartier::GPSLocation
114
+ # - +bearing+ -> Bearing in Degrees
115
+ # - +distance+ -> Distance in km
116
+ # * *Returns* :
117
+ # - Cartier::GPSLocation object representing final point
118
+ #
119
+ def self.get_destination_point(location, bearing, distance)
120
+ distance_in_radians = distance / EARTH_RADIUS
121
+ bearing_in_radians = bearing * Math::PI/180
122
+
123
+ latitude_1 = location.latitude.to_f * Math::PI/180
124
+ longitude_1 = location.longitude.to_f * Math::PI/180
125
+
126
+ latitude_2 = Math.asin( Math.sin(latitude_1)*Math.cos(distance_in_radians) +
127
+ Math.cos(latitude_1)*Math.sin(distance_in_radians)*Math.cos(bearing_in_radians) )
128
+ longitude_2 = longitude_1 + Math.atan2(Math.sin(bearing_in_radians)*Math.sin(distance_in_radians)*Math.cos(latitude_1),
129
+ Math.cos(distance_in_radians)-Math.sin(latitude_1)*Math.sin(latitude_2))
130
+ longitude_2 = (longitude_2+3*Math::PI) % (2*Math::PI) - Math::PI
131
+ latitude_2 = latitude_2 * RADIANS
132
+ longitude_2 = longitude_2 * RADIANS
133
+ Cartier::GPSLocation.new(latitude_2.to_s, longitude_2.to_s)
134
+ end
135
+
136
+ end
62
137
  end
@@ -1,3 +1,3 @@
1
- module Cartier
2
- VERSION = "0.0.1"
3
- end
1
+ module Cartier
2
+ VERSION = "0.0.2"
3
+ end
@@ -1,36 +1,60 @@
1
- require 'spec_helper'
2
- require 'factories/location_factory'
3
-
4
- include Cartier
5
-
6
- describe Cartier::Navigation do
7
- it "distance to self should be 0.0" do
8
- @location = FactoryGirl.build(:cn_tower)
9
- Cartier::Navigation.haversine_distance(@location, @location).should == 0.0
10
- end
11
-
12
- it "distance to washington monument should not be zero" do
13
- @cn_tower = FactoryGirl.build(:cn_tower)
14
- @washington_monument = FactoryGirl.build(:washington_monument)
15
- Cartier::Navigation.haversine_distance(@cn_tower, @washington_monument).should == 563.7658958719776
16
- end
17
-
18
- it ".closest_point should find the closest point" do
19
- @here = FactoryGirl.build(:cn_tower)
20
- @ago = FactoryGirl.build(:ago)
21
- @washington_monument = FactoryGirl.build(:washington_monument)
22
- Cartier::Navigation.closest_point(@here, [@ago, @washington_monument]).should == @ago
23
- end
24
-
25
- it ".get_bearing should calculate the bearing between cn_tower and ago properly" do
26
- @here = FactoryGirl.build(:cn_tower)
27
- @ago = FactoryGirl.build(:ago)
28
- Cartier::Navigation.get_bearing(@here, @ago).should == -42.86284026213279
29
- end
30
-
31
- it ".get_bearing should calculate the bearing between two points" do
32
- @here = FactoryGirl.build(:cn_tower)
33
- @ago = FactoryGirl.build(:washington_monument)
34
- Cartier::Navigation.get_bearing(@here, @ago).should == 18.121412196238214
35
- end
1
+ require 'spec_helper'
2
+ require 'factories/location_factory'
3
+
4
+ include Cartier
5
+
6
+ describe Cartier::Navigation do
7
+ it ".haversine_distance to self should be 0.0" do
8
+ @location = FactoryGirl.build(:cn_tower)
9
+ Cartier::Navigation.haversine_distance(@location, @location).should == 0.0
10
+ end
11
+
12
+ it ".haversine_distance to washington monument should not be zero" do
13
+ @cn_tower = FactoryGirl.build(:cn_tower)
14
+ @washington_monument = FactoryGirl.build(:washington_monument)
15
+ Cartier::Navigation.haversine_distance(@cn_tower, @washington_monument).should == 563.7658958719776
16
+ end
17
+
18
+ it ".equirectangular_projection to self should be 0.0" do
19
+ @location = FactoryGirl.build(:cn_tower)
20
+ Cartier::Navigation.equirectangular_projection(@location, @location).should == 0.0
21
+ end
22
+
23
+ it ".equirectangular_projection to washington monument should not be zero" do
24
+ @cn_tower = FactoryGirl.build(:cn_tower)
25
+ @washington_monument = FactoryGirl.build(:washington_monument)
26
+ Cartier::Navigation.equirectangular_projection(@cn_tower, @washington_monument).should == 563.8330522056333
27
+ end
28
+
29
+ it ".closest_point should find the closest point" do
30
+ @here = FactoryGirl.build(:cn_tower)
31
+ @ago = FactoryGirl.build(:ago)
32
+ @washington_monument = FactoryGirl.build(:washington_monument)
33
+ Cartier::Navigation.closest_point(@here, [@ago, @washington_monument]).should == @ago
34
+ end
35
+
36
+ it ".get_bearing should calculate the bearing between cn_tower and ago properly" do
37
+ @here = FactoryGirl.build(:cn_tower)
38
+ @ago = FactoryGirl.build(:ago)
39
+ Cartier::Navigation.get_bearing(@here, @ago).should == 248.24661021678037
40
+ end
41
+
42
+ it ".get_midpoint should find the proper location between two points" do
43
+ @here = FactoryGirl.build(:cn_tower)
44
+ @there = FactoryGirl.build(:washington_monument)
45
+ expected = Cartier::GPSLocation.new("41.277422062362376", "-78.16834424548739")
46
+ Cartier::Navigation.get_midpoint(@here, @there).latitude.should == expected.latitude
47
+ Cartier::Navigation.get_midpoint(@here, @there).longitude.should == expected.longitude
48
+ end
49
+
50
+ it ".get_destination_point will find the proper location from current location, bearing and distance" do
51
+ @here = FactoryGirl.build(:cn_tower)
52
+ @bearing = 180
53
+ @distance = 200
54
+ expected = Cartier::GPSLocation.new("43.64775274320249", "-79.3870789598738")
55
+ Cartier::Navigation.get_destination_point(@here, @bearing, @distance).latitude.should == expected.latitude
56
+ Cartier::Navigation.get_destination_point(@here, @bearing, @distance).longitude.should == expected.longitude
57
+ end
58
+
59
+
36
60
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cartier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-20 00:00:00.000000000 Z
12
+ date: 2012-07-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec