module Data.GPS.KML
(
KML
, trailToKML
, pointsToKML
, kmlToString
) where
import Text.XML.Light
import Data.GPS
type KML = Element
kmlToString :: KML -> String
kmlToString = (++) xml_header . ppElement
kmlTop = Element (QName "kml" Nothing Nothing) [Attr (basicName "xmlns") "http://www.opengis.net/kml/2.2"] [] Nothing
addElem :: Element -> Element -> Element
addElem top child = top { elContent = Elem child : elContent top }
basicName :: String -> QName
basicName n = QName n Nothing Nothing
basicElem :: String -> Element
basicElem n = Element (basicName n) [] [] Nothing
filledElem :: String -> String -> Element
filledElem name val = Element (basicName name) [] [Text (CData CDataText val Nothing)] Nothing
trailToKML :: Coordinate a => String -> Trail a -> KML
trailToKML name ps = addElem kmlTop doc
where
doc = foldl addElem (basicElem "Document") (nameElem : trailElem : [])
nameElem = filledElem "name" name
trailName = filledElem "name" (name ++ " trail")
trailElem = foldl addElem (basicElem "Placemark") [trailName, pointsElem]
pointsElem = addElem (basicElem "LineString") (filledElem "coordinates" points)
points :: String
points = concatMap packCoordinate ps
packCoordinate :: Coordinate a => a -> String
packCoordinate x =
let (lat, lon) = getDegreeLatLon x
in concat [lon, ",", lat, ",0 "]
pointsToKML :: Coordinate a => String -> [a] -> [String] -> KML
pointsToKML name ps pointNames = addElem kmlTop doc
where
doc = foldl addElem (basicElem "Document") (nameElem : placemarkElems)
nameElem = filledElem "name" name
placemarkElems = map buildPoint (zip ps pointNames)
buildPoint (p,n) =
let (t,g) = getDegreeLatLon p
in foldl addElem (basicElem "Placemark")
[ filledElem "name" n
, foldl addElem (basicElem "LookAt")
[ filledElem "longitude" g
, filledElem "latitude" t
, filledElem "altitude" "0"
, filledElem "range" "500"
]
, addElem (basicElem "Point") (filledElem "coordinates" (g ++ "," ++ t))
]
getDegreeLatLon :: Coordinate a => a -> (String,String)
getDegreeLatLon x =
let (lat,lon) = dmsToRadianPair . toDMS $ x
f = show . (*) (180 / pi)
in (f lat, f lon)