coordinate 0.0.20 → 0.0.21
raw patch · 10 files changed
+269/−41 lines, 10 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.Geo.Coordinate.Minutes: remMinutes :: Int -> Minutes
- Data.Geo.Coordinate.Seconds: remSeconds :: Double -> Seconds
+ Data.Geo.Coordinate.Coordinate: antipode :: Iso' Coordinate Coordinate
+ Data.Geo.Coordinate.DegreesLatitude: antipodeDegreesLatitude :: Iso' DegreesLatitude DegreesLatitude
+ Data.Geo.Coordinate.DegreesLongitude: antipodeDegreesLongitude :: Iso' DegreesLongitude DegreesLongitude
+ Data.Geo.Coordinate.Latitude: antipodeLatitude :: Iso' Latitude Latitude
+ Data.Geo.Coordinate.Latitude: modLatitude :: Int -> Int -> Double -> Latitude
+ Data.Geo.Coordinate.Longitude: antipodeLongitude :: Iso' Longitude Longitude
+ Data.Geo.Coordinate.Longitude: modLongitude :: Int -> Int -> Double -> Longitude
+ Data.Geo.Coordinate.Minutes: modMinutes :: Int -> Minutes
+ Data.Geo.Coordinate.Seconds: modSeconds :: Double -> Seconds
Files
- LICENCE +1/−1
- changelog +5/−0
- coordinate.cabal +2/−2
- src/Data/Geo/Coordinate/Coordinate.hs +14/−3
- src/Data/Geo/Coordinate/DegreesLatitude.hs +27/−3
- src/Data/Geo/Coordinate/DegreesLongitude.hs +27/−3
- src/Data/Geo/Coordinate/Latitude.hs +80/−4
- src/Data/Geo/Coordinate/Longitude.hs +80/−4
- src/Data/Geo/Coordinate/Minutes.hs +17/−11
- src/Data/Geo/Coordinate/Seconds.hs +16/−10
LICENCE view
@@ -1,4 +1,4 @@-Copyright 2013-2014 NICTA Limited+Copyright 2013-2016 NICTA Limited All rights reserved.
changelog view
@@ -1,3 +1,8 @@+0.0.21++* fix modulo arithmetic for minutes, seconds.+* antipode functions.+ 0.0.20 * fix modulo arithmetic for latitude and longitude.
coordinate.cabal view
@@ -1,10 +1,10 @@ name: coordinate-version: 0.0.20+version: 0.0.21 license: BSD3 license-file: LICENCE author: Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> maintainer: Tony Morris-copyright: Copyright (C) 2013-2014 NICTA Limited+copyright: Copyright (C) 2013-2016 NICTA Limited synopsis: A representation of latitude and longitude category: Development description:
src/Data/Geo/Coordinate/Coordinate.hs view
@@ -14,16 +14,17 @@ , longitudeSeconds , (.#.) , (<°>)+, antipode ) where import Control.Applicative(Applicative((<*>))) import Control.Category(Category(id, (.)))-import Control.Lens(Identity, Const, Prism', Choice, swapped, Profunctor, Optic', (^.), iso, from, lens, prism', swapped, (^?), (#))+import Control.Lens(Identity, Const, Prism', Choice, Iso', swapped, Profunctor, Optic', (^.), iso, from, lens, prism', swapped, (^?), (#)) import Control.Monad(Monad(return)) import Data.Eq(Eq) import Data.Functor(Functor, (<$>))-import Data.Geo.Coordinate.Latitude(AsLatitude(_Latitude), Latitude)-import Data.Geo.Coordinate.Longitude(AsLongitude(_Longitude), Longitude)+import Data.Geo.Coordinate.Latitude(AsLatitude(_Latitude), Latitude, antipodeLatitude)+import Data.Geo.Coordinate.Longitude(AsLongitude(_Longitude), Longitude, antipodeLongitude) import Data.Geo.Coordinate.DegreesLatitude(AsDegreesLatitude(_DegreesLatitude), DegreesLatitude) import Data.Geo.Coordinate.DegreesLongitude(AsDegreesLongitude(_DegreesLongitude), DegreesLongitude) import Data.Geo.Coordinate.Minutes(Minutes, AsMinutes(_Minutes))@@ -211,3 +212,13 @@ Optic' (->) f coord Seconds longitudeSeconds = _Coordinate . _Longitude . _Seconds++antipode ::+ Iso'+ Coordinate+ Coordinate+antipode =+ let n (Coordinate lat lon) = Coordinate (antipodeLatitude # lat) (antipodeLongitude # lon)+ in iso+ n+ n
src/Data/Geo/Coordinate/DegreesLatitude.hs view
@@ -6,17 +6,18 @@ DegreesLatitude , AsDegreesLatitude(..) , modDegreesLatitude+, antipodeDegreesLatitude ) where import Control.Applicative(Applicative) import Control.Category(Category(id))-import Control.Lens(Optic', Choice, prism')+import Control.Lens(Optic', Choice, prism', Iso', iso) import Data.Bool((&&)) import Data.Eq(Eq((==))) import Data.Int(Int) import Data.Maybe(Maybe(Just, Nothing)) import Data.Ord(Ord((<), (>)))-import Prelude(Show, mod, Num((+), (-)))+import Prelude(Show, mod, Num(negate, (+), (-))) -- $setup -- >>> import Control.Lens((#), (^?))@@ -64,7 +65,7 @@ then Just (DegreesLatitude i) else Nothing) --- | Setting a value @>= 90@ will get that value @(`rem` 90)@.+-- | Setting a value within the range @-90@ and @90@ using modulo arithmetic. -- -- >>> modDegreesLatitude 7 -- DegreesLatitude 7@@ -100,3 +101,26 @@ -> DegreesLatitude modDegreesLatitude x = DegreesLatitude (if x == 90 then 90 else mod (x + 90) 180 - 90)++-- | The degrees latitude that is symmetrical around the equator.+--+-- >>> antipodeDegreesLatitude # modDegreesLatitude 30+-- DegreesLatitude (-30)+--+-- >>> antipodeDegreesLatitude # modDegreesLatitude 80+-- DegreesLatitude (-80)+--+-- >>> antipodeDegreesLatitude # modDegreesLatitude 110+-- DegreesLatitude 70+--+-- >>> antipodeDegreesLatitude # modDegreesLatitude 0+-- DegreesLatitude 0+antipodeDegreesLatitude ::+ Iso'+ DegreesLatitude+ DegreesLatitude+antipodeDegreesLatitude =+ let n (DegreesLatitude x) = DegreesLatitude (negate x)+ in iso+ n+ n
src/Data/Geo/Coordinate/DegreesLongitude.hs view
@@ -6,17 +6,18 @@ DegreesLongitude , AsDegreesLongitude(..) , modDegreesLongitude+, antipodeDegreesLongitude ) where import Control.Applicative(Applicative) import Control.Category(Category(id))-import Control.Lens(Optic', Choice, prism')+import Control.Lens(Optic', Choice, prism', Iso', iso) import Data.Bool((&&)) import Data.Eq(Eq((==))) import Data.Int(Int) import Data.Maybe(Maybe(Just, Nothing)) import Data.Ord(Ord((<), (>)))-import Prelude(Show, mod, Num((+), (-)))+import Prelude(Show, mod, Num(negate, (+), (-))) -- $setup -- >>> import Control.Lens((#), (^?))@@ -64,7 +65,7 @@ then Just (DegreesLongitude i) else Nothing) --- | Setting a value @>= 180@ will get that value @(`rem` 180)@.+-- | Setting a value within the range @-180@ and @180@ using modulo arithmetic. -- -- >>> modDegreesLongitude 7 -- DegreesLongitude 7@@ -100,3 +101,26 @@ -> DegreesLongitude modDegreesLongitude x = DegreesLongitude (if x == 180 then 180 else mod (x + 180) 360 - 180)++-- | The degrees longitude that is symmetrical around the prime meridian.+--+-- >>> antipodeDegreesLongitude # modDegreesLongitude 30+-- DegreesLongitude (-30)+--+-- >>> antipodeDegreesLongitude # modDegreesLongitude 100+-- DegreesLongitude (-100)+--+-- >>> antipodeDegreesLongitude # modDegreesLongitude 190+-- DegreesLongitude 170+--+-- >>> antipodeDegreesLongitude # modDegreesLongitude 0+-- DegreesLongitude 0+antipodeDegreesLongitude ::+ Iso'+ DegreesLongitude+ DegreesLongitude+antipodeDegreesLongitude =+ let n (DegreesLongitude x) = DegreesLongitude (negate x)+ in iso+ n+ n
src/Data/Geo/Coordinate/Latitude.hs view
@@ -6,17 +6,20 @@ module Data.Geo.Coordinate.Latitude( Latitude , AsLatitude(..)+, modLatitude+, antipodeLatitude ) where import Control.Applicative(Applicative) import Control.Category(Category(id))-import Control.Lens(Choice, Profunctor, Optic', iso, prism', lens, (#), (^?))+import Control.Lens(Choice, Profunctor, Optic', Iso', iso, prism', lens, (#), (^?)) import Control.Monad(Monad(return)) import Data.Eq(Eq)+import Data.Fixed(divMod') import Data.Functor(Functor)-import Data.Geo.Coordinate.DegreesLatitude(DegreesLatitude, AsDegreesLatitude(_DegreesLatitude))-import Data.Geo.Coordinate.Minutes(AsMinutes(_Minutes), Minutes)-import Data.Geo.Coordinate.Seconds(AsSeconds(_Seconds), Seconds)+import Data.Geo.Coordinate.DegreesLatitude(DegreesLatitude, AsDegreesLatitude(_DegreesLatitude), modDegreesLatitude, antipodeDegreesLatitude)+import Data.Geo.Coordinate.Minutes(AsMinutes(_Minutes), Minutes, modMinutes)+import Data.Geo.Coordinate.Seconds(AsSeconds(_Seconds), Seconds, modSeconds) import Data.Ord(Ord((<))) import Prelude(Double, Show, Int, Num((+), (*), (-), abs), Fractional((/)), properFraction, fromIntegral) @@ -135,3 +138,76 @@ instance (p ~ (->), Functor f) => AsSeconds p f Latitude where _Seconds = lens (\(Latitude _ _ s) -> s) (\(Latitude d m _) s -> Latitude d m s)++-- | Setting a latitude using modulo arithmetic.+--+-- >>> modLatitude 20 20 20+-- Latitude (DegreesLatitude 20) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 20 20 (-20)+-- Latitude (DegreesLatitude 20) (Minutes 19) (Seconds 40.0000)+--+-- >>> modLatitude 20 20 80+-- Latitude (DegreesLatitude 20) (Minutes 21) (Seconds 20.0000)+--+-- >>> modLatitude 20 80 20+-- Latitude (DegreesLatitude 21) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 20 80 80+-- Latitude (DegreesLatitude 21) (Minutes 21) (Seconds 20.0000)+--+-- >>> modLatitude 20 80 (-20)+-- Latitude (DegreesLatitude 21) (Minutes 19) (Seconds 40.0000)+--+-- >>> modLatitude 110 20 20+-- Latitude (DegreesLatitude (-70)) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 110 20 80+-- Latitude (DegreesLatitude (-70)) (Minutes 21) (Seconds 20.0000)+--+-- >>> modLatitude 110 80 20+-- Latitude (DegreesLatitude (-69)) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 110 20 (-20)+-- Latitude (DegreesLatitude (-70)) (Minutes 19) (Seconds 40.0000)+--+-- >>> modLatitude 110 (-20) (-20)+-- Latitude (DegreesLatitude (-71)) (Minutes 39) (Seconds 40.0000)+--+-- >>> modLatitude 110 (-80) (-20)+-- Latitude (DegreesLatitude (-72)) (Minutes 39) (Seconds 40.0000)+--+-- >>> modLatitude 20 20 3620+-- Latitude (DegreesLatitude 21) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 20 20 (-3580)+-- Latitude (DegreesLatitude 19) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 110 20 3620+-- Latitude (DegreesLatitude (-69)) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLatitude 110 20 (-3580)+-- Latitude (DegreesLatitude (-71)) (Minutes 20) (Seconds 20.0000)+modLatitude ::+ Int+ -> Int+ -> Double+ -> Latitude+modLatitude d m s =+ let (ts, rs) = s `divMod'` 60+ (tm, rm) = (ts + m) `divMod'` 60+ in Latitude (modDegreesLatitude (tm + d)) (modMinutes rm) (modSeconds rs)++-- | The latitude that is symmetrical around the equator.+--+-- >>> fmap (\x -> antipodeLatitude # x) (do d <- (7 :: Int) ^? _DegreesLatitude; m <- (7 :: Int) ^? _Minutes; s <- (7 :: Double) ^? _Seconds; (d, m, s) ^? _Latitude :: Maybe Latitude)+-- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 7.0000))+antipodeLatitude ::+ Iso'+ Latitude+ Latitude+antipodeLatitude =+ let n (Latitude d m s) = Latitude (antipodeDegreesLatitude # d) m s+ in iso+ n+ n
src/Data/Geo/Coordinate/Longitude.hs view
@@ -6,17 +6,20 @@ module Data.Geo.Coordinate.Longitude( Longitude , AsLongitude(..)+, modLongitude+, antipodeLongitude ) where import Control.Applicative(Applicative) import Control.Category(Category(id))-import Control.Lens(Choice, Profunctor, Optic', iso, prism', lens, (#), (^?))+import Control.Lens(Choice, Profunctor, Optic', Iso', iso, prism', lens, (#), (^?)) import Control.Monad(Monad(return)) import Data.Eq(Eq)+import Data.Fixed(divMod') import Data.Functor(Functor)-import Data.Geo.Coordinate.DegreesLongitude(DegreesLongitude, AsDegreesLongitude(_DegreesLongitude))-import Data.Geo.Coordinate.Minutes(AsMinutes(_Minutes), Minutes)-import Data.Geo.Coordinate.Seconds(AsSeconds(_Seconds), Seconds)+import Data.Geo.Coordinate.DegreesLongitude(DegreesLongitude, AsDegreesLongitude(_DegreesLongitude), modDegreesLongitude, antipodeDegreesLongitude)+import Data.Geo.Coordinate.Minutes(AsMinutes(_Minutes), Minutes, modMinutes)+import Data.Geo.Coordinate.Seconds(AsSeconds(_Seconds), Seconds, modSeconds) import Data.Ord(Ord((<))) import Prelude(Double, Show, Int, Num((+), (*), (-), abs), Fractional((/)), properFraction, fromIntegral) @@ -135,3 +138,76 @@ instance (p ~ (->), Functor f) => AsSeconds p f Longitude where _Seconds = lens (\(Longitude _ _ s) -> s) (\(Longitude d m _) s -> Longitude d m s)++-- | Setting a longitude using modulo arithmetic.+--+-- >>> modLongitude 20 20 20+-- Longitude (DegreesLongitude 20) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 20 20 (-20)+-- Longitude (DegreesLongitude 20) (Minutes 19) (Seconds 40.0000)+--+-- >>> modLongitude 20 20 80+-- Longitude (DegreesLongitude 20) (Minutes 21) (Seconds 20.0000)+--+-- >>> modLongitude 20 80 20+-- Longitude (DegreesLongitude 21) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 20 80 80+-- Longitude (DegreesLongitude 21) (Minutes 21) (Seconds 20.0000)+--+-- >>> modLongitude 20 80 (-20)+-- Longitude (DegreesLongitude 21) (Minutes 19) (Seconds 40.0000)+--+-- >>> modLongitude 200 20 20+-- Longitude (DegreesLongitude (-160)) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 200 20 80+-- Longitude (DegreesLongitude (-160)) (Minutes 21) (Seconds 20.0000)+--+-- >>> modLongitude 200 80 20+-- Longitude (DegreesLongitude (-159)) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 200 20 (-20)+-- Longitude (DegreesLongitude (-160)) (Minutes 19) (Seconds 40.0000)+--+-- >>> modLongitude 200 (-20) (-20)+-- Longitude (DegreesLongitude (-161)) (Minutes 39) (Seconds 40.0000)+--+-- >>> modLongitude 200 (-80) (-20)+-- Longitude (DegreesLongitude (-162)) (Minutes 39) (Seconds 40.0000)+--+-- >>> modLongitude 20 20 3620+-- Longitude (DegreesLongitude 21) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 20 20 (-3580)+-- Longitude (DegreesLongitude 19) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 200 20 3620+-- Longitude (DegreesLongitude (-159)) (Minutes 20) (Seconds 20.0000)+--+-- >>> modLongitude 200 20 (-3580)+-- Longitude (DegreesLongitude (-161)) (Minutes 20) (Seconds 20.0000)+modLongitude ::+ Int+ -> Int+ -> Double+ -> Longitude+modLongitude d m s =+ let (ts, rs) = s `divMod'` 60+ (tm, rm) = (ts + m) `divMod'` 60+ in Longitude (modDegreesLongitude (tm + d)) (modMinutes rm) (modSeconds rs)++-- | The longitude that is symmetrical around the prime meridian.+--+-- >>> fmap (\x -> antipodeLongitude # x) (do d <- (7 :: Int) ^? _DegreesLongitude; m <- (7 :: Int) ^? _Minutes; s <- (7 :: Double) ^? _Seconds; (d, m, s) ^? _Longitude :: Maybe Longitude)+-- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 7.0000))+antipodeLongitude ::+ Iso'+ Longitude+ Longitude+antipodeLongitude =+ let n (Longitude d m s) = Longitude (antipodeDegreesLongitude # d) m s+ in iso+ n+ n
src/Data/Geo/Coordinate/Minutes.hs view
@@ -5,7 +5,7 @@ module Data.Geo.Coordinate.Minutes( Minutes , AsMinutes(..)-, remMinutes+, modMinutes ) where import Control.Applicative(Applicative)@@ -16,7 +16,7 @@ import Data.Eq(Eq) import Data.Int(Int) import Data.Ord(Ord((>=), (<)))-import Prelude(Show, rem)+import Prelude(Show, mod) -- $setup -- >>> import Control.Lens((#), (^?), (^.))@@ -58,24 +58,30 @@ then Just (Minutes i) else Nothing) --- | Setting a value @>= 60@ will get that value @(`rem` 60)@.+-- | Setting a value within the range @0@ and @60@ using modulo arithmetic. ----- >>> remMinutes 7+-- >>> modMinutes 7 -- Minutes 7 ----- >>> remMinutes 0+-- >>> modMinutes 0 -- Minutes 0 ----- >>> remMinutes 60+-- >>> modMinutes 60 -- Minutes 0 ----- >>> remMinutes 1+-- >>> modMinutes 1 -- Minutes 1 ----- >>> remMinutes 59+-- >>> modMinutes 59 -- Minutes 59 -remMinutes ::+--+-- >>> modMinutes 61+-- Minutes 1+--+-- >>> modMinutes (-1)+-- Minutes 59+modMinutes :: Int -> Minutes-remMinutes x =- Minutes (x `rem` 60)+modMinutes x =+ Minutes (x `mod` 60)
src/Data/Geo/Coordinate/Seconds.hs view
@@ -5,7 +5,7 @@ module Data.Geo.Coordinate.Seconds( Seconds , AsSeconds(..)-, remSeconds+, modSeconds ) where import Control.Applicative(Applicative)@@ -71,27 +71,33 @@ then Just (Seconds d) else Nothing) --- | Setting a value @>= 60@ will get that value @(`rem` 60)@.+-- | Setting a value within the range @0@ and @60@ using modulo arithmetic. ----- >>> remSeconds 7+-- >>> modSeconds 7 -- Seconds 7.0000 ----- >>> remSeconds 0+-- >>> modSeconds 0 -- Seconds 0.0000 ----- >>> remSeconds (-0.0001)+-- >>> modSeconds (-0.0001) -- Seconds 59.9999 ----- >>> remSeconds 60+-- >>> modSeconds 60 -- Seconds 0.0000 ----- >>> remSeconds 59.99999+-- >>> modSeconds 59.99999 -- Seconds 60.0000 ----- >>> remSeconds 59.999+-- >>> modSeconds 59.999 -- Seconds 59.9990-remSeconds ::+--+-- >>> modSeconds 61+-- Seconds 1.0000+--+-- >>> modSeconds (-1)+-- Seconds 59.0000+modSeconds :: Double -> Seconds-remSeconds x =+modSeconds x = Seconds (snd (x `divMod'` 60.0 :: (Int, Double)))