This is Part 5 in a multi-part series bout using the location functions in FileMaker Go.
1. Where Am I?
2. What’s Accuracy?
3. Where’s My Stuff?
4. How Far?
5. Which Way?
In my last post, I described how to calculate geographic distances between two locations. That’s fine for knowing how close you are to something, but it’s only half of the picture for knowing your relative location. Is the party 10 km north of your current location, or west?
The calculation of the initial bearing of the straight line “greatest circle” path between two points, like the haversine formula, involves spherical trigonometry that I wont bother you with except to show you the calculation:
Let ( [
// Convert angles to radians
~longitudeDifference = Radians ( endLongitude - startLongitude ) ;
~latitudeDifference = Radians ( endLatitude - startLatitude ) ;
~startLatitude = Radians ( startLatitude ) ;
~startLongitude = Radians ( startLongitude ) ;
~endLatitude = Radians ( endLatitude ) ;
~endLongitude = Radians ( endLongitude ) ;
// calculate forward bearing of path at start point
~bearingY = Sin ( ~longitudeDifference ) * Cos ( ~latitudeDifference ) ;
Cos ( ~startLatitude )
* Sin ( ~endLatitude )
- Sin ( ~startLatitude )
* Cos ( ~endLatitude )
* Cos ( ~longitudeDifference ) ;
~bearing = // Atan2 ( ~bearingY ; ~bearingX ) in range [0,2*Pi)
~bearingX < 0 ;
Atan ( ~bearingY / ~bearingX ) + Pi ;
~bearingX > 0 and ~bearingY < 0 ;
Atan ( ~bearingY / ~bearingX ) + 2 * Pi ;
~bearingX ≠ 0 ;
Atan ( ~bearingY / ~bearingX ) ;
~bearingY > 0 ;
Pi / 2 ;
~bearingY < 0 ;
3 / 2 * Pi ;
/* Else, ~bearingX = ~bearingY = 0 */
Degrees ( ~bearing )
The calculation above will give us a compass bearing, a number of degress between 0 and 360. That’s a fine start, but what am I as a user supposed to do with 143.490867°? Is that left or right? Converting that bearing to a cardinal direction is the natural next step. Since cardinal directions correspond to particular numerical ranges of bearing, we can just test for each range using the Case function to select the matching nominal direction:
$bearing < 45 ; "N" ;
$bearing < 135 ; "E" ;
$bearing < 225 ; "S" ;
$bearing < 315 ; "W" ;
/* Else */ "N"
If we want to use more precise cardinal directions, we can just specify smaller ranges and more of them:
$bearing < 22.5 ; "N" ;
$bearing < 67.5 ; "NE" ;
$bearing < 112.5 ; "E" ;
$bearing < 157.5 ; "SE" ;
$bearing < 202.5 ; "S" ;
$bearing < 247.5 ; "SW" ;
$bearing < 292.5 ; "W" ;
$bearing < 337.5 ; "NW" ;
/* Else */ "N"
This works fine, but something bugs me about it. We’re performing a test of the same variable several times, and the only difference is what number it’s being compared to each time. The ranges being checked are all exactly the same size, but you wouldn’t know that without subtracting each from the next one by one. I hate doing arithmetic myself. This is almost an example of the magic number code smell (but not exactly, since the calculation effectively defines what each numerical range represents). If we let FileMaker figure out what the ranges should be for us, we get an equally effective calculation with some differences that are worth contemplating:
More…Location, Part 5: Which Way? – The Scarpetta Group, Inc..