packages feed

jord-2.0.0.0: test/Data/Geo/Jord/LocalSpec.hs

module Data.Geo.Jord.LocalSpec
    ( spec
    ) where

import Test.Hspec

import qualified Data.Geo.Jord.Angle as Angle
import qualified Data.Geo.Jord.Geodetic as Geodetic
import qualified Data.Geo.Jord.Length as Length
import Data.Geo.Jord.Local (Ned(..))
import qualified Data.Geo.Jord.Local as Local
import qualified Data.Geo.Jord.Math3d as Math3d
import Data.Geo.Jord.Models (WGS84(..))

spec :: Spec
spec = do
    describe "Ellipsoidal earth model" $ do
        describe "destination" $ do
            it "return the given position if NED norm = 0" $ do
                let p0 = Geodetic.latLongHeightPos 53.320556 (-1.729722) Length.zero WGS84
                let d = Ned Length.zero Length.zero Length.zero
                Local.destinationN p0 d `shouldBe` p0
            it "computes the destination position from p0 and NED" $ do
                let p0 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
                let d = Local.nedMetres (-86126) (-78900) 1069
                Local.destinationN p0 d `shouldBe`
                    Geodetic.latLongHeightPos
                        48.886668961666665
                        2.3747212533333335
                        (Length.metres 0.198937)
                        WGS84
            it "computes the destination position from p0 and vector in Frame B" $ do
                let p0 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
                let y = Angle.decimalDegrees 10 -- yaw
                let r = Angle.decimalDegrees 20 -- roll
                let p = Angle.decimalDegrees 30 -- pitch
                let d = Local.deltaMetres 3000 2000 100
                Local.destination p0 (Local.frameB y r p) d `shouldBe`
                    Geodetic.latLongHeightPos
                        49.69180157805555
                        3.4812670616666668
                        (Length.metres 6.007735)
                        WGS84
        describe "nedBetween" $ do
            it "computes NED between surface positions" $ do
                let p1 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
                let p2 = Geodetic.latLongHeightPos 48.88667 2.37472 Length.zero WGS84
                let d = Local.nedBetween p1 p2
                d `shouldBe` Local.nedMetres (-86125.880549) (-78900.087818) 1069.19844
            it "computes NED between positions" $ do
                let p1 = Geodetic.latLongHeightPos 49.66618 3.45063 (Length.metres 12000) WGS84
                let p2 = Geodetic.latLongHeightPos 48.88667 2.37472 (Length.metres 15000) WGS84
                let d = Local.nedBetween p1 p2
                d `shouldBe` Local.nedMetres (-86328.623924) (-79085.290891) (-1928.287847)
        describe "deltaBetween" $
            it "computes delta between positions in frame L" $ do
                let p1 = Geodetic.latLongHeightPos 1 2 (Length.metres (-3)) WGS84
                let p2 = Geodetic.latLongHeightPos 4 5 (Length.metres (-6)) WGS84
                let w = Angle.decimalDegrees 5 -- wander azimuth
                let d = Local.deltaBetween p1 p2 (Local.frameL w)
                d `shouldBe` Local.deltaMetres 359490.578214 302818.522536 17404.271362
        describe "deltaBetween and destination consistency" $
            it "computes targetN p1 (nedBetween p1 p2) = p2" $ do
                let p1 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
                let p2 = Geodetic.latLongHeightPos 48.88667 2.37472 Length.zero WGS84
                Local.destinationN p1 (Local.nedBetween p1 p2) `shouldBe` p2
        describe "rotation matrix to/from earth-fixed frame" $ do
            it "computes rEN (frame N to earth-fixed frame)" $ do
                let p = Geodetic.latLongHeightPos 0.0 0.0 Length.zero WGS84
                let f = Local.frameN p
                Local.rEF f `shouldBe`
                    [Math3d.vec3 0.0 0.0 (-1.0), Math3d.vec3 0.0 1.0 0.0, Math3d.vec3 1.0 0.0 0.0]
            it "computes rEB (frame B to earth-fixed frame)" $ do
                let p = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
                let f =
                        Local.frameB
                            (Angle.decimalDegrees 10)
                            (Angle.decimalDegrees 20)
                            (Angle.decimalDegrees 30)
                            p
                Local.rEF f `shouldBe`
                    [ Math3d.vec3
                          (-0.49300713580470057)
                          (-0.37038991706707025)
                          (-0.7872453705044535)
                    , Math3d.vec3 0.1337450488624887 0.8618333991596926 (-0.4892396692804258)
                    , Math3d.vec3 0.8596837941652826 (-0.3464888186188679) (-0.375352198104241)
                    ]
    describe "North, East, Down delta" $ do
        describe "slantRange" $
            it "computes the slant range of a NED vector" $
            Local.slantRange (Local.nedMetres (-86126) (-78900) 1069) `shouldBe`
            Length.metres 116807.707952
        describe "bearing" $
            it "computes the bearing of a NED vector" $
            Local.bearing (Local.nedMetres (-86126) (-78900) 1069) `shouldBe`
            Angle.decimalDegrees 222.49278897666667
        describe "elevation" $
            it "computes the elevation of a NED vector from horizontal" $
            Local.elevation (Local.nedMetres (-86126) (-78900) 1069) `shouldBe`
            Angle.decimalDegrees (-0.5243664513888889)