## Angles on a compass

MJ -- To determine the difference between two directions on a compass the proc below can be used. It can most likely be written shorter, but it should at least give the correct answer.

For two compass courses \$a and \$b it will calculate the difference in degrees and whether you need to go clockwise (positive return) or counterclockwise (negative return) to go from course \$a to \$b.

``` proc anglediff {a b} {
set a [expr {\$a%360}]
set b [expr {\$b%360}]
set dclockwise [expr (360-\$a+\$b)%360]

return [expr {\$dclockwise<=180?\$dclockwise:-(360-\$dclockwise)}]
}

# and some tests:

proc assert_equal {a b} {
if {\$a != \$b} { error "assertion \$a==\$b failed"}
}

assert_equal [anglediff   1  359]  -2
assert_equal [anglediff   0  180] 180
assert_equal [anglediff -10   10]  20
assert_equal [anglediff 360    0]   0
assert_equal [anglediff 180 -180]   0
assert_equal [anglediff -10  340] -10```

dzach I use a similar routine often. Only, to make it work with decimal angles, one has to use fmod():

``` proc anglediff {a b} {
set dclockwise [expr {fmod(360-fmod(\$a,360)+fmod(\$b,360),360)}]
expr {\$dclockwise<=180?\$dclockwise:-(360-\$dclockwise)}
}```
``` % anglediff   1  359
-2.0
% time {anglediff   1  359} 1000
3.232 microseconds per iteration```

To make it faster, I use C and critcl:

``` critcl::cproc dcourse {double a double b} double {
double dc = fmod(360.0 - fmod(a,360) + fmod(b,360), 360);
return dc <= 180 ? dc : dc - 360;
}```
``` % load ./dcourse.so
% dcourse 1 359
-2.0
% time {dcourse 1 359} 1000
0.782 microseconds per iteration```

 Category Geography Category Mathematics Category Toys