packages feed

gps 1.1 → 1.2

raw patch · 6 files changed

+93/−83 lines, 6 filesdep +textdep −GPXdep −hxtdep −xsddep ~gpx-conduitdep ~test-frameworkdep ~test-framework-quickcheck2PVP ok

version bump matches the API change (PVP)

Dependencies added: text

Dependencies removed: GPX, hxt, xsd

Dependency ranges changed: gpx-conduit, test-framework, test-framework-quickcheck2

API changes (from Hackage documentation)

- Geo.Computations: readGPXFile :: FilePath -> IO (Maybe GPX)
+ Geo.Types: Point :: Latitude -> Longitude -> Maybe Double -> Maybe UTCTime -> Point
+ Geo.Types: Segment :: [Point] -> Segment
+ Geo.Types: Track :: Maybe Text -> Maybe Text -> [Segment] -> Track
+ Geo.Types: data Point
+ Geo.Types: data Segment
+ Geo.Types: data Track
+ Geo.Types: instance Eq Point
+ Geo.Types: instance Eq Segment
+ Geo.Types: instance Eq Track
+ Geo.Types: instance Ord Point
+ Geo.Types: instance Ord Segment
+ Geo.Types: instance Ord Track
+ Geo.Types: instance Read Point
+ Geo.Types: instance Read Segment
+ Geo.Types: instance Read Track
+ Geo.Types: instance Show Point
+ Geo.Types: instance Show Segment
+ Geo.Types: instance Show Track
+ Geo.Types: pntEle :: Point -> Maybe Double
+ Geo.Types: pntLat :: Point -> Latitude
+ Geo.Types: pntLon :: Point -> Longitude
+ Geo.Types: pntTime :: Point -> Maybe UTCTime
+ Geo.Types: points :: Segment -> [Point]
+ Geo.Types: pt :: Latitude -> Longitude -> Maybe Double -> Maybe UTCTime -> Point
+ Geo.Types: segments :: Track -> [Segment]
+ Geo.Types: trkDescription :: Track -> Maybe Text
+ Geo.Types: trkName :: Track -> Maybe Text
+ Geo.Types: type Latitude = Double
+ Geo.Types: type Longitude = Double
+ Geo.Types: zeroPoint :: Point
- Geo.Computations: data Point :: *
+ Geo.Computations: data Point

Files

Geo/Computations.hs view
@@ -6,7 +6,9 @@ module Geo.Computations        ( module Geo.Computations.Basic        , module Geo.Computations.Trail+       , module Geo.Types        ) where  import Geo.Computations.Basic import Geo.Computations.Trail+import Geo.Types
Geo/Computations/Basic.hs view
@@ -27,22 +27,20 @@        , circleIntersectionPoints        , intersectionArcsOf        , maximumDistanceOfArc-         -- * IO helpers-       , readGPXFile        ) where  import Data.Time import Data.Maybe-import Geo.GPX.Conduit+import Geo.Types  -- |Distances are expressed in meters type Distance = Double  -- |Angles are expressed in radians from North.--- 	0	== North--- 	pi/2	== West--- 	pi 	== South--- 	(3/2)pi	== East    == - (pi / 2)+--      0       == North+--      pi/2    == West+--      pi      == South+--      (3/2)pi == East    == - (pi / 2) type Heading = Double  -- |Speed is hard coded as meters per second@@ -71,8 +69,8 @@ -- | Direction two points aim toward (0 = North, pi/2 = West, pi = South, 3pi/2 = East) heading         :: Point -> Point -> Heading heading a b =-	atan2	(sin (diffLon) * cos (lat2))-		(cos(lat1) * sin (lat2) - sin(lat1) * cos lat2 * cos (diffLon))+        atan2   (sin (diffLon) * cos (lat2))+                (cos(lat1) * sin (lat2) - sin(lat1) * cos lat2 * cos (diffLon))  where   (lat1, lon1) = getRadianPair a   (lat2, lon2) = getRadianPair b@@ -84,23 +82,23 @@ -- |Given a vector and coordinate, computes a new coordinate. -- Within some epsilon it should hold that if ----- 	@dest = addVector (dist,heading) start@+--      @dest = addVector (dist,heading) start@ -- -- then ----- 	@heading == heading start dest@--- 	--- 	@dist    == distance start dest@+--      @heading == heading start dest@+--      +--      @dist    == distance start dest@ addVector :: Vector -> Point -> Point addVector (d,h) p =                   p { pntLon = toDegrees lon2-		    , pntLat = toDegrees lat2-			}+                    , pntLat = toDegrees lat2+                        }   where-	(lat,lon) = getRadianPair p-	lat2 = asin (sin lat * cos (d / radiusOfEarth) + cos lat+        (lat,lon) = getRadianPair p+        lat2 = asin (sin lat * cos (d / radiusOfEarth) + cos lat                      * sin(d/radiusOfEarth) * cos h)-        lon2 = lon - atan2 (sin h * sin (d / radiusOfEarth) * cos lat)+        lon2 = lon + atan2 (sin h * sin (d / radiusOfEarth) * cos lat)                            (cos (d/radiusOfEarth) - sin lat * sin lat2)  -- | Speed in meters per second, only if a 'Time' was recorded for each waypoint.
Geo/Computations/Trail.hs view
@@ -45,7 +45,7 @@  import Text.Show.Functions () import Geo.Computations.Basic-import Geo.GPX.Conduit ()+import Geo.Types  import Control.Arrow (first) import Control.Monad@@ -55,6 +55,7 @@ import Data.Maybe import Data.Ord import Data.Time+  import Statistics.Function as F import Statistics.Sample
+ Geo/Types.hs view
@@ -0,0 +1,35 @@+module Geo.Types where+import Data.Text+import Data.Time++data Track = Track+        { trkName               :: Maybe Text+        , trkDescription        :: Maybe Text+        , segments              :: [Segment]+        }+        deriving (Eq, Ord, Show, Read)++-- |A GPX segments is just a bundle of points.+data Segment = Segment { points  :: [Point] }+        deriving (Eq, Ord, Show, Read)++type Latitude = Double+type Longitude = Double++-- |Track point is a full-fledged representation of all the data+-- available in most GPS loggers.  It is possible you don't want+-- all this data and can just made do with coordinates (via 'Pnt')+-- or a custom derivative.+data Point = Point+        { pntLat        :: Latitude+        , pntLon        :: Longitude+        , pntEle        :: Maybe Double -- ^ In meters+        , pntTime       :: Maybe UTCTime+        -- , pntSpeed   :: Maybe Double -- ^ Non-standard.  Usually in meters/second.+        }+        deriving (Eq, Ord, Show, Read)++pt :: Latitude -> Longitude -> Maybe Double -> Maybe UTCTime -> Point+pt t g e m = Point t g e m++zeroPoint = Point 0 0 Nothing Nothing
Test/GpsTest.hs view
@@ -1,4 +1,4 @@-import Data.GPS+import Geo.Computations import Data.Time import Data.List import Data.Ord@@ -6,19 +6,9 @@ import Test.QuickCheck import Test.Framework (Test, defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)-import Text.XML.XSD.DateTime import Control.Applicative import Control.Monad -instance Arbitrary LatitudeType where-  arbitrary = liftM (latitudeType . flip mod' 180) arbitrary--instance Arbitrary LongitudeType where-  arbitrary = liftM (longitudeType . flip mod' 180) arbitrary--instance Arbitrary DateTime where-  arbitrary = liftM fromUTCTime arbitrary- instance Arbitrary UTCTime where   arbitrary = UTCTime <$> arbitrary <*> liftM (secondsToDiffTime . abs) (arbitrary :: Gen Integer) @@ -27,53 +17,35 @@  instance Arbitrary NominalDiffTime where   arbitrary = liftM fromIntegral (arbitrary :: Gen Int)-instance Arbitrary WptType where++instance Arbitrary Point where   arbitrary =-    wptType <$> arbitrary -- Lat-            <*> arbitrary -- Lon+    pt      <$> fmap (`mod'` 90) arbitrary -- Lat+            <*> fmap (`mod'` 180) arbitrary -- Lon             <*> arbitrary -- Time             <*> arbitrary -- elevation-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return []           -- LinkType-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing-            <*> return Nothing -newtype Trl = Trl [WptType]+newtype Trl = Trl [Point]   deriving (Show)  instance Arbitrary Trl where   arbitrary = do-    b <- arbitrary :: Gen [Int]-    u_ts_d <- mapM (\i -> (,,) <$> arbitrary <*> replicateM i arbitrary <*> arbitrary) b :: Gen [(UTCTime, [WptType],NominalDiffTime)]-    let u_ts_d' = sortBy (comparing (\(a,_,_) -> a)) u_ts_d-        xs = concat [zipWith (setTime' . fromUTCTime) (iterate (addUTCTime d) u) x | (u,x,d) <- u_ts_d']-    return $ Trl xs+    b <- (`mod` 5) `fmap` arbitrary :: Gen Int+    pnts <- mapM (\_ -> arbitrary) [0..abs b]+    return $ Trl (sortBy (comparing pntTime) pnts) -approxEq :: WptType -> WptType -> Bool+approxEq :: Point -> Point -> Bool approxEq a b = distance a b <= 0.2 -- error of 13cm has been observed due to floating point issues when using add vector. -pSaneDistance :: WptType -> WptType -> Bool+pSaneDistance :: Point -> Point -> Bool pSaneDistance a b = distance a b <= circumferenceOfEarth / 2 -pTriangleTheorem :: WptType -> WptType -> WptType -> Bool+pTriangleTheorem :: Point -> Point -> Point -> Bool pTriangleTheorem a b c =      distance a b + distance b c >= distance a c  -- Traditional flat-surface geometry  || distance a b + distance b c + distance c a == 2 * pi * radiusOfEarth -pAddVector_DistanceHeading_ident :: WptType -> WptType -> Bool+pAddVector_DistanceHeading_ident :: Point -> Point -> Bool pAddVector_DistanceHeading_ident a b =   let v = (distance a b, heading a b)       c = addVector v a@@ -82,7 +54,7 @@ pConvexHull_Has_Extreme_Points :: Trl -> Bool pConvexHull_Has_Extreme_Points (Trl ts) =   let ch = convexHull ts-      ts' = sortBy (comparing lat) ts+      ts' = sortBy (comparing pntLat) ts       northMost = last ts'       southMost = head ts'   in length ts < 3 || (northMost `elem` ch && southMost `elem` ch)@@ -105,9 +77,11 @@     , testProperty "TriangleTheorem" pTriangleTheorem     , testProperty "Vector identity" pAddVector_DistanceHeading_ident     ]-  , testGroup "Trail Computations"-    [ testProperty "Hull has extreme points" pConvexHull_Has_Extreme_Points-    , testProperty "HullContainsBezier" pConvexHull_Bezier_Const]+-- These might make some sense in a local scope, but in a global range what+-- is the "left most" point?  On a sphere what is a convex hull?+--  , testGroup "Trail Computations"+--    [ testProperty "Hull has extreme points" pConvexHull_Has_Extreme_Points+--    , testProperty "HullContainsBezier" pConvexHull_Bezier_Const]   ]  
gps.cabal view
@@ -1,16 +1,16 @@-name:		gps-version:	1.1-license:	BSD3-license-file:	LICENSE-author:		Thomas DuBuisson <thomas.dubuisson@gmail.com>-maintainer:	Thomas DuBuisson-description:	Useful for manipulating GPS coordinages (in various forms), building paths, and performing basic computations.-synopsis:	For manipulating GPS coordinates and trails.-category:	Data-stability:	stable-build-type:	Simple-cabal-version:	>= 1.8-tested-with:	GHC == 6.10.3+name:           gps+version:        1.2+license:        BSD3+license-file:   LICENSE+author:         Thomas DuBuisson <thomas.dubuisson@gmail.com>+maintainer:     Thomas DuBuisson+description:    Useful for manipulating GPS coordinages (in various forms), building paths, and performing basic computations.+synopsis:       For manipulating GPS coordinates and trails.+category:       Data+stability:      stable+build-type:     Simple+cabal-version:  >= 1.8+tested-with:    GHC == 6.10.3 extra-source-files:   Library@@ -18,11 +18,11 @@                  pretty >= 1.0,                  prettyclass >= 1.0,                  time >= 1.4,-                 gpx-conduit >= 0.1,                  vector >= 0.7,-                 statistics >= 0.9+                 statistics >= 0.9,+                 text   hs-source-dirs:-  exposed-modules: Geo.Computations+  exposed-modules: Geo.Computations, Geo.Types   other-modules: Geo.Computations.Basic, Geo.Computations.Trail   ghc-options: -Wall @@ -34,9 +34,9 @@   build-depends:     base >= 4.0,     QuickCheck >= 2.4.0.1,-    test-framework >= 0.3.3 && < 0.5,-    test-framework-quickcheck2 >= 0.2.9 && < 0.3,-    time, GPX, hxt, xsd, vector, statistics, gps+    test-framework >= 0.3.3,+    test-framework-quickcheck2 >= 0.2.9,+    time, vector, statistics, gps, gpx-conduit    ghc-options: -Wall source-repository head