cartier 0.0.1 → 0.0.2

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.
@@ -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