module Data.Geo.Route.Waypoint( Waypoint , Waypoints , HasWaypoint(..) , HasWaypoints(..) , HasDateTimes(..) , mkWaypoint , gpxWaypoint , (.<.>) , (~<.>) , (<%>) , (<.?>) , (-.-) ) where import Prelude(Show(show), Double) import Control.Applicative((<$>)) import Data.Eq(Eq) import Data.Foldable(Foldable(foldMap)) import Data.Function(id, (.)) import Data.Functor(Functor(fmap)) import Data.Maybe(Maybe(Nothing, Just)) import Data.Ord(Ord) import Data.String(String) import Data.Traversable(traverse) import Control.Lens(Lens', Traversal', lens, (#), (^.), over, firstOf, set) import Data.Geo.Coordinate.Latitude(HasLatitude(latitude), fracLatitude) import Data.Geo.Coordinate.Longitude(HasLongitude(longitude), fracLongitude) import Data.Geo.Coordinate.Coordinate(Coordinate, HasCoordinate(coordinate), (..#..)) import Data.Geo.Route.Comment(Comment, HasComments(comments), commentIso) import Data.Geo.Route.Description(Description, HasDescriptions(descriptions), descriptionIso) import Data.Geo.Route.Elevation(Elevation, HasElevations(elevations)) import Data.Geo.Route.Gpx(Gpx(gpx)) import Data.Geo.Route.Name(Name, HasNames(names), nameIso) import Data.Geo.Route.Symbol(Symbol, HasSymbols(symbols)) import Text.Printf(printf) import Text.XML.XSD.DateTime(DateTime) data Waypoint = Waypoint Coordinate (Maybe Elevation) (Maybe DateTime) (Maybe Name) (Maybe Comment) (Maybe Description) (Maybe Symbol) deriving (Eq, Ord, Show) type Waypoints = [Waypoint] mkWaypoint :: HasCoordinate c => c -> Waypoint mkWaypoint c = Waypoint (c ^. coordinate) Nothing Nothing Nothing Nothing Nothing Nothing instance HasCoordinate Waypoint where coordinate = lens (\(Waypoint c _ _ _ _ _ _) -> c) (\(Waypoint _ e d n m s y) c -> Waypoint c e d n m s y) instance HasLatitude Waypoint where latitude = coordinate . latitude instance HasLongitude Waypoint where longitude = coordinate . longitude instance HasElevations Waypoint where elevations f (Waypoint c e d n m s y) = (\e' -> Waypoint c e' d n m s y) <$> traverse f e class HasDateTimes t where dateTimes :: Traversal' t DateTime instance HasDateTimes DateTime where dateTimes = id instance HasDateTimes Waypoint where dateTimes f (Waypoint c e d n m s y) = (\d' -> Waypoint c e d' n m s y) <$> traverse f d (<%>) :: HasDateTimes t => DateTime -> t -> t (<%>) = set dateTimes infixr 5 <%> instance HasNames Waypoint where names f (Waypoint c e d n m s y) = (\n' -> Waypoint c e d n' m s y) <$> traverse f n instance HasComments Waypoint where comments f (Waypoint c e d n m s y) = (\m' -> Waypoint c e d n m' s y) <$> traverse f m instance HasDescriptions Waypoint where descriptions f (Waypoint c e d n m s y) = (\s' -> Waypoint c e d n m s' y) <$> traverse f s instance HasSymbols Waypoint where symbols f (Waypoint c e d n m s y) = Waypoint c e d n m s <$> traverse f y class HasWaypoint t where waypoint :: Lens' t Waypoint instance HasWaypoint Waypoint where waypoint = id class HasWaypoints t where waypoints :: Lens' t Waypoints gpxWaypoint :: (HasNames s, HasComments s, HasSymbols s, HasElevations s, HasDescriptions s, HasLatitude s, HasLongitude s,HasDateTimes s) => String -> s -> String gpxWaypoint element w = let lat = fracLatitude # (w ^. latitude) lon = fracLongitude # (w ^. longitude) e = firstOf elevations w d = firstOf dateTimes w n = firstOf names w m = firstOf comments w s = firstOf descriptions w y = firstOf symbols w gpx' :: (Foldable t, Gpx a) => t a -> String gpx' = foldMap gpx in printf "<%s lat=\"%0.6f\" lon=\"%0.6f\">%s%s%s%s%s%s" element lat lon (gpx' e) (gpx' d) (gpx' n) (gpx' m) (gpx' s) (gpx' y) element instance Gpx Waypoint where gpx = gpxWaypoint "wpt" (.<.>) :: String -> Coordinate -> Waypoint s .<.> c = let ups i = Just (s ^. i) in Waypoint c Nothing Nothing (ups nameIso) (ups commentIso) (ups descriptionIso) Nothing infixr 5 .<.> (~<.>) :: Name -> Coordinate -> Waypoint n ~<.> c = Waypoint c Nothing Nothing (Just n) Nothing Nothing Nothing infixr 5 ~<.> (<.?>) :: Double -> Double -> Maybe Waypoint x <.?> y = fmap mkWaypoint (x ..#.. y) infixr 6 <.?> (-.-) :: HasWaypoints t => Maybe Waypoint -> t -> t (-.-) Nothing = id (-.-) (Just w) = over waypoints (w:) infixr 6 -.-