I just took the Geospatial course by @Paul. I really enjoyed it, he has a wonderful delivery and explained things well.

I tried my hand at writing two M functions based on the course (Haversine get distance and a function to get bearing).

Sharing in case it helps anyone:

// fnGetHaversine

// Source: https://www.geeksforgeeks.org/haversine-formula-to-find-distance-between-two-points-on-a-sphere/

(lat1 as number, lon1 as number, lat2 as number, lon2 as number, optional measure as number)=>

let

// distance between lats and longs

dLat = (lat2-lat1) * Number.PI / 180.0,

dLon = (lon2-lon1) * Number.PI / 180.0,

```
// convert to radians
latitude1 = lat1 * Number.PI / 180.0,
latitude2 = lat2 * Number.PI / 180.0,
// apply formulae
a = (Number.Power(Number.Sin(dLat/2),2) +
Number.Power(Number.Sin(dLon/2),2) *
Number.Cos(latitude1) * Number.Cos(latitude2)),
// default is kilometers but if 1 then miles
r = if measure ?? 0 = 0 then 6371 else 3961,
c = 2 * Number.Asin(Number.Sqrt(a)),
result = Number.Round(r * c,4)
```

in

result

// fnGetBearing

// Source: Paul Lucassen, I wrote this function based on his Enterprise DNA course

(lat1_rad as number, lat2_rad as number, lon1_rad as number, lon2_rad as number)=>

let

Source = Number.Atan2(Number.Sin(lon2_rad-lon1_rad) * Number.Cos(lat2_rad),

Number.Cos(lat1_rad) * Number.Sin(lat2_rad)-Number.Sin(lat1_rad) * Number.Cos(lat2_rad) * Number.Cos((lon2_rad-lon1_rad))),

FromRadians = Source * (180/Number.PI),

CorrectNegative = Number.Mod(FromRadians+360,360),

Round = Number.RoundUp(CorrectNegative),

DirectionResult =

if Round <= 11 or Round >= 349 then [Direction = “N”, Sort=1]

else if Round <= 33 then [Direction = “NNE”, Sort=2]

else if Round <= 55 then [Direction = “NE”, Sort=3]

else if Round <= 77 then [Direction = “ENE”, Sort=4]

else if Round <= 99 then [Direction = “E”, Sort=5]

else if Round <= 121 then [Direction = “ESE”, Sort=6]

else if Round <= 143 then [Direction = “SE”, Sort=7]

else if Round <= 166 then [Direction = “SSE”, Sort=8]

else if Round <= 189 then [Direction = “S”, Sort=9]

else if Round <= 212 then [Direction = “SSW”, Sort=10]

else if Round <= 234 then [Direction = “SW”, Sort=11]

else if Round <= 256 then [Direction = “WSW”, Sort=12]

else if Round <= 279 then [Direction = “W”, Sort=13]

else if Round <= 302 then [Direction = “WNW”, Sort=14]

else if Round <= 325 then [Direction = “NW”, Sort=15]

else if Round >= 348 then [Direction = “NNW”, Sort=16]

else [Direction=“UNK”, Sort=-1]

in

DirectionResult