-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Terrestrial coordinate systems and geodetic calculations.
--   
--   Precise geographical coordinates (latitude &amp; longitude), with
--   conversion between different reference frames and projections.
--   
--   Certain distinguished reference frames and grids are given distinct
--   types so that coordinates expressed within them cannot be confused
--   with from coordinates in other frames.
@package geodetics
@version 0.0.6

module Geodetics.Altitude

-- | All geographical coordinate systems need the concept of# altitude
--   above a reference point, usually associated with local sea level.
--   
--   Minimum definition: altitude, setAltitude.
class HasAltitude a
altitude :: HasAltitude a => a -> Length Double
setAltitude :: HasAltitude a => Length Double -> a -> a

-- | Set altitude to zero.
groundPosition :: HasAltitude a => a -> a


-- | An Ellipsoid is a reasonable best fit for the surface of the Earth
--   over some defined area. WGS84 is the standard used for the whole of
--   the Earth. Other Ellipsoids are considered a best fit for some
--   specific area.
module Geodetics.Ellipsoids

-- | The 7 parameter Helmert transformation. The monoid instance allows
--   composition.
data Helmert
Helmert :: Length Double -> Dimensionless Double -> Dimensionless Double -> Helmert
[cX, cY, cZ] :: Helmert -> Length Double

-- | Parts per million
[helmertScale] :: Helmert -> Dimensionless Double
[rX, rY, rZ] :: Helmert -> Dimensionless Double

-- | The inverse of a Helmert transformation.
inverseHelmert :: Helmert -> Helmert

-- | Earth-centred, Earth-fixed coordinates as a vector. The origin and
--   axes are not defined: use with caution.
type ECEF = Vec3 (Length Double)

-- | Apply a Helmert transformation to earth-centered coordinates.
applyHelmert :: Helmert -> ECEF -> ECEF

-- | An Ellipsoid is defined by the major radius and the inverse flattening
--   (which define its shape), and its Helmert transform relative to WGS84
--   (which defines its position and orientation).
--   
--   The inclusion of the Helmert parameters relative to WGS84 actually
--   make this a Terrestrial Reference Frame (TRF), but the term
--   <a>Ellipsoid</a> will be used in this library for readability.
--   
--   Minimum definition: <tt>majorRadius</tt>, <tt>flatR</tt> &amp;
--   <tt>helmert</tt>.
--   
--   Laws:
--   
--   <pre>
--   helmertToWGS84 = applyHelmert . helmert
--   helmertFromWGS84 e . helmertToWGS84 e = id
--   </pre>
class (Show a, Eq a) => Ellipsoid a
majorRadius :: Ellipsoid a => a -> Length Double
flatR :: Ellipsoid a => a -> Dimensionless Double
helmert :: Ellipsoid a => a -> Helmert
helmertToWSG84 :: Ellipsoid a => a -> ECEF -> ECEF
helmertFromWSG84 :: Ellipsoid a => a -> ECEF -> ECEF

-- | The WGS84 geoid, major radius 6378137.0 meters, flattening = 1 /
--   298.257223563 as defined in "Technical Manual DMA TM 8358.1 - Datums,
--   Ellipsoids, Grids, and Grid Reference Systems" at the National
--   Geospatial-Intelligence Agency (NGA).
--   
--   The WGS84 has a special place in this library as the standard
--   Ellipsoid against which all others are defined.
data WGS84
WGS84 :: WGS84

-- | Ellipsoids other than WGS84, used within a defined geographical area
--   where they are a better fit to the local geoid. Can also be used for
--   historical ellipsoids.
--   
--   The <tt>Show</tt> instance just returns the name. Creating two
--   different local ellipsoids with the same name is a Bad Thing.
data LocalEllipsoid
LocalEllipsoid :: String -> Length Double -> Dimensionless Double -> Helmert -> LocalEllipsoid
[nameLocal] :: LocalEllipsoid -> String
[majorRadiusLocal] :: LocalEllipsoid -> Length Double
[flatRLocal] :: LocalEllipsoid -> Dimensionless Double
[helmertLocal] :: LocalEllipsoid -> Helmert

-- | Flattening (f) of an ellipsoid.
flattening :: (Ellipsoid e) => e -> Dimensionless Double

-- | The minor radius of an ellipsoid.
minorRadius :: (Ellipsoid e) => e -> Length Double

-- | The eccentricity squared of an ellipsoid.
eccentricity2 :: (Ellipsoid e) => e -> Dimensionless Double

-- | The second eccentricity squared of an ellipsoid.
eccentricity'2 :: (Ellipsoid e) => e -> Dimensionless Double

-- | Distance from the surface at the specified latitude to the axis of the
--   Earth straight down. Also known as the radius of curvature in the
--   prime vertical, and often denoted <tt>N</tt>.
normal :: (Ellipsoid e) => e -> Angle Double -> Length Double

-- | Radius of the circle of latitude: the distance from a point at that
--   latitude to the axis of the Earth.
latitudeRadius :: (Ellipsoid e) => e -> Angle Double -> Length Double

-- | Radius of curvature in the meridian at the specified latitude. Often
--   denoted <tt>M</tt>.
meridianRadius :: (Ellipsoid e) => e -> Angle Double -> Length Double

-- | Radius of curvature of the ellipsoid perpendicular to the meridian at
--   the specified latitude.
primeVerticalRadius :: (Ellipsoid e) => e -> Angle Double -> Length Double

-- | The isometric latitude. The isometric latitude is conventionally
--   denoted by ψ (not to be confused with the geocentric latitude): it is
--   used in the development of the ellipsoidal versions of the normal
--   Mercator projection and the Transverse Mercator projection. The name
--   "isometric" arises from the fact that at any point on the ellipsoid
--   equal increments of ψ and longitude λ give rise to equal distance
--   displacements along the meridians and parallels respectively.
isometricLatitude :: (Ellipsoid e) => e -> Angle Double -> Angle Double

-- | 3d vector as <tt>(X,Y,Z)</tt>.
type Vec3 a = (a, a, a)

-- | 3x3 transform matrix for Vec3.
type Matrix3 a = Vec3 (Vec3 a)

-- | Add two vectors
add3 :: (Num a) => Vec3 (Quantity d a) -> Vec3 (Quantity d a) -> Vec3 (Quantity d a)

-- | Multiply a vector by a scalar.
scale3 :: (Num a) => Vec3 (Quantity d a) -> Quantity d' a -> Vec3 (Quantity (d * d') a)

-- | Negation of a vector.
negate3 :: (Num a) => Vec3 (Quantity d a) -> Vec3 (Quantity d a)

-- | Multiply a matrix by a vector in the Dimensional type system.
transform3 :: (Num a) => Matrix3 (Quantity d a) -> Vec3 (Quantity d' a) -> Vec3 (Quantity (d * d') a)

-- | Inverse of a 3x3 matrix.
invert3 :: (Fractional a) => Matrix3 (Quantity d a) -> Matrix3 (Quantity ((d * d) / (d * d * d)) a)

-- | Transpose of a 3x3 matrix.
trans3 :: Matrix3 a -> Matrix3 a

-- | Dot product of two vectors
dot3 :: (Num a) => Vec3 (Quantity d1 a) -> Vec3 (Quantity d2 a) -> Quantity (d1 * d2) a

-- | Cross product of two vectors
cross3 :: (Num a) => Vec3 (Quantity d1 a) -> Vec3 (Quantity d2 a) -> Vec3 (Quantity (d1 * d2) a)
instance GHC.Classes.Eq Geodetics.Ellipsoids.LocalEllipsoid
instance GHC.Show.Show Geodetics.Ellipsoids.Helmert
instance GHC.Classes.Eq Geodetics.Ellipsoids.Helmert
instance GHC.Show.Show Geodetics.Ellipsoids.LocalEllipsoid
instance Geodetics.Ellipsoids.Ellipsoid Geodetics.Ellipsoids.LocalEllipsoid
instance GHC.Classes.Eq Geodetics.Ellipsoids.WGS84
instance GHC.Show.Show Geodetics.Ellipsoids.WGS84
instance Geodetics.Ellipsoids.Ellipsoid Geodetics.Ellipsoids.WGS84
instance GHC.Base.Semigroup Geodetics.Ellipsoids.Helmert
instance GHC.Base.Monoid Geodetics.Ellipsoids.Helmert


-- | The default reader for Geodetic ground positions is flexible but slow.
--   If you are going to read positions in a known format and performance
--   matters then use one of the more specialised parsers here.
module Geodetics.LatLongParser

-- | Parse an unsigned angle written using degrees, minutes and seconds
--   separated by spaces. All except the last must be integers.
degreesMinutesSeconds :: ReadP Double

-- | Parse an unsigned angle written using degrees, minutes and seconds
--   with units (° ' "). At least one component must be specified.
degreesMinutesSecondsUnits :: ReadP Double

-- | Parse an unsigned angle written using degrees and decimal minutes.
degreesDecimalMinutes :: ReadP Double

-- | Parse an unsigned angle written using degrees and decimal minutes with
--   units (° ')
degreesDecimalMinutesUnits :: ReadP Double

-- | Parse an unsigned angle written in DDDMMSS.ss format. Leading zeros on
--   the degrees and decimal places on the seconds are optional
dms7 :: ReadP Double

-- | Parse an unsigned angle, either in decimal degrees or in degrees,
--   minutes and seconds. In the latter case the unit indicators are
--   optional.
angle :: ReadP Double

-- | Parse latitude as an unsigned angle followed by <tt>N</tt> or
--   <tt>S</tt>
latitudeNS :: ReadP Double

-- | Parse longitude as an unsigned angle followed by <tt>E</tt> or
--   <tt>W</tt>.
longitudeEW :: ReadP Double

-- | Parse latitude and longitude as two signed decimal numbers in that
--   order, optionally separated by a comma. Longitudes in the western
--   hemisphere may be represented either by negative angles down to -180
--   or by positive angles less than 360.
signedLatLong :: ReadP (Double, Double)

-- | Parse latitude and longitude in any format.
latLong :: ReadP (Double, Double)

module Geodetics.Geodetic

-- | Defines a three-D position on or around the Earth using latitude,
--   longitude and altitude with respect to a specified ellipsoid, with
--   positive directions being North and East. The default "show" instance
--   gives position in degrees, minutes and seconds to 5 decimal places,
--   which is a resolution of about 1m on the Earth's surface. Internally
--   latitude and longitude are stored as double precision radians. Convert
--   to degrees using e.g. <tt>latitude g /~ degree</tt>.
--   
--   The functions here deal with altitude by assuming that the local
--   height datum is always co-incident with the ellipsoid in use, even
--   though the "mean sea level" (the usual height datum) can be tens of
--   meters above or below the ellipsoid, and two ellipsoids can differ by
--   similar amounts. This is because the altitude is usually known with
--   reference to a local datum regardless of the ellipsoid in use, so it
--   is simpler to preserve the altitude across all operations. However if
--   you are working with ECEF coordinates from some other source then this
--   may give you the wrong results, depending on the altitude correction
--   your source has used.
--   
--   There is no <a>Eq</a> instance because comparing two arbitrary
--   co-ordinates on the Earth is a non-trivial exercise. Clearly if all
--   the parameters are equal on the same ellipsoid then they are indeed in
--   the same place. However if different ellipsoids are used then two
--   co-ordinates with different numbers can still refer to the same
--   physical location. If you want to find out if two co-ordinates are the
--   same to within a given tolerance then use "geometricDistance" (or its
--   squared variant to avoid an extra <tt>sqrt</tt> operation).
data (Ellipsoid e) => Geodetic e
Geodetic :: Angle Double -> Length Double -> e -> Geodetic e
[latitude, longitude] :: Geodetic e -> Angle Double
[geoAlt] :: Geodetic e -> Length Double
[ellipsoid] :: Geodetic e -> e

-- | Read the latitude and longitude of a ground position and return a
--   Geodetic position on the specified ellipsoid.
--   
--   The latitude and longitude may be in any of the following formats. The
--   comma between latitude and longitude is optional in all cases.
--   Latitude must always be first.
--   
--   <ul>
--   <li>Signed decimal degrees: 34.52327, -46.23234</li>
--   <li>Decimal degrees NSEW: 34.52327N, 46.23234W</li>
--   <li>Degrees and decimal minutes (units optional): 34° 31.43' N, 46°
--   13.92'</li>
--   <li>Degrees, minutes and seconds (units optional): 34° 31' 23.52" N,
--   46° 13' 56.43" W</li>
--   <li>DDDMMSS format with optional leading zeros: 343123.52N,
--   0461356.43W</li>
--   </ul>
readGroundPosition :: (Ellipsoid e) => e -> String -> Maybe (Geodetic e)

-- | Convert a position from any geodetic to another one, assuming local
--   altitude stays constant.
toLocal :: (Ellipsoid e1, Ellipsoid e2) => e2 -> Geodetic e1 -> Geodetic e2

-- | Convert a position from any geodetic to WGS84, assuming local altitude
--   stays constant.
toWGS84 :: (Ellipsoid e) => Geodetic e -> Geodetic WGS84

-- | The point on the Earth diametrically opposite the argument, with the
--   same altitude.
antipode :: (Ellipsoid e) => Geodetic e -> Geodetic e

-- | The absolute distance in a straight line between two geodetic points.
--   They must be on the same ellipsoid. Note that this is not the geodetic
--   distance taken by following the curvature of the earth.
geometricalDistance :: (Ellipsoid e) => Geodetic e -> Geodetic e -> Length Double

-- | The square of the absolute distance. Comes out as <a>Area</a> type of
--   course.
geometricalDistanceSq :: (Ellipsoid e) => Geodetic e -> Geodetic e -> Area Double

-- | The shortest ellipsoidal distance between two points on the ground
--   with reference to the same ellipsoid. Altitude is ignored.
--   
--   The results are the distance between the points, the bearing of the
--   second point from the first, and (180 degrees - the bearing of the
--   first point from the second).
--   
--   The algorithm can fail to converge where the arguments are near to
--   antipodal. In this case it returns <tt>Nothing</tt>.
--   
--   Uses Vincenty's formula. "Direct and inverse solutions of geodesics on
--   the ellipsoid with application of nested equations". T. Vincenty.
--   Survey Review XXII 176, April 1975.
--   <a>http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf</a>
groundDistance :: (Ellipsoid e) => Geodetic e -> Geodetic e -> Maybe (Length Double, Dimensionless Double, Dimensionless Double)

-- | Add or subtract multiples of 2*pi so that for all <tt>t</tt>, <tt>-pi
--   &lt; properAngle t &lt; pi</tt>.
properAngle :: Angle Double -> Angle Double

-- | Show an angle as degrees, minutes and seconds to two decimal places.
showAngle :: Angle Double -> String

-- | Earth-centred, Earth-fixed coordinates as a vector. The origin and
--   axes are not defined: use with caution.
type ECEF = Vec3 (Length Double)

-- | Convert a geodetic coordinate into earth centered, relative to the
--   ellipsoid in use.
geoToEarth :: (Ellipsoid e) => Geodetic e -> ECEF

-- | Convert an earth centred coordinate into a geodetic coordinate on the
--   specified geoid.
--   
--   Uses the closed form solution of H. Vermeille: Direct transformation
--   from geocentric coordinates to geodetic coordinates. Journal of
--   Geodesy Volume 76, Number 8 (2002), 451-454
earthToGeo :: (Ellipsoid e) => e -> ECEF -> (Angle Double, Angle Double, Length Double)

-- | The WGS84 geoid, major radius 6378137.0 meters, flattening = 1 /
--   298.257223563 as defined in "Technical Manual DMA TM 8358.1 - Datums,
--   Ellipsoids, Grids, and Grid Reference Systems" at the National
--   Geospatial-Intelligence Agency (NGA).
--   
--   The WGS84 has a special place in this library as the standard
--   Ellipsoid against which all others are defined.
data WGS84
WGS84 :: WGS84
instance Geodetics.Ellipsoids.Ellipsoid e => GHC.Show.Show (Geodetics.Geodetic.Geodetic e)
instance Geodetics.Ellipsoids.Ellipsoid e => Geodetics.Altitude.HasAltitude (Geodetics.Geodetic.Geodetic e)

module Geodetics.Grid

-- | A Grid is a two-dimensional projection of the ellipsoid onto a plane.
--   Any given type of grid can usually be instantiated with parameters
--   such as a tangential point or line, and these parameters will include
--   the terrestrial reference frame (<a>Ellipsoid</a> in this library)
--   used as a foundation. Hence conversion from a geodetic to a grid point
--   requires the "basis" for the grid in question, and grid points carry
--   that basis with them because without it there is no defined
--   relationship between the grid points and terrestrial positions.
class GridClass r e | r -> e
fromGrid :: GridClass r e => GridPoint r -> Geodetic e
toGrid :: GridClass r e => r -> Geodetic e -> GridPoint r
gridEllipsoid :: GridClass r e => r -> e

-- | A point on the specified grid.
data GridPoint r
GridPoint :: Length Double -> r -> GridPoint r
[eastings, northings, altGP] :: GridPoint r -> Length Double
[gridBasis] :: GridPoint r -> r

-- | A vector relative to a point on a grid. Operations that use offsets
--   will only give meaningful results if all the points come from the same
--   grid.
--   
--   The monoid instance is the sum of offsets.
data GridOffset
GridOffset :: Length Double -> GridOffset
[deltaEast, deltaNorth, deltaAltitude] :: GridOffset -> Length Double

-- | An offset defined by a distance and a bearing to the right of North.
--   
--   There is no elevation parameter because we are using a plane to
--   approximate an ellipsoid, so elevation would not provide a useful
--   result. If you want to work with elevations then "rayPath" will give
--   meaningful results.
polarOffset :: Length Double -> Angle Double -> GridOffset

-- | Scale an offset by a scalar.
offsetScale :: Dimensionless Double -> GridOffset -> GridOffset

-- | Invert an offset.
offsetNegate :: GridOffset -> GridOffset
applyOffset :: GridOffset -> GridPoint g -> GridPoint g

-- | The distance represented by an offset.
offsetDistance :: GridOffset -> Length Double

-- | The square of the distance represented by an offset.
offsetDistanceSq :: GridOffset -> Area Double

-- | The direction represented by an offset, as bearing to the right of
--   North.
offsetBearing :: GridOffset -> Angle Double

-- | The offset required to move from p1 to p2.
gridOffset :: GridPoint g -> GridPoint g -> GridOffset

-- | Coerce a grid point of one type into a grid point of a different type,
--   but with the same easting, northing and altitude. This is unsafe
--   because it will produce a different position unless the two grids are
--   actually equal.
--   
--   It should be used only to convert between distinguished grids (e.g.
--   <a>UkNationalGrid</a>) and their equivalent numerical definitions.
unsafeGridCoerce :: b -> GridPoint a -> GridPoint b

-- | Convert a list of digits to a distance. The first argument is the size
--   of the grid square within which these digits specify a position. The
--   first digit is in units of one tenth of the grid square, the second
--   one hundredth, and so on. The first result is the lower limit of the
--   result, and the second is the size of the specified offset. So for
--   instance <tt>fromGridDigits (100 *~ kilo meter) "237"</tt> will return
--   
--   <pre>
--   Just (23700 meters, 100 meters)
--   </pre>
--   
--   If there are any non-digits in the string then the function returns
--   <tt>Nothing</tt>.
fromGridDigits :: Length Double -> String -> Maybe (Length Double, Length Double)

-- | Convert a distance into a digit string suitable for printing as part
--   of a grid reference. The result is the nearest position to the
--   specified number of digits, expressed as an integer count of squares
--   and a string of digits. If any arguments are invalid then
--   <tt>Nothing</tt> is returned.
toGridDigits :: Length Double -> Int -> Length Double -> Maybe (Integer, String)
instance GHC.Show.Show Geodetics.Grid.GridOffset
instance GHC.Classes.Eq Geodetics.Grid.GridOffset
instance GHC.Show.Show r => GHC.Show.Show (Geodetics.Grid.GridPoint r)
instance GHC.Base.Semigroup Geodetics.Grid.GridOffset
instance GHC.Base.Monoid Geodetics.Grid.GridOffset
instance GHC.Classes.Eq (Geodetics.Grid.GridPoint r)
instance Geodetics.Altitude.HasAltitude (Geodetics.Grid.GridPoint g)


-- | The implementation assumes IEEE 754 arithmetic.
module Geodetics.Path

-- | Lower and upper exclusive bounds within which a path is valid.
type PathValidity = (Length Double, Length Double)

-- | A path is a parametric function of distance along the path. The result
--   is the position, and the direction of the path at that point as
--   heading and elevation angles.
--   
--   A well-behaved path must be continuous and monotonic (that is, if the
--   distance increases then the result is further along the path) for all
--   distances within its validity range. Ideally the physical distance
--   along the path from the origin to the result should be equal to the
--   argument. If this is not practical then a reasonably close
--   approximation may be used, such as a spheroid instead of an ellipsoid,
--   provided that this is documented. Outside its validity the path
--   function may return anything or bottom.
data Path e
Path :: Length Double -> (Geodetic e, Angle Double, Angle Double) -> PathValidity -> Path e
[pathFunc] :: Path e -> Length Double -> (Geodetic e, Angle Double, Angle Double)
[pathValidity] :: Path e -> PathValidity

-- | Convenience value for paths that are valid for all distances.
alwaysValid :: PathValidity

-- | True if the path is valid at that distance.
pathValidAt :: Path e -> Length Double -> Bool

-- | Find where a path meets a given condition using bisection. This is not
--   the most efficient algorithm, but it will always produce a result if
--   there is one within the initial bounds. If there is more than one
--   result then an arbitrary one will be returned.
--   
--   The initial bounds must return one GT or EQ value and one LT or EQ
--   value. If they do not then <tt>Nothing</tt> is returned.
bisect :: Path e -> (Geodetic e -> Ordering) -> Length Double -> Length Double -> Length Double -> Maybe (Length Double)

-- | Try to find the intersection point of two ground paths (i.e. ignoring
--   altitude). Returns the distance of the intersection point along each
--   path using a modified Newton-Raphson method. If the two paths are
--   fairly straight and not close to parallel then this will converge
--   rapidly.
--   
--   The algorithm projects great-circle paths forwards using the bearing
--   at the estimate to find the estimated intersection, and then uses the
--   distances to this intersection as the next estimates.
--   
--   If either estimate departs from its path validity then
--   <tt>Nothing</tt> is returned.
intersect :: (Ellipsoid e) => Length Double -> Length Double -> Length Double -> Int -> Path e -> Path e -> Maybe (Length Double, Length Double)

-- | A ray from a point heading in a straight line in 3 dimensions.
rayPath :: (Ellipsoid e) => Geodetic e -> Angle Double -> Angle Double -> Path e

-- | Rhumb line: path following a constant course. Also known as a
--   loxodrome.
--   
--   The valid range stops a few arc-minutes short of the poles to ensure
--   that the polar singularities are not included. Anyone using a rhumb
--   line that close to a pole must be going round the twist anyway.
--   
--   Based on *Practical Sailing Formulas for Rhumb-Line Tracks on an
--   Oblate Earth* by G.H. Kaplan, U.S. Naval Observatory. Except for
--   points close to the poles the approximation is accurate to within a
--   few meters over 1000km.
rhumbPath :: (Ellipsoid e) => Geodetic e -> Angle Double -> Path e

-- | A path following the line of latitude around the Earth eastwards.
--   
--   This is equivalent to <tt>rhumbPath pt (pi/2)</tt>
latitudePath :: (Ellipsoid e) => Geodetic e -> Path e

-- | A path from the specified point to the North Pole. Use negative
--   distances for the southward path.
--   
--   This is equivalent to <tt>rhumbPath pt _0</tt>
longitudePath :: (Ellipsoid e) => Geodetic e -> Path e


-- | The following is based on equations in Section 1.4.7.1 in OGP
--   Surveying and Positioning Guidance Note number 7, part 2 – August 2006
--   <a>http://ftp.stu.edu.tw/BSD/NetBSD/pkgsrc/distfiles/epsg-6.11/G7-2.pdf</a>
module Geodetics.Stereographic

-- | A stereographic projection with its origin at an arbitrary point on
--   Earth, other than the poles.
data GridStereo e

-- | Create a stereographic projection. The tangency point must not be one
--   of the poles.
mkGridStereo :: (Ellipsoid e) => Geodetic e -> GridOffset -> Dimensionless Double -> GridStereo e
instance Geodetics.Ellipsoids.Ellipsoid e => GHC.Show.Show (Geodetics.Stereographic.GridStereo e)
instance Geodetics.Ellipsoids.Ellipsoid e => Geodetics.Grid.GridClass (Geodetics.Stereographic.GridStereo e) e

module Geodetics.TransverseMercator

-- | A Transverse Mercator projection gives an approximate mapping of the
--   ellipsoid on to a 2-D grid. It models a sheet curved around the
--   ellipsoid so that it touches it at one north-south line (hence making
--   it part of a slightly elliptical cylinder).
data GridTM e

-- | Create a Transverse Mercator grid.
mkGridTM :: (Ellipsoid e) => Geodetic e -> GridOffset -> Dimensionless Double -> GridTM e
instance Geodetics.Ellipsoids.Ellipsoid e => GHC.Show.Show (Geodetics.TransverseMercator.GridTM e)
instance Geodetics.Ellipsoids.Ellipsoid e => Geodetics.Grid.GridClass (Geodetics.TransverseMercator.GridTM e) e


-- | Distinguished coordinate systems for the United Kingdom.
module Geodetics.UK

-- | Ellipsoid definition for Great Britain. Airy 1830 offset from the
--   centre of the Earth and rotated slightly.
--   
--   The Helmert parameters are from the Ordnance Survey document "A Guide
--   to Coordinate Systems in Great Britain", which notes that it can be in
--   error by as much as 5 meters and should not be used in applications
--   requiring greater accuracy. A more precise conversion requires a large
--   table of corrections for historical inaccuracies in the triangulation
--   of the UK.
data OSGB36
OSGB36 :: OSGB36

-- | The UK National Grid is a Transverse Mercator projection with a true
--   origin at 49 degrees North, 2 degrees West on OSGB36, and a false
--   origin 400km West and 100 km North of the true origin. The scale
--   factor is defined as <tt>10**(0.9998268 - 1)</tt>.
data UkNationalGrid
UkNationalGrid :: UkNationalGrid

-- | Numerical definition of the UK national grid.
ukGrid :: GridTM OSGB36

-- | Convert a grid reference to a position, if the reference is valid.
--   This returns the position of the south-west corner of the nominated
--   grid square and an offset to its centre. Altitude is set to zero.
fromUkGridReference :: String -> Maybe (GridPoint UkNationalGrid, GridOffset)

-- | Find the nearest UK grid reference point to a specified position. The
--   Int argument is the number of digits precision, so 2 for a 4-figure
--   reference and 3 for a 6-figure reference, although any value between 0
--   and 5 can be used (giving a 1 meter precision). Altitude is ignored.
--   If the result is outside the area defined by the two letter grid codes
--   then <tt>Nothing</tt> is returned.
toUkGridReference :: Int -> GridPoint UkNationalGrid -> Maybe String
instance GHC.Show.Show Geodetics.UK.UkNationalGrid
instance GHC.Classes.Eq Geodetics.UK.UkNationalGrid
instance GHC.Show.Show Geodetics.UK.OSGB36
instance GHC.Classes.Eq Geodetics.UK.OSGB36
instance Geodetics.Grid.GridClass Geodetics.UK.UkNationalGrid Geodetics.UK.OSGB36
instance Geodetics.Ellipsoids.Ellipsoid Geodetics.UK.OSGB36
