module Data.Internal.Wkt.Line ( line , lineString , multiLineString , emptyLine , emptyMultiLine , commandPoint ) where import Control.Applicative ((<|>)) import qualified Data.Geospatial as Geospatial import qualified Data.LineString as LineString import qualified Data.Sequence as Sequence import qualified Text.Trifecta as Trifecta import qualified Data.Internal.Wkt.Common as Wkt import qualified Data.Internal.Wkt.Point as Point lineString :: Trifecta.Parser Geospatial.GeoLine lineString = do _ <- Trifecta.string "linestring" _ <- Trifecta.spaces (Trifecta.string "empty" >> pure emptyLine) <|> nonEmptyLines nonEmptyLines :: Trifecta.Parser Geospatial.GeoLine nonEmptyLines = (Trifecta.string "zm" >> Geospatial.GeoLine <$> line Point.justPointsXYZM) <|> (Trifecta.string "z" >> Geospatial.GeoLine <$> line Point.justPointsXYZ) <|> Geospatial.GeoLine <$> line Point.justPointsXY multiLineString :: Trifecta.Parser Geospatial.GeoMultiLine multiLineString = do _ <- Trifecta.string "multilinestring" _ <- Trifecta.spaces x <- Wkt.emptySet <|> nonEmptyMultiLines pure $ Geospatial.GeoMultiLine x nonEmptyMultiLines :: Trifecta.Parser (Sequence.Seq (LineString.LineString Geospatial.GeoPositionWithoutCRS)) nonEmptyMultiLines = (Trifecta.string "zm" >> manyLines Point.justPointsXYZM) <|> (Trifecta.string "z" >> manyLines Point.justPointsXYZ) <|> manyLines Point.justPointsXY manyLines :: Trifecta.Parser Geospatial.GeoPositionWithoutCRS -> Trifecta.Parser (Sequence.Seq (LineString.LineString Geospatial.GeoPositionWithoutCRS)) manyLines pointParser = do _ <- Trifecta.spaces >> Trifecta.char '(' x <- line pointParser xs <- Trifecta.many (Trifecta.char ',' >> Trifecta.spaces >> line pointParser) _ <- Trifecta.char ')' >> Trifecta.spaces pure $ x Sequence.:<| Sequence.fromList xs line :: Trifecta.Parser Geospatial.GeoPositionWithoutCRS -> Trifecta.Parser (LineString.LineString Geospatial.GeoPositionWithoutCRS) line pointParser = do _ <- Trifecta.spaces >> Trifecta.char '(' >> Trifecta.spaces first <- pointParser second <- commandPoint pointParser rest <- Trifecta.many (commandPoint pointParser) _ <- Trifecta.char ')' >> Trifecta.spaces pure $ LineString.makeLineString first second (Sequence.fromList rest) commandPoint :: Trifecta.Parser Geospatial.GeoPositionWithoutCRS -> Trifecta.Parser Geospatial.GeoPositionWithoutCRS commandPoint pointParser = do _ <- Trifecta.char ',' _ <- Trifecta.spaces pointParser emptyLine :: Geospatial.GeoLine emptyLine = Geospatial.GeoLine $ LineString.makeLineString Geospatial.GeoEmpty Geospatial.GeoEmpty Sequence.empty emptyMultiLine :: Geospatial.GeoMultiLine emptyMultiLine = Geospatial.mergeGeoLines Sequence.empty