jord-2.0.0.0: test/Data/Geo/Jord/PositionsSpec.hs
module Data.Geo.Jord.PositionsSpec
( spec
) where
import Test.Hspec
import Data.Maybe (fromJust)
import qualified Data.Geo.Jord.Geocentric as Geocentric
import qualified Data.Geo.Jord.Geodetic as Geodetic
import qualified Data.Geo.Jord.Length as Length
import Data.Geo.Jord.Model (Epoch(..))
import Data.Geo.Jord.Models
import qualified Data.Geo.Jord.Positions as Positions
import qualified Data.Geo.Jord.Tx as Tx
import qualified Data.Geo.Jord.Txs as Txs
spec :: Spec
spec = do
describe "Geodetic <=> Geocentric (Ellipsoidal)" $ do
it "n-vector <=> Geocentric" $ do
let p = Geodetic.nvectorHeightPos 0.5 0.5 0.7071067811865475 Length.zero WGS84
let g = Geocentric.metresPos 3194419.145061 3194419.145061 4487348.408866 WGS84
Positions.toGeocentric p `shouldBe` g
Positions.toGeodetic g `shouldBe` p
it "latitude, longitude and height <=> Geocentric" $ do
let refLlh =
[ Geodetic.latLongHeightPos 0 0 Length.zero WGS84
, Geodetic.latLongHeightPos 90 0 Length.zero WGS84
, Geodetic.latLongHeightPos (-90) 0 Length.zero WGS84
, Geodetic.latLongHeightPos 45.0 45.0 (Length.metres 500) WGS84
, Geodetic.latLongHeightPos (-45) (-45) (Length.metres 500) WGS84
]
let refGeocentrics =
[ Geocentric.metresPos 6378137 0 0 WGS84
, Geocentric.metresPos 0 0 6356752.314245 WGS84
, Geocentric.metresPos 0 0 (-6356752.314245) WGS84
, Geocentric.metresPos 3194669.145061 3194669.145061 4487701.962256 WGS84
, Geocentric.metresPos 3194669.145061 (-3194669.145061) (-4487701.962256) WGS84
]
fmap Positions.toGeocentric refLlh `shouldBe` refGeocentrics
fmap Positions.toGeodetic refGeocentrics `shouldBe` refLlh
describe "Geodetic <=> Geocentric (Spherical)" $ do
it "n-vector <=> Geocentric" $ do
let p = Geodetic.nvectorHeightPos 0.5 0.5 0.7071 Length.zero S84
let g = Geocentric.metresPos 3185519.660307 3185519.660307 4504961.903617 S84
Positions.toGeocentric p `shouldBe` g
Positions.toGeodetic g `shouldBe` p
it "latitude, longitude and height <=> Geocentric" $ do
let refLlh =
[ Geodetic.latLongHeightPos 0 0 Length.zero S84
, Geodetic.latLongHeightPos 90 0 Length.zero S84
, Geodetic.latLongHeightPos (-90) 0 Length.zero S84
, Geodetic.latLongHeightPos 45.0 45.0 (Length.metres 500) S84
, Geodetic.latLongHeightPos (-45) (-45) (Length.metres 500) S84
]
let refGeocentrics =
[ Geocentric.metresPos 6371008.771415 0 0 S84
, Geocentric.metresPos 0 0 6371008.771415 S84
, Geocentric.metresPos 0 0 (-6371008.771415) S84
, Geocentric.metresPos 3185754.385708 3185754.385708 4505337.058657 S84
, Geocentric.metresPos 3185754.385708 (-3185754.385708) (-4505337.058657) S84
]
fmap Positions.toGeocentric refLlh `shouldBe` refGeocentrics
fmap Positions.toGeodetic refGeocentrics `shouldBe` refLlh
describe "coordinates transformation - fixed" $ do
it "returns the initial coordinates if all parameters are 0" $ do
let tx7 = Tx.params7 (0, 0, 0) 0 (0, 0, 0)
let pWGS84 = Geocentric.metresPos 4193790.895437 454436.195118 4768166.813801 WGS84
Positions.transform' pWGS84 WGS84 tx7 `shouldBe` pWGS84
it "uses the 7-parameter transformation" $ do
let pWGS84 = Geocentric.metresPos 4193790.895437 454436.195118 4768166.813801 WGS84
let tx = Tx.params Txs.from_WGS84_to_NAD83
let pNAD83 = Positions.transform' pWGS84 NAD83 tx
pNAD83 `shouldBe` Geocentric.metresPos 4193792.080781 454433.921298 4768166.15479 NAD83
it "returns the initial coordinates when doing round-trip (direct -> inverse)" $ do
let tx = Tx.params Txs.from_WGS84_to_ETRS89
let itx = Tx.inverseParams tx
let pWGS84 = Geocentric.metresPos 3194419.145061 3194419.145061 4487348.408866 WGS84
Positions.transform' (Positions.transform' pWGS84 NAD83 tx) WGS84 itx `shouldBe` pWGS84
describe "coordinates transformation - time dependent" $ do
it "returns the initial coordinates if all parameters are 0" $ do
let tx15 =
Tx.Params15
(Epoch 2010)
(Tx.params7 (0, 0, 0) 0 (0, 0, 0))
(Tx.rates (0, 0, 0) 0 (0, 0, 0))
let pWGS84 =
Geocentric.metresPos 4193790.895437 454436.195118 4768166.813801 WGS84_G1762
Positions.transformAt' pWGS84 (Epoch 2010.0) WGS84_G1762 tx15 `shouldBe` pWGS84
it "uses the 15-parameter transformation and position epoch" $ do
let pITRF2014 = Geocentric.metresPos 4027894.006 307045.600 4919474.910 ITRF2014
let tx = Tx.params Txs.from_ITRF2014_to_ETRF2000
let pETRF2000 = Positions.transformAt' pITRF2014 (Epoch 2012.0) ETRF2000 tx
pETRF2000 `shouldBe`
Geocentric.metresPos 4027894.366234 307045.252967 4919474.626307 ETRF2000
it "returns the initial coordinates when doing round-trip (direct -> inverse)" $ do
let tx = Tx.params Txs.from_ITRF2014_to_ETRF2000
let itx = Tx.inverseParams tx
let pITRF2014 = Geocentric.metresPos 4027894.006 307045.600 4919474.910 ITRF2014
let e = Epoch 2019.0
Positions.transformAt' (Positions.transformAt' pITRF2014 e ETRF2000 tx) e ITRF2014 itx `shouldBe`
pITRF2014
it "returns the initial coordinates when using chained conversion round-trip" $ do
let pNAD83 =
Positions.toGeocentric (Geodetic.latLongHeightPos 0 0 Length.zero NAD83_CORS96)
-- goes via ITRF2000
let pITRF2014 =
fromJust
(Positions.transformAt pNAD83 (Epoch 2014.0) ITRF2014 Txs.timeDependent)
Positions.transformAt pITRF2014 (Epoch 2014.0) NAD83_CORS96 Txs.timeDependent `shouldBe`
Just pNAD83
it "converts between ITRF2000 & ETRF2000" $ do
let pITRF2000 = Geocentric.metresPos 4027894.006 307045.600 4919474.910 ITRF2000
let pETRF2000 =
fromJust
(Positions.transformAt pITRF2000 (Epoch 2012) ETRF2000 Txs.timeDependent)
pETRF2000 `shouldBe`
Geocentric.metresPos 4027894.355909 307045.250849 4919474.644695 ETRF2000
it "converts between ITRF2014 & ETRF2000" $ do
let pITRF2014 = Geocentric.metresPos 4027894.006 307045.600 4919474.910 ITRF2014
let pETRF2000 =
fromJust
(Positions.transformAt pITRF2014 (Epoch 2012) ETRF2000 Txs.timeDependent)
pETRF2000 `shouldBe`
Geocentric.metresPos 4027894.366234 307045.252967 4919474.626307 ETRF2000