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 vector-based approached described in Gade, K. (2010). A Non-singular Horizontal Position Representation

## Synopsis

- data GreatCircle
- greatCircle :: (NTransform a, Show a) => a -> a -> GreatCircle
- greatCircleE :: NTransform a => a -> a -> Either String GreatCircle
- greatCircleF :: (NTransform a, MonadFail m) => a -> a -> m GreatCircle
- greatCircleBearing :: NTransform a => a -> Angle -> GreatCircle
- 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
- intersections :: NTransform a => GreatCircle -> GreatCircle -> Maybe (a, a)
- insideSurface :: (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 non-antipodal 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 `greatCircle`

, `greatCircleE`

, `greatCircleF`

or `greatCircleBearing`

constructors.

## 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 # |

# Smart constructors

greatCircle :: (NTransform a, Show a) => a -> a -> GreatCircle Source #

`GreatCircle`

passing by both given positions. `error`

s if given positions are
equal or antipodal.

greatCircleE :: NTransform a => a -> a -> Either String GreatCircle Source #

`GreatCircle`

passing by both given positions. A `Left`

indicates that given positions are
equal or antipodal.

greatCircleF :: (NTransform a, MonadFail m) => a -> a -> m GreatCircle Source #

`GreatCircle`

passing by both given positions. `fail`

s if given positions are
equal or antipodal.

greatCircleBearing :: NTransform a => a -> Angle -> GreatCircle Source #

`GreatCircle`

passing by the given position and heading on given bearing.

# Calculations

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`

computes the signed distance 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 == (- crossTrackDistance p gc2)

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`

.

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 #

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.

insideSurface :: (Eq a, NTransform a) => a -> [a] -> Bool Source #

`insideSurface 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 non-zero.

Always returns `False`

if `ps`

does not at least defines a triangle.

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.