Angle difference between two bearings: Difference between revisions
(→{{header|Javascript}}: ES6) |
Thundergnat (talk | contribs) (→{{header|Perl 6}}: remove extraneous line (copy / paste error)) |
||
Line 162: | Line 162: | ||
{{out}} |
{{out}} |
||
<pre>20 ∠ 45 = 25 |
<pre>20 ∠ 45 = 25 |
||
20 ∠ 45 = 25 |
|||
-45 ∠ 45 = 90 |
-45 ∠ 45 = 90 |
||
-85 ∠ 90 = 175 |
-85 ∠ 90 = 175 |
Revision as of 11:47, 16 December 2016
Finding the angle between two bearings is often confusing.[1]
- Task
We need to find the angle which is the result of the subtraction b2-b1, where b1 and b2 are both bearings. The result must be expressed in the range +180 to -180 degrees. Compute the angle for the following pairs:
- 20 degrees (b1) and 45 degrees (b2)
- -45 and 45
- -85 and 90
- -95 and 90
- -45 and 125
- -45 and 145
C++
<lang javascript>#include <cmath>
- include <iostream>
using namespace std;
double getDifference(double b1, double b2) { double val = std::min((b1-b2)<0?b1-b2+360:b1-b2, (b2-b1)<0?b2-b1+360:b2-b1); if (val > M_PI) val -= 2*M_PI; return val; }
int main() { const double deg2rad = M_PI/180.0; const double rad2deg = 180.0/M_PI; cout << getDifference(20.0*deg2rad, 45.0*deg2rad)*rad2deg << endl; cout << getDifference(-45.0*deg2rad, 45.0*deg2rad)*rad2deg << endl; cout << getDifference(-85.0*deg2rad, 90.0*deg2rad)*rad2deg << endl; cout << getDifference(-95.0*deg2rad, 90.0*deg2rad)*rad2deg << endl; cout << getDifference(-45.0*deg2rad, 125.0*deg2rad)*rad2deg << endl; cout << getDifference(-45.0*deg2rad, 145.0*deg2rad)*rad2deg << endl; return 0; } </lang>
- Output:
25 90 175 -175 170 -170
JavaScript
ES5
This approach should be reliable but it is also very inefficient.
<lang javascript>function relativeBearing(b1Rad, b2Rad) { b1y = Math.cos(b1Rad); b1x = Math.sin(b1Rad); b2y = Math.cos(b2Rad); b2x = Math.sin(b2Rad); crossp = b1y * b2x - b2y * b1x; dotp = b1x * b2x + b1y * b2y; if(crossp > 0.) return Math.acos(dotp); return -Math.acos(dotp); }
function test() { var deg2rad = 3.14159265/180.0; var rad2deg = 180.0/3.14159265; return relativeBearing(20.0*deg2rad, 45.0*deg2rad)*rad2deg+"\n" +relativeBearing(-45.0*deg2rad, 45.0*deg2rad)*rad2deg+"\n" +relativeBearing(-85.0*deg2rad, 90.0*deg2rad)*rad2deg+"\n" +relativeBearing(-95.0*deg2rad, 90.0*deg2rad)*rad2deg+"\n" +relativeBearing(-45.0*deg2rad, 125.0*deg2rad)*rad2deg+"\n" +relativeBearing(-45.0*deg2rad, 145.0*deg2rad)*rad2deg+"\n"; }</lang>
- Output:
25.000000000000004 90 174.99999999999997 -175.00000041135993 170.00000000000003 -170.00000041135996
ES6
<lang JavaScript>(() => {
const [Pi, sin, cos, acos] = ['PI', 'sin', 'cos', 'acos'] .map(k => Math[k]), degRad = x => Pi * x / 180.0, radDeg = x => 180.0 * x / Pi;
// relBearing :: Radians -> Radians -> Radians const relBearing = (ar, br) => { const [ax, ay] = [sin(ar), cos(ar)], [bx, by] = [sin(br), cos(br)],
// Cross-product > 0 ? sign = ((ay * bx) - (by * ax)) > 0 ? +1 : -1;
// Sign * dot-product return sign * acos((ax * bx) + (ay * by)); }
// TEST
// justifyRight :: Int -> Char -> Text -> Text const justifyRight = (n, cFiller, strText) => n > strText.length ? ( (cFiller.repeat(n) + strText) .slice(-n) ) : strText;
// showMap :: Degrees -> Degrees -> String const showMap = (da, db) => justifyRight(6, ' ', `${da}° +`) + justifyRight(11, ' ',` ${db}° -> `) + justifyRight(7, ' ', `${(radDeg(relBearing(degRad(da), degRad(db)))) .toPrecision(4)}°`);
return [ [20, 45], [-45, 45], [-85, 90], [-95, 90], [-45, 125], [-45, 145] ].map(xy => showMap(...xy)) .join('\n');
})();</lang>
- Output:
20° + 45° -> 25.00° -45° + 45° -> 90.00° -85° + 90° -> 175.0° -95° + 90° -> -175.0° -45° + 125° -> 170.0° -45° + 145° -> -170.0°
Perl 6
<lang perl6>sub infix:<∠> (Int $b1, Int $b2) {
(my $b = ($b2 - $b1 + 720) % 360) > 180 ?? $b - 360 !! $b;
}
- TESTING
for 20, 45,
-45, 45, -85, 90, -95, 90, -45, 125, -45, 145 -> $b1, $b2 { say "$b1 ∠ $b2 = ", $b1 ∠ $b2 }</lang>
- Output:
20 ∠ 45 = 25 -45 ∠ 45 = 90 -85 ∠ 90 = 175 -95 ∠ 90 = -175 -45 ∠ 125 = 170 -45 ∠ 145 = -170