Copyright  (c) 2018 Cedric Liegeois 

License  BSD3 
Maintainer  Cedric Liegeois <ofmooseandmen@yahoo.fr> 
Stability  experimental 
Portability  portable 
Safe Haskell  Safe 
Language  Haskell2010 
Geodetic calculations assuming a spherical earth model.
All functions are implemented using the vectorbased approached described in Gade, K. (2010). A Nonsingular Horizontal Position Representation
Synopsis
 data GreatCircle
 class IsGreatCircle a where
 gcPos :: GreatCircle > NVector
 gcBearing :: GreatCircle > Angle
 data GreatArc
 class IsGreatArc a where
 gaStart :: GreatArc > NVector
 gaEnd :: GreatArc > NVector
 alongTrackDistance :: NTransform a => a > GreatArc > Length > Length
 alongTrackDistance84 :: NTransform a => a > GreatArc > Length
 angularDistance :: NTransform a => a > a > Maybe a > Angle
 antipode :: NTransform a => a > a
 crossTrackDistance :: NTransform a => a > GreatCircle > Length > Length
 crossTrackDistance84 :: NTransform a => a > GreatCircle > Length
 destination :: NTransform a => a > Angle > Length > Length > a
 destination84 :: NTransform a => a > Angle > Length > a
 finalBearing :: (Eq a, NTransform a) => a > a > Maybe Angle
 initialBearing :: (Eq a, NTransform a) => a > a > Maybe Angle
 interpolate :: NTransform a => a > a > Double > a
 intersection :: NTransform a => GreatArc > GreatArc > Maybe a
 intersections :: NTransform a => GreatCircle > GreatCircle > Maybe (a, a)
 isBetween :: NTransform a => a > GreatArc > Bool
 isInsideSurface :: (Eq a, NTransform a) => a > [a] > Bool
 mean :: NTransform a => [a] > Maybe a
 surfaceDistance :: NTransform a => a > a > Length > Length
 surfaceDistance84 :: NTransform a => a > a > Length
The
GreatCircle
type
data GreatCircle Source #
A circle on the surface of the Earth which lies in a plane passing through the Earth's centre. Every two distinct and nonantipodal points on the surface of the Earth define a Great Circle.
It is internally represented as its normal vector  i.e. the normal vector to the plane containing the great circle.
see IsGreatCircle
.
Instances
Eq GreatCircle Source #  
Defined in Data.Geo.Jord.Geodetics (==) :: GreatCircle > GreatCircle > Bool # (/=) :: GreatCircle > GreatCircle > Bool #  
Show GreatCircle Source #  
Defined in Data.Geo.Jord.Geodetics showsPrec :: Int > GreatCircle > ShowS # show :: GreatCircle > String # showList :: [GreatCircle] > ShowS # 
class IsGreatCircle a where Source #
Class for data from which a GreatCircle
can be computed.
:: a  
> GreatCircle 

:: a  
> Either String GreatCircle 

:: MonadFail m  
=> a  
> m GreatCircle 

Instances
gcPos :: GreatCircle > NVector Source #
position (nvector) on the great circle
The
GreatArc
type
A closed segment of GreatCircle
. It represent the shortest path on the surface of the Earth
between the two positions.
see IsGreatArc
.
Instances
Eq GreatArc Source #  
Show GreatArc Source #  
IsGreatCircle GreatArc Source # 

Defined in Data.Geo.Jord.Geodetics greatCircle :: GreatArc > GreatCircle Source # greatCircleE :: GreatArc > Either String GreatCircle Source # greatCircleF :: MonadFail m => GreatArc > m GreatCircle Source # 
class IsGreatArc a where Source #
Class for data from which a GreatArc
can be computed.
:: a  
> GreatArc 

Instances
NTransform a => IsGreatArc (a, a) Source # 
let p1 = decimalLatLongHeight 45.0 (143.5) (metres 1500) let p2 = decimalLatLongHeight 46.0 14.5 (metres 3000) greatArc (p1, p2)  heights are ignored, great arc are always at earth surface. 
NTransform a => IsGreatArc (Track a, Duration) Source # 

NTransform a => IsGreatArc (Track a, Duration, Length) Source # 

Calculations
alongTrackDistance :: NTransform a => a > GreatArc > Length > Length Source #
alongTrackDistance p ga r
how far position p
is along a path described
by great arc ga
: if a perpendicular is drawn from p
to the great arc, the
alongtrack distance is the signed distance from the start point to where the
perpendicular crosses the path.
let p = decimalLatLong 53.2611 (0.7972) let ga = greatArc (decimalLatLong 53.3206 (1.7297)) (decimalLatLong 53.1887 0.1334) alongTrackDistance p ga r84  62.3315757 kilometres
alongTrackDistance84 :: NTransform a => a > GreatArc > Length Source #
alongTrackDistance
using the mean radius of the WGS84 reference ellipsoid.
angularDistance :: NTransform a => a > a > Maybe a > Angle Source #
angularDistance p1 p2 n
computes the angle between the horizontal positions p1
and p2
.
If n
is Nothing
, the angle is always in [0..180], otherwise it is in [180, +180],
signed + if p1
is clockwise looking along n
,  in opposite direction.
antipode :: NTransform a => a > a Source #
antipode p
computes the antipodal horizontal position of p
:
the horizontal position on the surface of the Earth which is diametrically opposite to p
.
crossTrackDistance :: NTransform a => a > GreatCircle > Length > Length Source #
crossTrackDistance p gc r
computes the signed distance from horizontal position p
to great circle gc
.
Returns a negative Length
if position if left of great circle,
positive Length
if position if right of great circle; the orientation of the
great circle is therefore important:
let gc1 = greatCircle (decimalLatLong 51 0) (decimalLatLong 52 1) let gc2 = greatCircle (decimalLatLong 52 1) (decimalLatLong 51 0) crossTrackDistance p gc1 r84 = ( crossTrackDistance p gc2 r84) let p = decimalLatLong 53.2611 (0.7972) let gc = greatCircleBearing (decimalLatLong 53.3206 (1.7297)) (decimalDegrees 96.0) crossTrackDistance p gc r84  305.663 metres
crossTrackDistance84 :: NTransform a => a > GreatCircle > Length Source #
crossTrackDistance
using the mean radius of the WGS84 reference ellipsoid.
destination :: NTransform a => a > Angle > Length > Length > a Source #
destination p b d r
computes the destination position from position p
having
travelled the distance d
on the initial bearing (compass angle) b
(bearing will normally vary
before destination is reached) and using the earth radius r
.
let p0 = ecefToNVector (ecefMetres 3812864.094 (115142.863) 5121515.161) s84 let p1 = ecefMetres 3826406.4710518294 8900.536398998282 5112694.233184049 let p = destination p0 (decimalDegrees 96.0217) (metres 124800) r84 nvectorToEcef p s84 = p1
destination84 :: NTransform a => a > Angle > Length > a Source #
destination
using the mean radius of the WGS84 reference ellipsoid.
finalBearing :: (Eq a, NTransform a) => a > a > Maybe Angle Source #
finalBearing p1 p2
computes the final bearing arriving at p2
from p1
in compass angle.
Compass angles are clockwise angles from true north: 0 = north, 90 = east, 180 = south, 270 = west.
The final bearing will differ from the initialBearing
by varying degrees according to distance and latitude.
Returns Nothing
if both horizontal positions are equals.
initialBearing :: (Eq a, NTransform a) => a > a > Maybe Angle Source #
initialBearing p1 p2
computes the initial bearing from p1
to p2
in compass angle.
Compass angles are clockwise angles from true north: 0 = north, 90 = east, 180 = south, 270 = west.
Returns Nothing
if both horizontal positions are equals.
interpolate :: NTransform a => a > a > Double > a Source #
interpolate p0 p1 f# computes the horizontal position at fraction
f between the
p0 and
p1@.
Special conditions:
interpolate p0 p1 0.0 = p0 interpolate p0 p1 1.0 = p1
let p1 = latLongHeight (readLatLong "53°28'46''N 2°14'43''W") (metres 10000) let p2 = latLongHeight (readLatLong "55°36'21''N 13°02'09''E") (metres 20000) interpolate p1 p2 0.5 = decimalLatLongHeight 54.7835574 5.1949856 (metres 15000)
intersection :: NTransform a => GreatArc > GreatArc > Maybe a Source #
Computes the intersection between the two given GreatArc
s.
see also intersections
let spd = kilometresPerHour 1000 let t1 = Track (decimalLatLong 51.885 0.235) (decimalDegrees 108.63) spd let t2 = Track (decimalLatLong 49.008 2.549) (decimalDegrees 32.72) spd let oneHour = hours 1 let ga1 = greatArc (t1, oneHour) let ga2 = greatArc (t2, oneHour) intersection ga1 ga2 = Just (decimalLatLong 50.9017225 4.494278333333333)
intersections :: NTransform a => GreatCircle > GreatCircle > Maybe (a, a) Source #
Computes the intersections between the two given GreatCircle
s.
Two GreatCircle
s intersect exactly twice unless there are equal (regardless of orientation),
in which case Nothing
is returned.
let gc1 = greatCircleBearing (decimalLatLong 51.885 0.235) (decimalDegrees 108.63) let gc2 = greatCircleBearing (decimalLatLong 49.008 2.549) (decimalDegrees 32.72) let (i1, i2) = fromJust (intersections gc1 gc2) i1 = decimalLatLong 50.9017226 4.4942782 i2 = antipode i1
isBetween :: NTransform a => a > GreatArc > Bool Source #
isBetween p ga
determines whether position p
is between start and end points
of great arc ga
.
If p
is not on the great arc, returns whether p
is within the area bound
by perpendiculars to the great arc at each point (in the same hemisphere).
isInsideSurface :: (Eq a, NTransform a) => a > [a] > Bool Source #
isInsideSurface p ps
determines whether the p
is inside the polygon defined by the list of positions ps
.
The polygon is closed if needed (i.e. if head ps /= last ps
).
Uses the angle summation test: on a sphere, due to spherical excess, enclosed point angles will sum to less than 360°, and exterior point angles will be small but nonzero.
Always returns False
if ps
does not at least defines a triangle.
let malmo = decimalLatLong 55.6050 13.0038 let ystad = decimalLatLong 55.4295 13.82 let lund = decimalLatLong 55.7047 13.1910 let helsingborg = decimalLatLong 56.0465 12.6945 let kristianstad = decimalLatLong 56.0294 14.1567 let polygon = [malmo, ystad, kristianstad, helsingborg, lund] let hoor = decimalLatLong 55.9295 13.5297 let hassleholm = decimalLatLong 56.1589 13.7668 isInsideSurface hoor polygon = True isInsideSurface hassleholm polygon = False
mean :: NTransform a => [a] > Maybe a Source #
mean ps
computes the mean geographic horitzontal position of ps
, if it is defined.
The geographic mean is not defined for antipodals position (since they cancel each other).
Special conditions:
mean [] = Nothing mean [p] = Just p mean [p1, p2, p3] = Just circumcentre mean [p1, .., antipode p1] = Nothing
surfaceDistance :: NTransform a => a > a > Length > Length Source #
surfaceDistance p1 p2
computes the surface distance (length of geodesic) between the positions p1
and p2
.
surfaceDistance84 :: NTransform a => a > a > Length Source #
surfaceDistance
using the mean radius of the WGS84 reference ellipsoid.