{-# LANGUAGE TypeOperators, TypeFamilies, FlexibleContexts #-}
module Geodetics.Path where
import Control.Monad
import Geodetics.Ellipsoids
import Geodetics.Geodetic
type PathValidity = (Double, Double)
data Path e = Path {
forall e. Path e -> Double -> (Geodetic e, Double, Double)
pathFunc :: Double -> (Geodetic e, Double, Double),
forall e. Path e -> PathValidity
pathValidity :: PathValidity
}
alwaysValid :: PathValidity
alwaysValid :: PathValidity
alwaysValid = (Double -> Double
forall a. Num a => a -> a
negate Double
inf, Double
inf) where
inf :: Double
inf = Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0
pathValidAt :: Path e -> Double -> Bool
pathValidAt :: forall e. Path e -> Double -> Bool
pathValidAt Path e
path Double
d = Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
x1 Bool -> Bool -> Bool
&& Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
x2
where (Double
x1,Double
x2) = Path e -> PathValidity
forall e. Path e -> PathValidity
pathValidity Path e
path
bisect ::
Path e
-> (Geodetic e -> Ordering)
-> Double
-> Double -> Double
-> Maybe Double
bisect :: forall e.
Path e
-> (Geodetic e -> Ordering)
-> Double
-> Double
-> Double
-> Maybe Double
bisect Path e
path Geodetic e -> Ordering
f Double
t Double
b1 Double
b2 = do
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ Path e -> Double -> Bool
forall e. Path e -> Double -> Bool
pathValidAt Path e
path Double
b1
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ Path e -> Double -> Bool
forall e. Path e -> Double -> Bool
pathValidAt Path e
path Double
b2
let r :: ((Double, Ordering), (Double, Ordering))
r = Double -> Double -> ((Double, Ordering), (Double, Ordering))
pairResults Double
b1 Double
b2
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ ((Double, Ordering), (Double, Ordering)) -> Bool
forall {a} {a}. ((a, Ordering), (a, Ordering)) -> Bool
hasRoot ((Double, Ordering), (Double, Ordering))
r
((Double, Ordering), (Double, Ordering)) -> Maybe Double
bisect1 (((Double, Ordering), (Double, Ordering)) -> Maybe Double)
-> ((Double, Ordering), (Double, Ordering)) -> Maybe Double
forall a b. (a -> b) -> a -> b
$ ((Double, Ordering), (Double, Ordering))
-> ((Double, Ordering), (Double, Ordering))
forall {a} {a}. Ord a => ((a, a), (a, a)) -> ((a, a), (a, a))
sortPair ((Double, Ordering), (Double, Ordering))
r
where
f' :: Double -> Ordering
f' Double
d = let (Geodetic e
p, Double
_, Double
_) = Path e -> Double -> (Geodetic e, Double, Double)
forall e. Path e -> Double -> (Geodetic e, Double, Double)
pathFunc Path e
path Double
d in Geodetic e -> Ordering
f Geodetic e
p
pairResults :: Double -> Double -> ((Double, Ordering), (Double, Ordering))
pairResults Double
d1 Double
d2 = ((Double
d1, Double -> Ordering
f' Double
d1), (Double
d2, Double -> Ordering
f' Double
d2))
hasRoot :: ((a, Ordering), (a, Ordering)) -> Bool
hasRoot ((a, Ordering)
v1, (a, Ordering)
v2) = (a, Ordering) -> Ordering
forall a b. (a, b) -> b
snd (a, Ordering)
v1 Ordering -> Ordering -> Bool
forall a. Ord a => a -> a -> Bool
<= Ordering
EQ Bool -> Bool -> Bool
&& Ordering
EQ Ordering -> Ordering -> Bool
forall a. Ord a => a -> a -> Bool
<= (a, Ordering) -> Ordering
forall a b. (a, b) -> b
snd (a, Ordering)
v2
sortPair :: ((a, a), (a, a)) -> ((a, a), (a, a))
sortPair ((a, a)
v1, (a, a)
v2) = if (a, a) -> a
forall a b. (a, b) -> b
snd (a, a)
v1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= (a, a) -> a
forall a b. (a, b) -> b
snd (a, a)
v2 then ((a, a)
v1, (a, a)
v2) else ((a, a)
v2, (a, a)
v1)
bisect1 :: ((Double, Ordering), (Double, Ordering)) -> Maybe Double
bisect1 ((Double
d1, Ordering
r1), (Double
d2, Ordering
r2)) =
let d3 :: Double
d3 = (Double
d1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d2) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
r3 :: Ordering
r3 = Double -> Ordering
f' Double
d3
c1 :: ((Double, Ordering), (Double, Ordering))
c1 = ((Double
d1, Ordering
r1), (Double
d3, Ordering
r3))
c2 :: ((Double, Ordering), (Double, Ordering))
c2 = ((Double
d3, Ordering
r3), (Double
d2, Ordering
r2))
in if Double -> Double
forall a. Num a => a -> a
abs (Double
d1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
d2) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
t
then Double -> Maybe Double
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return Double
d3
else ((Double, Ordering), (Double, Ordering)) -> Maybe Double
bisect1 (((Double, Ordering), (Double, Ordering)) -> Maybe Double)
-> ((Double, Ordering), (Double, Ordering)) -> Maybe Double
forall a b. (a -> b) -> a -> b
$ if ((Double, Ordering), (Double, Ordering)) -> Bool
forall {a} {a}. ((a, Ordering), (a, Ordering)) -> Bool
hasRoot ((Double, Ordering), (Double, Ordering))
c1 then ((Double, Ordering), (Double, Ordering))
c1 else ((Double, Ordering), (Double, Ordering))
c2
intersect :: (Ellipsoid e) =>
Double -> Double
-> Double
-> Int
-> Path e -> Path e
-> Maybe (Double, Double)
intersect :: forall e.
Ellipsoid e =>
Double
-> Double
-> Double
-> Int
-> Path e
-> Path e
-> Maybe PathValidity
intersect Double
d1 Double
d2 Double
accuracy Int
n Path e
path1 Path e
path2
| Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Path e -> Double -> Bool
forall e. Path e -> Double -> Bool
pathValidAt Path e
path1 Double
d1 = Maybe PathValidity
forall a. Maybe a
Nothing
| Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Path e -> Double -> Bool
forall e. Path e -> Double -> Bool
pathValidAt Path e
path2 Double
d2 = Maybe PathValidity
forall a. Maybe a
Nothing
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Maybe PathValidity
forall a. Maybe a
Nothing
| Double
mag Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1e-15 = Maybe PathValidity
forall a. Maybe a
Nothing
| (Double, Double, Double) -> Double
forall {a}. Floating a => (a, a, a) -> a
mag3 ((Double, Double, Double)
nv1 (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double)
forall a. Num a => Vec3 a -> Vec3 a -> Vec3 a
`cross3` (Double, Double, Double)
nv2) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
accuracy = PathValidity -> Maybe PathValidity
forall a. a -> Maybe a
Just (Double
d1, Double
d2)
| Bool
otherwise =
if Double -> Double
forall a. Num a => a -> a
abs Double
d1a Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Num a => a -> a
abs Double
d2a Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Num a => a -> a
abs Double
d1b Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Num a => a -> a
abs Double
d2b
then Double
-> Double
-> Double
-> Int
-> Path e
-> Path e
-> Maybe PathValidity
forall e.
Ellipsoid e =>
Double
-> Double
-> Double
-> Int
-> Path e
-> Path e
-> Maybe PathValidity
intersect (Double
d1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d1a) (Double
d2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d2a) Double
accuracy (Int -> Int
forall a. Enum a => a -> a
pred Int
n) Path e
path1 Path e
path2
else Double
-> Double
-> Double
-> Int
-> Path e
-> Path e
-> Maybe PathValidity
forall e.
Ellipsoid e =>
Double
-> Double
-> Double
-> Int
-> Path e
-> Path e
-> Maybe PathValidity
intersect (Double
d1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d1b) (Double
d2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d2b) Double
accuracy (Int -> Int
forall a. Enum a => a -> a
pred Int
n) Path e
path1 Path e
path2
where
(Geodetic e
pt1, Double
h1, Double
_) = Path e -> Double -> (Geodetic e, Double, Double)
forall e. Path e -> Double -> (Geodetic e, Double, Double)
pathFunc Path e
path1 Double
d1
(Geodetic e
pt2, Double
h2, Double
_) = Path e -> Double -> (Geodetic e, Double, Double)
forall e. Path e -> Double -> (Geodetic e, Double, Double)
pathFunc Path e
path2 Double
d2
vectors :: Double -> Double -> Double
-> (Vec3 Double, Vec3 Double)
vectors :: Double
-> Double
-> Double
-> ((Double, Double, Double), (Double, Double, Double))
vectors Double
lat Double
lon Double
b = (
(Double
cosLatDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cosLon, Double
cosLatDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinLon, Double
sinLat),
(Double
sinLon Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
cosB Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
sinLat Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
cosLon Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sinB,
Double -> Double
forall a. Num a => a -> a
negate Double
cosLon Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
cosB Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
sinLat Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sinLon Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sinB,
Double
cosLat Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sinB))
where
sinLon :: Double
sinLon = Double -> Double
forall a. Floating a => a -> a
sin Double
lon
sinLat :: Double
sinLat = Double -> Double
forall a. Floating a => a -> a
sin Double
lat
cosLon :: Double
cosLon = Double -> Double
forall a. Floating a => a -> a
cos Double
lon
cosLat :: Double
cosLat = Double -> Double
forall a. Floating a => a -> a
cos Double
lat
sinB :: Double
sinB = Double -> Double
forall a. Floating a => a -> a
sin Double
b
cosB :: Double
cosB = Double -> Double
forall a. Floating a => a -> a
cos Double
b
mag3 :: (a, a, a) -> a
mag3 (a
x,a
y,a
z) = a -> a
forall a. Floating a => a -> a
sqrt (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
xa -> a -> a
forall a. Num a => a -> a -> a
*a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
ya -> a -> a
forall a. Num a => a -> a -> a
*a
y a -> a -> a
forall a. Num a => a -> a -> a
+ a
za -> a -> a
forall a. Num a => a -> a -> a
*a
z
((Double, Double, Double)
nv1, (Double, Double, Double)
gc1) = Double
-> Double
-> Double
-> ((Double, Double, Double), (Double, Double, Double))
vectors (Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt1) (Geodetic e -> Double
forall e. Geodetic e -> Double
longitude Geodetic e
pt1) Double
h1
((Double, Double, Double)
nv2, (Double, Double, Double)
gc2) = Double
-> Double
-> Double
-> ((Double, Double, Double), (Double, Double, Double))
vectors (Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt2) (Geodetic e -> Double
forall e. Geodetic e -> Double
longitude Geodetic e
pt2) Double
h2
nv3 :: (Double, Double, Double)
nv3 = (Double, Double, Double)
gc1 (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double)
forall a. Num a => Vec3 a -> Vec3 a -> Vec3 a
`cross3` (Double, Double, Double)
gc2
mag :: Double
mag = (Double, Double, Double) -> Double
forall {a}. Floating a => (a, a, a) -> a
mag3 (Double, Double, Double)
nv3
nv3a :: (Double, Double, Double)
nv3a = (Double, Double, Double) -> Double -> (Double, Double, Double)
forall a. Num a => Vec3 a -> a -> Vec3 a
scale3 (Double, Double, Double)
nv3 (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
mag)
nv3b :: (Double, Double, Double)
nv3b = (Double, Double, Double) -> (Double, Double, Double)
forall a. Num a => Vec3 a -> Vec3 a
negate3 (Double, Double, Double)
nv3a
d1a :: Double
d1a = (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double) -> Double
forall {b}. RealFloat b => Vec3 b -> Vec3 b -> Vec3 b -> b
gcDist (Double, Double, Double)
gc1 (Double, Double, Double)
nv1 (Double, Double, Double)
nv3a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r
d2a :: Double
d2a = (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double) -> Double
forall {b}. RealFloat b => Vec3 b -> Vec3 b -> Vec3 b -> b
gcDist (Double, Double, Double)
gc2 (Double, Double, Double)
nv2 (Double, Double, Double)
nv3a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r
d1b :: Double
d1b = (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double) -> Double
forall {b}. RealFloat b => Vec3 b -> Vec3 b -> Vec3 b -> b
gcDist (Double, Double, Double)
gc1 (Double, Double, Double)
nv1 (Double, Double, Double)
nv3b Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r
d2b :: Double
d2b = (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double) -> Double
forall {b}. RealFloat b => Vec3 b -> Vec3 b -> Vec3 b -> b
gcDist (Double, Double, Double)
gc2 (Double, Double, Double)
nv2 (Double, Double, Double)
nv3b Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r
gcDist :: Vec3 b -> Vec3 b -> Vec3 b -> b
gcDist Vec3 b
norm Vec3 b
v1 Vec3 b
v2 =
let c :: Vec3 b
c = Vec3 b
v1 Vec3 b -> Vec3 b -> Vec3 b
forall a. Num a => Vec3 a -> Vec3 a -> Vec3 a
`cross3` Vec3 b
v2
in (if Vec3 b
c Vec3 b -> Vec3 b -> b
forall a. Num a => Vec3 a -> Vec3 a -> a
`dot3` Vec3 b
norm b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< b
0 then b -> b
forall a. Num a => a -> a
negate else b -> b
forall a. a -> a
id) (b -> b) -> b -> b
forall a b. (a -> b) -> a -> b
$ b -> b -> b
forall a. RealFloat a => a -> a -> a
atan2 (Vec3 b -> b
forall {a}. Floating a => (a, a, a) -> a
mag3 Vec3 b
c) (Vec3 b
v1 Vec3 b -> Vec3 b -> b
forall a. Num a => Vec3 a -> Vec3 a -> a
`dot3` Vec3 b
v2)
r :: Double
r = e -> Double
forall a. Ellipsoid a => a -> Double
majorRadius (e -> Double) -> e -> Double
forall a b. (a -> b) -> a -> b
$ Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt1
rayPath :: (Ellipsoid e) =>
Geodetic e
-> Double
-> Double
-> Path e
rayPath :: forall e. Ellipsoid e => Geodetic e -> Double -> Double -> Path e
rayPath Geodetic e
pt1 Double
bearing Double
elevation = (Double -> (Geodetic e, Double, Double)) -> PathValidity -> Path e
forall e.
(Double -> (Geodetic e, Double, Double)) -> PathValidity -> Path e
Path Double -> (Geodetic e, Double, Double)
ray PathValidity
alwaysValid
where
ray :: Double -> (Geodetic e, Double, Double)
ray Double
distance = (Double -> Double -> Double -> e -> Geodetic e
forall e. Double -> Double -> Double -> e -> Geodetic e
Geodetic Double
lat Double
long Double
alt (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt1), Double
bearing2, Double
elevation2)
where
pt2' :: (Double, Double, Double)
pt2' = (Double, Double, Double)
pt1' (Double, Double, Double)
-> (Double, Double, Double) -> (Double, Double, Double)
forall a. Num a => Vec3 a -> Vec3 a -> Vec3 a
`add3` ((Double, Double, Double)
delta (Double, Double, Double) -> Double -> (Double, Double, Double)
forall a. Num a => Vec3 a -> a -> Vec3 a
`scale3` Double
distance)
(Double
lat,Double
long,Double
alt) = e -> (Double, Double, Double) -> (Double, Double, Double)
forall e.
Ellipsoid e =>
e -> (Double, Double, Double) -> (Double, Double, Double)
earthToGeo (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt1) (Double, Double, Double)
pt2'
(Double
dE,Double
dN,Double
dU) = Matrix3 Double
-> (Double, Double, Double) -> (Double, Double, Double)
forall a. Num a => Matrix3 a -> Vec3 a -> Vec3 a
transform3 (Matrix3 Double -> Matrix3 Double
forall a. Matrix3 a -> Matrix3 a
trans3 (Matrix3 Double -> Matrix3 Double)
-> Matrix3 Double -> Matrix3 Double
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Matrix3 Double
forall {c} {a}.
(Floating c, Num a) =>
c -> c -> ((c, c, c), (c, c, c), (a, c, c))
ecefMatrix Double
lat Double
long) (Double, Double, Double)
delta
elevation2 :: Double
elevation2 = Double -> Double
forall a. Floating a => a -> a
asin Double
dU
bearing2 :: Double
bearing2 = if Double
dE Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
&& Double
dN Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 then Double
bearing else Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
dE Double
dN
ecefMatrix :: c -> c -> ((c, c, c), (c, c, c), (a, c, c))
ecefMatrix c
lat c
long =
((c -> c
forall a. Num a => a -> a
negate c
sinLong, c -> c
forall a. Num a => a -> a
negate c
cosLongc -> c -> c
forall a. Num a => a -> a -> a
*c
sinLat, c
cosLongc -> c -> c
forall a. Num a => a -> a -> a
*c
cosLat),
( c
cosLong, c -> c
forall a. Num a => a -> a
negate c
sinLongc -> c -> c
forall a. Num a => a -> a -> a
*c
sinLat, c
sinLongc -> c -> c
forall a. Num a => a -> a -> a
*c
cosLat),
( a
0, c
cosLat , c
sinLat))
where
sinLong :: c
sinLong = c -> c
forall a. Floating a => a -> a
sin c
long
cosLong :: c
cosLong = c -> c
forall a. Floating a => a -> a
cos c
long
sinLat :: c
sinLat = c -> c
forall a. Floating a => a -> a
sin c
lat
cosLat :: c
cosLat = c -> c
forall a. Floating a => a -> a
cos c
lat
direction :: (Double, Double, Double)
direction = (Double
sinBDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cosE, Double
cosBDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cosE, Double
sinE)
delta :: (Double, Double, Double)
delta = Matrix3 Double
-> (Double, Double, Double) -> (Double, Double, Double)
forall a. Num a => Matrix3 a -> Vec3 a -> Vec3 a
transform3 (Double -> Double -> Matrix3 Double
forall {c} {a}.
(Floating c, Num a) =>
c -> c -> ((c, c, c), (c, c, c), (a, c, c))
ecefMatrix (Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt1) (Geodetic e -> Double
forall e. Geodetic e -> Double
longitude Geodetic e
pt1)) (Double, Double, Double)
direction
pt1' :: (Double, Double, Double)
pt1' = Geodetic e -> (Double, Double, Double)
forall e. Ellipsoid e => Geodetic e -> (Double, Double, Double)
geoToEarth Geodetic e
pt1
sinB :: Double
sinB = Double -> Double
forall a. Floating a => a -> a
sin Double
bearing
cosB :: Double
cosB = Double -> Double
forall a. Floating a => a -> a
cos Double
bearing
sinE :: Double
sinE = Double -> Double
forall a. Floating a => a -> a
sin Double
elevation
cosE :: Double
cosE = Double -> Double
forall a. Floating a => a -> a
cos Double
elevation
rhumbPath :: (Ellipsoid e) =>
Geodetic e
-> Double
-> Path e
rhumbPath :: forall e. Ellipsoid e => Geodetic e -> Double -> Path e
rhumbPath Geodetic e
pt Double
course = (Double -> (Geodetic e, Double, Double)) -> PathValidity -> Path e
forall e.
(Double -> (Geodetic e, Double, Double)) -> PathValidity -> Path e
Path Double -> (Geodetic e, Double, Double)
rhumb PathValidity
validity
where
rhumb :: Double -> (Geodetic e, Double, Double)
rhumb Double
distance = (Double -> Double -> Double -> e -> Geodetic e
forall e. Double -> Double -> Double -> e -> Geodetic e
Geodetic Double
lat (Double -> Double
properAngle Double
lon) Double
0 (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt), Double
course, Double
0)
where
lat' :: Double
lat' = Double
lat0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
distance Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
cosC Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
m0
lat :: Double
lat = Double
lat0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
m0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
e2))) Double -> Double -> Double
forall a. Num a => a -> a -> a
* ((Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e2Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4)Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
lat'Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
lat0)
Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e2Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
8)Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double -> Double
forall a. Floating a => a -> a
sin (Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
lat') Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
sin (Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
lat0)))
lon :: Double
lon | Double -> Double
forall a. Num a => a -> a
abs Double
cosC Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
1e-7
= Double
lon0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
tanC Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double -> Double
q Double
lat Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
q0)
| Bool
otherwise
= Double
lon0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
distance Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sinC Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ e -> Double -> Double
forall e. Ellipsoid e => e -> Double -> Double
latitudeRadius (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt) ((Double
lat0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
lat')Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)
validity :: PathValidity
validity
| Double
cosC Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 = ((Double -> Double
forall a. Num a => a -> a
negate Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
b Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
cosC, (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
b Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
cosC)
| Bool
otherwise = ((Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
b Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
cosC, (Double -> Double
forall a. Num a => a -> a
negate Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
b Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
cosC)
q0 :: Double
q0 = Double -> Double
q Double
lat0
q :: Double -> Double
q Double
phi = Double -> Double
forall a. Floating a => a -> a
log (Double -> Double
forall a. Floating a => a -> a
tan (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
phiDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
e Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
log ((Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
eSinPhi)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
eSinPhi)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
where
eSinPhi :: Double
eSinPhi = Double
e Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
phi
sinC :: Double
sinC = Double -> Double
forall a. Floating a => a -> a
sin Double
course
cosC :: Double
cosC = Double -> Double
forall a. Floating a => a -> a
cos Double
course
tanC :: Double
tanC = Double -> Double
forall a. Floating a => a -> a
tan Double
course
lat0 :: Double
lat0 = Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt
lon0 :: Double
lon0 = Geodetic e -> Double
forall e. Geodetic e -> Double
longitude Geodetic e
pt
e2 :: Double
e2 = e -> Double
forall a. Ellipsoid a => a -> Double
eccentricity2 (e -> Double) -> e -> Double
forall a b. (a -> b) -> a -> b
$ Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt
e :: Double
e = Double -> Double
forall a. Floating a => a -> a
sqrt Double
e2
m0 :: Double
m0 = e -> Double -> Double
forall e. Ellipsoid e => e -> Double -> Double
meridianRadius (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt) Double
lat0
a :: Double
a = e -> Double
forall a. Ellipsoid a => a -> Double
majorRadius (e -> Double) -> e -> Double
forall a b. (a -> b) -> a -> b
$ Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt
b :: Double
b = e -> Double
forall a. Ellipsoid a => a -> Double
minorRadius (e -> Double) -> e -> Double
forall a b. (a -> b) -> a -> b
$ Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt
latitudePath :: (Ellipsoid e) =>
Geodetic e
-> Path e
latitudePath :: forall e. Ellipsoid e => Geodetic e -> Path e
latitudePath Geodetic e
pt = (Double -> (Geodetic e, Double, Double)) -> PathValidity -> Path e
forall e.
(Double -> (Geodetic e, Double, Double)) -> PathValidity -> Path e
Path Double -> (Geodetic e, Double, Double)
line PathValidity
alwaysValid
where
line :: Double -> (Geodetic e, Double, Double)
line Double
distance = (Geodetic e
pt2, Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2, Double
0)
where
pt2 :: Geodetic e
pt2 = Double -> Double -> Double -> e -> Geodetic e
forall e. Double -> Double -> Double -> e -> Geodetic e
Geodetic
(Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt) (Geodetic e -> Double
forall e. Geodetic e -> Double
longitude Geodetic e
pt Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
distance Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
r)
Double
0 (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt)
r :: Double
r = e -> Double -> Double
forall e. Ellipsoid e => e -> Double -> Double
latitudeRadius (Geodetic e -> e
forall e. Geodetic e -> e
ellipsoid Geodetic e
pt) (Geodetic e -> Double
forall e. Geodetic e -> Double
latitude Geodetic e
pt)
longitudePath :: (Ellipsoid e) =>
Geodetic e
-> Path e
longitudePath :: forall e. Ellipsoid e => Geodetic e -> Path e
longitudePath Geodetic e
pt = Geodetic e -> Double -> Path e
forall e. Ellipsoid e => Geodetic e -> Double -> Path e
rhumbPath Geodetic e
pt Double
0