jord-2.0.0.0: Geographical Position Calculations

Copyright(c) 2020 Cedric Liegeois
LicenseBSD3
MaintainerCedric Liegeois <ofmooseandmen@yahoo.fr>
Stabilityexperimental
Portabilityportable
Safe HaskellSafe
LanguageHaskell2010

Data.Geo.Jord.Geodesic

Contents

Description

Solutions to the direct and inverse geodesic problems on ellipsoidal models using Vincenty formulaes. A geodesic is the shortest path between two points on a curved surface - here an ellispoid. Using these functions improves on the accuracy available using Data.Geo.Jord.GreatCircle at the expense of higher CPU usage.

In order to use this module you should start with the following imports:

import qualified Data.Geo.Jord.Angle as Angle
import Data.Geo.Jord.Geodesic (Geodesic)
import qualified Data.Geo.Jord.Geodesic as Geodesic
import qualified Data.Geo.Jord.Geodetic as Geodetic
import qualified Data.Geo.Jord.Length as Length

T Vincenty, "Direct and Inverse Solutions of Geodesics on the Ellipsoid with application of nested equations", Survey Review, vol XXIII no 176, 1975.

Synopsis

The Geodesic type

data Geodesic a Source #

Geodesic line: shortest route between two positions on the surface of a model.

Bearing are in compass angles. Compass angles are clockwise angles from true north: 0° = north, 90° = east, 180° = south, 270° = west. The final bearing will differ from the initial bearing by varying degrees according to distance and latitude.

Instances
Model a => Eq (Geodesic a) Source # 
Instance details

Defined in Data.Geo.Jord.Geodesic

Methods

(==) :: Geodesic a -> Geodesic a -> Bool #

(/=) :: Geodesic a -> Geodesic a -> Bool #

Model a => Show (Geodesic a) Source # 
Instance details

Defined in Data.Geo.Jord.Geodesic

Methods

showsPrec :: Int -> Geodesic a -> ShowS #

show :: Geodesic a -> String #

showList :: [Geodesic a] -> ShowS #

startPosition :: Geodesic a -> HorizontalPosition a Source #

geodesic start position.

endPosition :: Geodesic a -> HorizontalPosition a Source #

geodesic end position.

initialBearing :: Geodesic a -> Maybe Angle Source #

initial bearing from startPosition to endPosition, if both are different.

finalBearing :: Geodesic a -> Maybe Angle Source #

final bearing from startPosition to endPosition, if both are different.

length :: Geodesic a -> Length Source #

length of the geodesic: the surface distance between startPosition to endPosition.

Calculations

direct :: Ellipsoidal a => HorizontalPosition a -> Angle -> Length -> Maybe (Geodesic a) Source #

direct p1 b1 d solves the direct geodesic problem using Vicenty formula: position along the geodesic, reached from position p1 having travelled the surface distance d on the initial bearing (compass angle) b1 at constant height; it also returns the final bearing at the reached position. For example:

>>> Geodesic.direct (Geodetic.northPole WGS84) Angle.zero (Length.kilometres 20003.931458623)
Just (Geodesic { startPosition = 90°0'0.000"N,0°0'0.000"E (WGS84)
               , endPosition = 90°0'0.000"S,180°0'0.000"E (WGS84)
               , initialBearing = Just 0°0'0.000"
               , finalBearing = Just 180°0'0.000"
               , length = 20003.931458623km})

The Vincenty formula for the direct problem should always converge, however this function returns Nothing if it would ever fail to do so (probably thus indicating a bug in the implementation).

inverse :: Ellipsoidal a => HorizontalPosition a -> HorizontalPosition a -> Maybe (Geodesic a) Source #

inverse p1 p2 solves the inverse geodesic problem using Vicenty formula: surface distance, and initial/final bearing between the geodesic line between positions p1 and p2. For example:

>>> Geodesic.inverse (Geodetic.latLongPos 0 0 WGS84) (Geodetic.latLongPos 0.5 179.5 WGS84)
Just (Geodesic { startPosition = 0°0'0.000"N,0°0'0.000"E 0.0m (WGS84)
               , endPosition = 0°30'0.000"N,179°30'0.000"E 0.0m (WGS84)
               , initialBearing = Just 25°40'18.742"
               , finalBearing = Just 154°19'37.507"
               , length = 19936.288578981km})

The Vincenty formula for the inverse problem can fail to converge for nearly antipodal points in which case this function returns Nothing. For example:

>>> Geodesic.inverse (Geodetic.latLongPos 0 0 WGS84) (Geodetic.latLongPos 0.5 179.7 WGS84)
Nothing