-- | ESRI/ArcInfo ASCII Grid file format module ArcGrid ( ArcGrid , ncols , nrows , xllcorner , yllcorner , xllcenter , yllcenter , cellsize , nodata_value , vat , arcGridFromFile , asciiGridParser ) where import Data.Char import Text.Parsec import Text.Parsec.ByteString import Text.ParserCombinators.Parsec.Numeric {- - The ESRI ArcInfo ASCII Grid spec: - http://resources.esri.com/help/9.3/arcgisdesktop/com/gp_toolref/spatial_analyst_tools/esri_ascii_raster_format.htm -} data ArcGrid = ArcGrid { ncols :: Int , nrows :: Int , xllcorner :: Maybe Float , yllcorner :: Maybe Float , xllcenter :: Maybe Float , yllcenter :: Maybe Float , cellsize :: Float , nodata_value :: Maybe Int , vat :: [Int] -- value attribute table } deriving (Show) arcGridFromFile :: String -> IO ArcGrid arcGridFromFile fname = do e <- parseFromFile asciiGridParser fname case e of Left err -> error $ show err Right ag -> return ag -- | Both upper- and lower-case strings wordParser :: String -> Parser () wordParser str = let ucstr = map toUpper str lcstr = map toLower str in do string str <|> string ucstr <|> string lcstr return () -- | Spaces and tabs pvDelimParser :: Parser () pvDelimParser = do many1 (char ' ' <|> char '\t') return () -- | Parameter-value line pvLineParser :: String -> Parser a -> Parser a pvLineParser param vparser = do wordParser param pvDelimParser val <- vparser endOfLine return val -- | Parse (x|y)llcorner xor (x|y)llcenter block. Returns (corner, center) cllParser :: Char -> Parser (Maybe Float, Maybe Float) cllParser c = let cllcorner = c : "llcorner" cllcenter = c : "llcenter" in do -- try "?llcorner" first without consuming the output mbcor <- optionMaybe $ try $ pvLineParser cllcorner floating case mbcor of Just val -> return (Just val, Nothing) Nothing -> do -- read "?llcenter" then val <- pvLineParser cllcenter floating return (Nothing, Just val) -- -- | Parse VAT row -- vatLineParser :: Int -> Parser [Int] -- vatLineParser ncols = do -- skipMany space -- as <- count ncols $ do -- a <- int -- space <|> newline -- return a -- return as vatParser :: Int -> Parser [Int] vatParser n = do as <- count n $ do spaces a <- int space <|> newline return a return as -- | The parser asciiGridParser :: Parser ArcGrid asciiGridParser = do _ncols <- pvLineParser "ncols" decimal _nrows <- pvLineParser "nrows" decimal (_xllcorner, _xllcenter) <- cllParser 'x' (_yllcorner, _yllcenter) <- cllParser 'y' _cellsize <- pvLineParser "cellsize" floating _nodata_value <- optionMaybe $ pvLineParser "NODATA_value" int _vat <- vatParser (_ncols * _nrows) return $ ArcGrid { ncols = _ncols , nrows = _nrows , xllcorner = _xllcorner , yllcorner = _yllcorner , xllcenter = _xllcenter , yllcenter = _yllcenter , cellsize = _cellsize , nodata_value = _nodata_value , vat = _vat }