Class: SGS::Bearing

Inherits:
Object
  • Object
show all
Defined in:
lib/sgs/bearing.rb

Overview

Class for dealing with the angle/distance vector.

 Note that for convenience, we retain the angle in Radians. The distance is in nautical miles.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(angle = 0.0, distance = 0.0) ⇒ Bearing

Create the Bearing instance. Angle is in radians, distance in nautical miles.



54
55
56
57
# File 'lib/sgs/bearing.rb', line 54

def initialize(angle = 0.0, distance = 0.0)
  self.angle = angle.to_f
  self.distance = distance.to_f
end

Instance Attribute Details

#distanceObject

Returns the value of attribute distance.



49
50
51
# File 'lib/sgs/bearing.rb', line 49

def distance
  @distance
end

Class Method Details

.absolute(angle) ⇒ Object

Handy function to re-adjust an angle away from negative



96
97
98
# File 'lib/sgs/bearing.rb', line 96

def self.absolute(angle)
  (angle + 2.0 * Math::PI) % (2.0 * Math::PI)
end

.absolute_d(angle) ⇒ Object

Another handy function to re-adjust an angle (in degrees) away from negative.



103
104
105
# File 'lib/sgs/bearing.rb', line 103

def self.absolute_d(angle)
  (angle + 360) % 360
end

.compute(loc1, loc2) ⇒ Object

Haversine formula for calculating distance and angle, given two locations.

To calculate an angle and distance from two positions:

This code was derived from formulae on the Movable Type site: www.movable-type.co.uk/scripts/latlong.html

var d = Math.acos(Math.sin(lat1)*Math.sin(lat2) +

Math.cos(lat1)*Math.cos(lat2) *
Math.cos(lon2-lon1)) * R;

var y = Math.sin(dLon) * Math.cos(lat2); var x = Math.cos(lat1)*Math.sin(lat2) -

Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);

var angle = Math.atan2(y, x).toDeg();



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/sgs/bearing.rb', line 123

def self.compute(loc1, loc2)
  bearing = new
  sin_lat1 = Math.sin(loc1.latitude)
  sin_lat2 = Math.sin(loc2.latitude)
  cos_lat1 = Math.cos(loc1.latitude)
  cos_lat2 = Math.cos(loc2.latitude)
  sin_dlon = Math.sin(loc2.longitude - loc1.longitude)
  cos_dlon = Math.cos(loc2.longitude - loc1.longitude)
  bearing.distance = Math.acos(sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon) *
                            EARTH_RADIUS
  y = sin_dlon * cos_lat2
  x = cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon
  bearing.angle = Math.atan2(y, x)
  bearing
end

.degrees(angle, distance) ⇒ Object

Create a bearing from an angle in degrees.



61
62
63
# File 'lib/sgs/bearing.rb', line 61

def self.degrees(angle, distance)
  new(Bearing.dtor(angle), distance)
end

.dtor(deg) ⇒ Object

Handy function to translate degrees to radians



67
68
69
# File 'lib/sgs/bearing.rb', line 67

def self.dtor(deg)
  deg.to_f * Math::PI / 180.0
end

.rtod(rad) ⇒ Object

Handy function to translate radians to degrees



73
74
75
# File 'lib/sgs/bearing.rb', line 73

def self.rtod(rad)
  rad.to_f * 180.0 / Math::PI
end

.rtox(rad) ⇒ Object

Convert radians to hex-degrees.



90
91
92
# File 'lib/sgs/bearing.rb', line 90

def self.rtox(rad)
  (rad.to_f * 128.0 / Math::PI).round.to_i & 0xff
end

.xtor(val) ⇒ Object

Convert boat angle (0->255) to radians. The boat uses an 8bit quantity to represent an angle, where 256 maps to 360 degrees. This makes angle arithmetic quite simple on an 8 bit processor, but useless for something which has a proper FPU. These two helper functions convert to and from radians.



83
84
85
86
# File 'lib/sgs/bearing.rb', line 83

def self.xtor(val)
  val &= 0xff
  val.to_f * Math::PI / 128.0
end

Instance Method Details

#angleObject

Get the angle



147
148
149
# File 'lib/sgs/bearing.rb', line 147

def angle
  @angle
end

#angle=(angle) ⇒ Object

Set the angle



141
142
143
# File 'lib/sgs/bearing.rb', line 141

def angle=(angle)
  @angle = Bearing.absolute(angle)
end

#angle_dObject

Return the angle (in degrees)



153
154
155
# File 'lib/sgs/bearing.rb', line 153

def angle_d
  Bearing.rtod(@angle).to_i
end

#back_angleObject

Get the back-angle (the angle viewed from the opposite end of the line)



159
160
161
# File 'lib/sgs/bearing.rb', line 159

def back_angle
  Bearing.absolute(@angle - Math::PI)
end

#distance_mObject

Return the distance in metres



165
166
167
# File 'lib/sgs/bearing.rb', line 165

def distance_m
  @distance * 1852.0
end

#to_sObject

Convert to a string



171
172
173
174
175
176
177
# File 'lib/sgs/bearing.rb', line 171

def to_s
  if @distance > 0.9
    "BRNG %03dd,%.3fNM" % [angle_d, @distance]
  else
    "BRNG %03dd,%.1fm" % [angle_d, distance_m]
  end
end