Angle difference between two bearings: Difference between revisions
(→{{header|Javascript}}: ES6) |
|||
Line 48: | Line 48: | ||
=={{header|Javascript}}== |
=={{header|Javascript}}== |
||
===ES5=== |
|||
This approach should be reliable but it is also very inefficient. |
This approach should be reliable but it is also very inefficient. |
||
Line 83: | Line 83: | ||
170.00000000000003 |
170.00000000000003 |
||
-170.00000041135996</pre> |
-170.00000041135996</pre> |
||
===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> |
|||
{{Out}} |
|||
<pre> |
|||
20° + 45° -> 25.00° |
|||
-45° + 45° -> 90.00° |
|||
-85° + 90° -> 175.0° |
|||
-95° + 90° -> -175.0° |
|||
-45° + 125° -> 170.0° |
|||
-45° + 145° -> -170.0°</pre> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |
Revision as of 07:14, 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 20 ∠ 45 = 25 -45 ∠ 45 = 90 -85 ∠ 90 = 175 -95 ∠ 90 = -175 -45 ∠ 125 = 170 -45 ∠ 145 = -170