jord-2.0.0.0: test/Data/Geo/Jord/GeodeticSpec.hs
module Data.Geo.Jord.GeodeticSpec
( spec
) where
import Data.Maybe (mapMaybe)
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.Models (GRS80(..), Mars2000(..), S84(..), WGS84(..))
spec :: Spec
spec = do
describe "antipode" $ do
it "returns the antipodal position" $ do
Geodetic.antipode (Geodetic.wgs84Pos 45 154) `shouldBe` Geodetic.wgs84Pos (-45) (-26)
Geodetic.antipode (Geodetic.s84Pos 45 154) `shouldBe` Geodetic.s84Pos (-45) (-26)
Geodetic.antipode' (Geodetic.latLongHeightPos 45 154 (Length.metres 15000) WGS84) `shouldBe`
Geodetic.latLongHeightPos (-45) (-26) (Length.metres 15000) WGS84
Geodetic.antipode' (Geodetic.latLongHeightPos 45 154 (Length.metres 15000) S84) `shouldBe`
Geodetic.latLongHeightPos (-45) (-26) (Length.metres 15000) S84
it "returns the south pole when called with the north pole" $ do
Geodetic.antipode (Geodetic.northPole WGS84) `shouldBe` Geodetic.southPole WGS84
it "returns the north pole when called with the south pole" $ do
Geodetic.antipode (Geodetic.southPole WGS84) `shouldBe` Geodetic.northPole WGS84
describe "poles" $ do
it "returns 90°, 0° for the north pole" $ do
Geodetic.latitude (Geodetic.northPole WGS84) `shouldBe` Angle.decimalDegrees 90
Geodetic.longitude (Geodetic.northPole WGS84) `shouldBe` Angle.zero
it "returns -90°, 0° for the south pole" $ do
Geodetic.latitude (Geodetic.southPole WGS84) `shouldBe` Angle.decimalDegrees (-90)
Geodetic.longitude (Geodetic.southPole WGS84) `shouldBe` Angle.zero
it "always returns a longitude of 0° at the north pole" $ do
let longs = (take 37 (iterate (\x -> x + 10 :: Double) (-180.0)))
fmap (\long -> Geodetic.wgs84Pos 90 long) longs `shouldBe`
(replicate 37 (Geodetic.northPole WGS84))
it "always returns a longitude of 0° at the south pole" $ do
let longs = (take 37 (iterate (\x -> x + 10 :: Double) (-180.0)))
fmap (\long -> Geodetic.wgs84Pos (-90) long) longs `shouldBe`
(replicate 37 (Geodetic.southPole WGS84))
describe "wrapping latitude/longitude" $ do
it "wraps a Earth position to [-90°, 90°] and [-180°, 180°]" $ do
let p1 = Geodetic.s84Pos 91 54
Geodetic.latitude p1 `shouldBe` Angle.decimalDegrees 89
Geodetic.longitude p1 `shouldBe` Angle.decimalDegrees (-126)
let p2 = Geodetic.s84Pos 91 (-150)
Geodetic.latitude p2 `shouldBe` Angle.decimalDegrees 89
Geodetic.longitude p2 `shouldBe` Angle.decimalDegrees 30
it "wraps a Mars position longitude to [0°, 360°]" $ do
let p = Geodetic.latLongPos 89 (-150) Mars2000
Geodetic.latitude p `shouldBe` Angle.decimalDegrees 89
Geodetic.longitude p `shouldBe` Angle.decimalDegrees 210
it "wraps a Mars position to [-90°, 90°] and [0°, 360°]" $ do
let p = Geodetic.latLongPos 91 (-150) Mars2000
Geodetic.latitude p `shouldBe` Angle.decimalDegrees 89
Geodetic.longitude p `shouldBe` Angle.decimalDegrees 30
describe "wrapping n-vector" $ do
it "wraps a n-vector Mars position to [-90°, 90°] and [0°, 360°]" $ do
let p = Geodetic.nvectorPos (-0.8660254037844387) (-0.49999999999999994) 0 Mars2000
Geodetic.latitude p `shouldBe` Angle.zero
Geodetic.longitude p `shouldBe` Angle.decimalDegrees 210
describe "Reading valid DMS text" $ do
it "reads WGS84 horizontal positions" $ do
let texts =
[ "553621N0130002E"
, "5536N01300E"
, "55N013E"
, "011659S0364900E"
, "0116S03649E"
, "01S036E"
, "473622N1221955W"
, "4736N12219W"
, "47N122W"
, "544807S0681811W"
, "5448S06818W"
, "54S068W"
, "55°36'21''N 013°00'02''E"
, "1°16'S,36°49'E"
, "47°N 122°W"
]
let positions =
[ Geodetic.wgs84Pos 55.60583333333334 13.000555555555556
, Geodetic.wgs84Pos 55.6 13.0
, Geodetic.wgs84Pos 55.0 13.0
, Geodetic.wgs84Pos (-1.2830555555555556) 36.81666666666667
, Geodetic.wgs84Pos (-1.2666666666666666) 36.81666666666667
, Geodetic.wgs84Pos (-1.0) 36.0
, Geodetic.wgs84Pos 47.60611111111111 (-122.33194444444445)
, Geodetic.wgs84Pos 47.6 (-122.31666666666666)
, Geodetic.wgs84Pos 47.0 (-122.0)
, Geodetic.wgs84Pos (-54.801944444444445) (-68.30305555555556)
, Geodetic.wgs84Pos (-54.8) (-68.3)
, Geodetic.wgs84Pos (-54.0) (-68.0)
, Geodetic.wgs84Pos 55.60583333333334 13.000555555555556
, Geodetic.wgs84Pos (-1.2666666666666666) 36.81666666666667
, Geodetic.wgs84Pos 47.0 (-122.0)
]
mapMaybe (`Geodetic.readHorizontalPosition` WGS84) texts `shouldBe` positions
it "reads positions around the WGS84 ellipsoid" $ do
let texts = ["55°36'21''N 013°00'02''E 5m", "55°36'21''N 013°00'02''E -5m"]
let positions =
[ Geodetic.latLongHeightPos
55.60583333333334
13.000555555555556
(Length.metres 5)
WGS84
, Geodetic.latLongHeightPos
55.60583333333334
13.000555555555556
(Length.metres (-5))
WGS84
]
mapMaybe (`Geodetic.readPosition` WGS84) texts `shouldBe` positions
it "reads positions around the S84 sphere" $ do
let texts = ["55°36'21''N 013°00'02''E 5m", "55°36'21''N 013°00'02''E -5m"]
let positions =
[ Geodetic.latLongHeightPos
55.60583333333334
13.000555555555556
(Length.metres 5)
S84
, Geodetic.latLongHeightPos
55.60583333333334
13.000555555555556
(Length.metres (-5))
S84
]
mapMaybe (`Geodetic.readPosition` S84) texts `shouldBe` positions
it "reads Mars horizontal positions" $ do
let texts = ["54S360E", "55°36'21''N 341°34'02''E"]
let positions =
[ Geodetic.latLongPos (-54.0) 360 Mars2000
, Geodetic.latLongPos 55.60583333333334 341.5672222222222 Mars2000
]
mapMaybe (`Geodetic.readHorizontalPosition` Mars2000) texts `shouldBe` positions
describe "Attempting to read invalid DMS text" $ do
it "fails to read syntactically invalid positions" $ do
let texts = ["553621K0130002E", "011659S0364900Z", "4736221221955W", "54480S0681811W"]
mapMaybe (`Geodetic.readHorizontalPosition` WGS84) texts `shouldBe` []
it "fails to read invalid WGS84 surface positions" $ do
let texts = ["914807S0681811W", "804807S1811811W"]
mapMaybe (`Geodetic.readHorizontalPosition` WGS84) texts `shouldBe` []
it "fails to read invalid Mars surface positions" $ do
let texts = ["914807S0681811E", "5448S06818W"]
mapMaybe (`Geodetic.readHorizontalPosition` Mars2000) texts `shouldBe` []
describe "Showing positions" $ do
it "shows the N/E position formatted in DMS with symbols" $
show (Geodetic.latLongHeightPos 55.6058333333 13.00055556 (Length.metres 5) WGS84) `shouldBe`
"55°36'21.000\"N,13°0'2.000\"E 5.0m (WGS84)"
it "shows the S/E position formatted in DMS with symbols" $
show (Geodetic.latLongPos (-1.28305556) 36.81666 GRS80) `shouldBe`
"1°16'59.000\"S,36°48'59.976\"E (GRS80)"
it "shows the N/W position formatted in DMS with symbols" $
show (Geodetic.latLongPos 47.60611 (-122.33194) S84) `shouldBe`
"47°36'21.996\"N,122°19'54.984\"W (S84)"
it "shows the S/W position formatted in DMS with symbols" $
show (Geodetic.latLongPos (-54.80194) (-68.30305) S84) `shouldBe`
"54°48'6.984\"S,68°18'10.980\"W (S84)"