Copyright | (c) 2020 Cedric Liegeois |
---|---|
License | BSD3 |
Maintainer | Cedric Liegeois <ofmooseandmen@yahoo.fr> |
Stability | experimental |
Portability | portable |
Safe Haskell | Safe |
Language | Haskell2010 |
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 Data.Geo.Jord.Geodesic import Data.Geo.Jord.Position
If you wish to use both this module and the Data.Geo.Jord.GreatCircle module you must qualify both imports.
Synopsis
- data Geodesic a
- geodesicPos1 :: Geodesic a -> Position a
- geodesicPos2 :: Geodesic a -> Position a
- geodesicBearing1 :: Geodesic a -> Maybe Angle
- geodesicBearing2 :: Geodesic a -> Maybe Angle
- geodesicLength :: Geodesic a -> Length
- directGeodesic :: Ellipsoidal a => Position a -> Angle -> Length -> Maybe (Geodesic a)
- inverseGeodesic :: Ellipsoidal a => Position a -> Position a -> Maybe (Geodesic a)
- destination :: Ellipsoidal a => Position a -> Angle -> Length -> Maybe (Position a)
- finalBearing :: Ellipsoidal a => Position a -> Position a -> Maybe Angle
- initialBearing :: Ellipsoidal a => Position a -> Position a -> Maybe Angle
- surfaceDistance :: Ellipsoidal a => Position a -> Position a -> Maybe Length
The Geodesic
type
Geodesic line: shortest route between two positions on the surface of a model.
geodesicPos1 :: Geodesic a -> Position a Source #
geodesic start position, p1.
geodesicPos2 :: Geodesic a -> Position a Source #
geodesic end position, p2.
geodesicBearing1 :: Geodesic a -> Maybe Angle Source #
initial bearing from p1 to p2, if p1 and p2 are different.
geodesicBearing2 :: Geodesic a -> Maybe Angle Source #
final bearing from p1 to p2, if p1 and p2 are different
geodesicLength :: Geodesic a -> Length Source #
length of the geodesic: the surface distance between p1 and p2.
Calculations
directGeodesic :: Ellipsoidal a => Position a -> Angle -> Length -> Maybe (Geodesic a) Source #
directGeodesic 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.
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).
Examples
>>>
import Data.Geo.Jord.Geodesic
>>>
import Data.Geo.Jord.Position
>>>
>>>
directGeodesic (northPole WGS84) zero (kilometres 20003.931458623)
Just (Geodesic {geodesicPos1 = 90°0'0.000"N,0°0'0.000"E 0.0m (WGS84) , geodesicPos2 = 90°0'0.000"S,180°0'0.000"E 0.0m (WGS84) , geodesicBearing1 = Just 0°0'0.000" , geodesicBearing2 = Just 180°0'0.000" , geodesicLength = 20003.931458623km})
inverseGeodesic :: Ellipsoidal a => Position a -> Position a -> Maybe (Geodesic a) Source #
inverseGeodesic 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
.
The Vincenty formula for the inverse problem can fail to converge for nearly antipodal points in which
case this function returns Nothing
.
Examples
>>>
import Data.Geo.Jord.Geodesic
>>>
import Data.Geo.Jord.Position
>>>
>>>
inverseGeodesic (latLongPos 0 0 WGS84) (latLongPos 0.5 179.5 WGS84)
Just (Geodesic {geodesicPos1 = 0°0'0.000"N,0°0'0.000"E 0.0m (WGS84) , geodesicPos2 = 0°30'0.000"N,179°30'0.000"E 0.0m (WGS84) , geodesicBearing1 = Just 25°40'18.742" , geodesicBearing2 = Just 154°19'37.507" , geodesicLength = 19936.288578981km})>>>
>>>
inverseGeodesic (latLongPos 0 0 WGS84) (latLongPos 0.5 179.7 WGS84)
Nothing
destination :: Ellipsoidal a => Position a -> Angle -> Length -> Maybe (Position a) Source #
destination p b d
computes the position along the geodesic, reached from
position p
having travelled the surface distance d
on the initial bearing (compass angle) b
at constant height.
Note that the bearing will normally vary before destination is reached.
fmapgeodesicPos2
(directGeodesic
p b d)
Examples
>>>
import Data.Geo.Jord.Geodesic
>>>
import Data.Geo.Jord.Position
>>>
>>>
destination (wgs84Pos 54 154 (metres 15000)) (decimalDegrees 33) (kilometres 1000)
Just 61°10'8.983"N,164°7'52.258"E 15.0km (WGS84)
finalBearing :: Ellipsoidal a => Position a -> Position 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 initial bearing by varying degrees according to distance and latitude.
Returns Nothing
if both positions are equals or if inverseGeodesic
fails to converge.
This is equivalent to:
(inverseGeodesic
p1 p2) >>=geodesicBearing2
Examples
>>>
import Data.Geo.Jord.Geodesic
>>>
import Data.Geo.Jord.Position
>>>
>>>
p1 = latLongPos (-37.95103341666667) 144.42486788888888 WGS84
>>>
p2 = latLongPos (-37.65282113888889) 143.92649552777777 WGS84
>>>
initialBearing p1 p2
Just 307°10'25.070"
initialBearing :: Ellipsoidal a => Position a -> Position 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 positions are equals or if inverseGeodesic
fails to converge.
(inverseGeodesic
p1 p2) >>=geodesicBearing1
Examples
>>>
import Data.Geo.Jord.Geodesic
>>>
import Data.Geo.Jord.Position
>>>
>>>
p1 = latLongPos (-37.95103341666667) 144.42486788888888 WGS84
>>>
p2 = latLongPos (-37.65282113888889) 143.92649552777777 WGS84
>>>
initialBearing p1 p2
Just 306°52'5.373"
surfaceDistance :: Ellipsoidal a => Position a -> Position a -> Maybe Length Source #
surfaceDistance p1 p2
computes the surface distance on the geodesic between the
positions p1
and p2
.
This function relies on inverseGeodesic
and can therefore fail to compute the distance
for nearly antipodal positions.
fmapgeodesicLength
(inverseGeodesic
p1 p2)
Examples
>>>
import Data.Geo.Jord.Geodesic
>>>
import Data.Geo.Jord.Position
>>>
>>>
surfaceDistance (northPole WGS84) (southPole WGS84)
Just 20003.931458623km