-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | For manipulating GPS coordinates and trails. -- -- Useful for manipulating GPS coordinages (in various forms), building -- paths, and performing basic computations. @package gps @version 0.9 -- | A basic GPS library with calculations for distance and speed along -- with helper functions for filtering/smoothing trails. All distances -- are in meters and time is in seconds. Speed is thus meters/second module Data.GPS -- | Distances are expressed in meters type Distance = Double -- | Angles are expressed in radians from North. 0 == North pi/2 == West pi -- == South (32)pi == East == - (pi 2) type Heading = Double -- | Speed is hard coded as meters per second type Speed = Double type Vector = (Distance, Heading) type Trail a = [a] -- | Genearlly a circle indicates a known area in which we are searching -- (so a center point and maximum possible distance from that point) type Circle a = (a, Distance) -- | An arc is represented as a circle, starting heading and ending heading type Arc a = (Circle a, Heading, Heading) -- | North is 0 radians north :: Heading -- | South, being 180 degrees from North, is pi. south :: Heading -- | East is 270 degrees (3 pi / 2) east :: Heading -- | West is 90 degrees (pi/2) west :: Heading -- | radius of the earth in meters radiusOfEarth :: Double -- | Circumference of earth (meters) circumferenceOfEarth :: Double -- | Direction two points aim toward (0 = North, pi2 = West, pi = South, -- 3pi2 = East) heading :: (LatL a, LonL a, LatL b, LonL b) => a -> b -> Heading distance :: (LatL a, LonL a, LatL b, LonL b) => a -> b -> Distance -- | Speed in meters per second, only if a Time was recorded for -- each waypoint. speed :: (LatL loc, LonL loc, TimeL loc, LatL b, LonL b, TimeL b) => loc -> b -> Maybe Speed getVector :: (LatL a, LonL a, LatL b, LonL b) => a -> b -> Vector -- | Given a vector and coordinate, computes a new coordinate. Within some -- epsilon it should hold that if -- --
-- dest = addVector (dist,heading) start ---- -- then -- --
-- heading == heading start dest ---- --
-- dist == distance start dest --addVector :: (LatL c, LonL c) => Vector -> c -> c -- | Provides a lat/lon pair of doubles in radians getRadianPair :: (LatL p, LonL p) => p -> (Latitude, Longitude) getDMSPair :: (LatL c, LonL c) => c -> (Latitude, Longitude) -- | divideArea vDist hDist nw se divides an area into a grid of -- equally spaced coordinates within the box drawn by the northwest point -- (nw) and southeast point (se). Because this uses floating point there -- might be a different number of points in some rows (the last might be -- too far east based on a heading from the se point). divideArea :: (LatL c, LonL c) => Distance -> Distance -> c -> c -> [[c]] -- | interpolate c1 c2 w where 0 <= w <= 1 Gives a -- point on the line between c1 and c2 equal to c1 when w == 0 -- (weighted linearly toward c2). interpolate :: (LatL a, LonL a) => a -> a -> Double -> a -- | Compute the points at which two circles intersect (assumes a flat -- plain). If the circles do not intersect or are identical then the -- result is Nothing. circleIntersectionPoints :: (LatL a, LonL a) => (a, Distance) -> (a, Distance) -> Maybe (a, a) -- | Find the area in which all given circles intersect. The resulting area -- is described in terms of the bounding arcs. All cirlces must intersect -- at two points. intersectionArcsOf :: (LatL a, LonL a) => [Circle a] -> [Arc a] maximumDistanceOfArc :: (LatL a, LonL a) => a -> Arc a -> Distance writeGPX :: FilePath -> Trail Wpt -> IO () -- | Reads a GPX file (using the GPX library) by simply concatenating all -- the tracks, segments, and points (trkpts, trksegs, -- trks) into a single Trail. readGPX :: FilePath -> IO (Trail Wpt) readGPXSegments :: FilePath -> IO [Trail Wpt] getUTCTime :: TimeL a => a -> Maybe UTCTime data AvgMethod c -- | Obtain the mean of the considered points AvgMean :: AvgMethod c -- | Obtain the harmonicMean AvgHarmonicMean :: AvgMethod c -- | Obtain the geometricMean AvgGeometricMean :: AvgMethod c -- | Obtain the median of the considered points AvgMedian :: AvgMethod c -- | Compute the speed considering only the given endpoints AvgEndPoints :: AvgMethod c -- | Take the minimum of the speeds from the given methods AvgMinOf :: [AvgMethod c] -> AvgMethod c AvgWith :: ([c] -> Speed) -> AvgMethod c -- | When grouping points, lists of points are either marked as -- Select or NotSelect. data Selected a Select :: a -> Selected a unSelect :: Selected a -> a NotSelect :: a -> Selected a unSelect :: Selected a -> a -- | A PointGrouping is a function that selects segments of a trail. -- -- Grouping point _does not_ result in deleted points. It is always true -- that: -- -- forall g :: PointGrouping c --> concatMap unSelect (g ts) == ts -- -- The purpose of grouping is usually for later processing. Any desire to -- drop points that didn't meet a particular grouping criteria can be -- filled with a composition with filter (or directly via -- filterPoints). type PointGrouping c = Trail c -> [Selected (Trail c)] -- | Given a selection of coordinates, transform the selected coordinates -- in some way (while leaving the non-selected coordinates unaffected). type TransformGrouping c = [Selected (Trail c)] -> [Selected (Trail c)] isSelected :: Selected a -> Bool isNotSelected :: Selected a -> Bool onSelected :: (a -> b) -> (a -> b) -> Selected a -> b selLength :: Selected [a] -> Int -- | Find the total distance traveled totalDistance :: (LatL a, LonL a) => [a] -> Distance totalTime :: TimeL a => Trail a -> NominalDiffTime -- | avgSpeeds n points Average speed using a window of up to -- n seconds and averaging by taking the Median -- (AvgMedian). avgSpeeds :: (LatL a, LonL a, TimeL a) => NominalDiffTime -> Trail a -> [(UTCTime, Speed)] -- | slidingAverageSpeed m n Average speed using a moving window -- of up to n seconds and an AvgMethod of m. slidingAverageSpeed :: (LatL a, LonL a, TimeL a) => AvgMethod a -> NominalDiffTime -> Trail a -> [(UTCTime, Speed)] -- | Returns the closest distance between two trails (or Nothing if a trail -- is empty). Inefficient implementation: O( (n * m) * log (n * m) ) closestDistance :: (LatL a, LonL a) => Trail a -> Trail a -> Maybe Distance -- | Uses Grahams scan to compute the convex hull of the given points. This -- operation requires sorting of the points, so don't try it unless you -- have notably more memory than the list of points will consume. convexHull :: (Eq c, LatL c, LonL c) => [c] -> [c] -- | Construct a bezier curve using the provided trail. Construct a new -- trail by sampling the given bezier curve at the given times. The -- current implementation assumes the times of the input coordinates are -- available and all equal (Ex: all points are 5 seconds apart), the -- results will be poor if this is not the case! bezierCurveAt :: (LatL a, LonL a, TimeL a) => [UTCTime] -> Trail a -> Trail a -- | Interpolate selected points onto a bezier curve. Note this gets -- exponentially more expensive with the length of the segement being -- transformed - it is not advisable to perform this operation on trail -- segements with more than ten points! bezierCurve :: (LatL a, LonL a, TimeL a) => [Selected (Trail a)] -> Trail a -- | Filters out any points that go backward in time (thus must not be -- valid if this is a trail) linearTime :: (LonL a, LatL a, TimeL a) => [a] -> [a] -- | Remove all points that remain NotSelected by the given grouping -- algorithm. filterPoints :: PointGrouping a -> Trail a -> Trail a -- | Groups trail segments into contiguous points within the speed and all -- others outside of the speed. The speed from point p(i) to -- p(i+1) is associated with p(i) (execpt for the first speed value, -- which is associated with both the first and second point) betweenSpeeds :: (LatL a, LonL a, TimeL a) => Double -> Double -> PointGrouping a -- | A rest point means the coordinates remain within a given -- distance for at least a particular amount of time. restLocations :: (LatL a, LonL a, TimeL a) => Distance -> NominalDiffTime -> PointGrouping a -- | chunking points into groups spanning at most the given time interval. spansTime :: (LatL a, LonL a, TimeL a) => NominalDiffTime -> PointGrouping a -- | chunk the trail into groups of N points everyNPoints :: Int -> PointGrouping a -- | intersects the given groupings intersectionOf :: (LatL a, LonL a, TimeL a) => [PointGrouping a] -> PointGrouping a -- | Inverts the selected/nonselected segments invertSelection :: TransformGrouping a -- | firstGrouping f ps only the first segment remains -- Selected, and only if it was already selected by f. firstGrouping :: TransformGrouping a -- | Only the last segment, if any, is selected (note: the current -- implementation is inefficient, using reverse) lastGrouping :: TransformGrouping a -- | Union all the groupings unionOf :: (LatL a, LonL a, TimeL a) => [PointGrouping a] -> PointGrouping a -- | For every selected group, refine the selection using the second -- grouping method. This differs from IntersectionOf by -- restarting the second grouping algorithm at the beginning each group -- selected by the first algorithm. refineGrouping :: PointGrouping a -> TransformGrouping a -- | Intersection binary operator (/\) :: [Selected (Trail a)] -> TransformGrouping a -- | Union binary operator (\/) :: [Selected (Trail a)] -> TransformGrouping a smoothRests :: (LatL a, LonL a, TimeL a) => Trail a -> Trail a smoothSome :: (LatL a, LonL a, TimeL a) => Trail a -> Trail a smoothMore :: (LatL a, LonL a, TimeL a) => Trail a -> Trail a bezierPoint :: (LatL a, LonL a) => [a] -> Double -> a