hgis 0.1.0.0 → 0.1.1.0
raw patch · 9 files changed
+746/−6 lines, 9 filesdep +binarydep +bytestringdep +data-binary-ieee754dep −readshpdep ~hgis
Dependencies added: binary, bytestring, data-binary-ieee754, filepath, monad-loops
Dependencies removed: readshp
Dependency ranges changed: hgis
Files
- docs/manual.tex +41/−0
- hgis.cabal +18/−6
- src/depends/readshp/Geometry/Shapefile.hs +16/−0
- src/depends/readshp/Geometry/Shapefile/Internal.hs +58/−0
- src/depends/readshp/Geometry/Shapefile/MergeShpDbf.hs +30/−0
- src/depends/readshp/Geometry/Shapefile/ReadDbf.hs +63/−0
- src/depends/readshp/Geometry/Shapefile/ReadShp.hs +247/−0
- src/depends/readshp/Geometry/Shapefile/Types.hs +207/−0
- stack.yaml +66/−0
+ docs/manual.tex view
@@ -0,0 +1,41 @@+\documentclass{article}++\usepackage{hyperref}+\usepackage{appendix}++\begin{document}++\title{HGIS - GIS in Haskell}+\author{Vanessa McHale}++\maketitle++\begin{abstract}+This document contains explanations of some of the math behind hgis works. It+also serves as documentation supplemental to haddock, presernting several+examples and sample outputs. +\end{abstract}++\tableofcontents++\section{Parsing a shapefile}++\section{Geometry on a sphere}++Computing perimeters on a sphere is relatively straightforward: ++\subsection{Measuring compactness}++\section{Making maps}++\subsection{Projections}++\begin{appendices}+ \section{Installation}+ HGIS is supported and tested with stack, available from+ \url{https://haskellstack.org}. ++ \section{Using the libaries}+\end{appendices}++\end{document}
hgis.cabal view
@@ -1,5 +1,5 @@ name: hgis-version: 0.1.0.0+version: 0.1.1.0 cabal-version: >=1.10 build-type: Simple license: BSD3@@ -16,6 +16,8 @@ author: Vanessa McHale extra-source-files: README.md+ stack.yaml+ docs/manual.tex source-repository head type: git@@ -32,7 +34,6 @@ GIS.Math.Projections build-depends: base >=4.7 && <5,- readshp >=0.1.0.0 && <0.2, optparse-applicative >=0.13.1.0 && <0.14, Chart >=1.8.2 && <1.9, Chart-cairo >=1.8.2 && <1.9,@@ -43,11 +44,16 @@ transformers >=0.5.2.0 && <0.6, directory >=1.3.0.0 && <1.4, colour >=2.3.3 && <2.4,- data-default >=0.7.1.1 && <0.8+ data-default >=0.7.1.1 && <0.8,+ binary >=0.8.3.0 && <0.9,+ bytestring >=0.10.8.1 && <0.11,+ data-binary-ieee754 >=0.4.4 && <0.5,+ filepath >=1.4.1.1 && <1.5,+ monad-loops >=0.4.3 && <0.5 pkgconfig-depends: cairo >=0.13.3.1 && <0.14 default-language: Haskell2010 default-extensions: DeriveGeneric OverloadedStrings- hs-source-dirs: src+ hs-source-dirs: src src/depends/readshp other-modules: GIS.Math.Utils GIS.Utils@@ -55,12 +61,18 @@ GIS.Graphics.Types GIS.Types GIS.Exe.Parser+ Geometry.Shapefile+ Geometry.Shapefile.MergeShpDbf+ Geometry.Shapefile.ReadDbf+ Geometry.Shapefile.ReadShp+ Geometry.Shapefile.Types+ Geometry.Shapefile.Internal executable hgis main-is: MainPng.hs build-depends: base >=4.9.1.0 && <4.10,- hgis >=0.1.0.0 && <0.2+ hgis >=0.1.1.0 && <0.2 default-language: Haskell2010 hs-source-dirs: app ghc-options: -threaded -rtsopts -with-rtsopts=-N@@ -70,7 +82,7 @@ main-is: Spec.hs build-depends: base >=4.9.1.0 && <4.10,- hgis >=0.1.0.0 && <0.2,+ hgis >=0.1.1.0 && <0.2, hspec >=2.4.2 && <2.5 default-language: Haskell2010 hs-source-dirs: test
+ src/depends/readshp/Geometry/Shapefile.hs view
@@ -0,0 +1,16 @@+{-|+Module : Geometry.Shapefile+Description : Code for reading ESRI shapefiles.+ Developed for intelligence2integrity.+Author : Sam van Herwaarden <samvherwaarden@gmail.com>+-}+module Geometry.Shapefile ( module Geometry.Shapefile.MergeShpDbf,+ module Geometry.Shapefile.ReadDbf,+ module Geometry.Shapefile.ReadShp,+ module Geometry.Shapefile.Types+ ) where++import Geometry.Shapefile.MergeShpDbf+import Geometry.Shapefile.ReadDbf+import Geometry.Shapefile.ReadShp+import Geometry.Shapefile.Types
+ src/depends/readshp/Geometry/Shapefile/Internal.hs view
@@ -0,0 +1,58 @@+{-|+Module : Geometry.Shapefile.Internal+Description : Some functions for reuse inside the library+Author : Sam van Herwaarden <samvherwaarden@gmail.com>+-}++module Geometry.Shapefile.Internal where++import Control.Monad ( replicateM )+import Data.Binary.Get+import Data.Binary.IEEE754 ( getFloat64le )+import qualified Data.ByteString.Char8 as C++-- | 8-bit Int value+getInt8 :: Get Int+getInt8 = fromIntegral <$> getWord8++-- | 32-bit big-endian Int+getIntBE :: Get Int+getIntBE = fromIntegral <$> getWord32be++-- | 16-bit big-endian Int+getInt16BE :: Get Int+getInt16BE = fromIntegral <$> getWord16be++-- | 32-bit little-endian Int+getIntLE :: Get Int+getIntLE = fromIntegral <$> getWord32le++-- | 16-bit little-endian Int+getInt16LE :: Get Int+getInt16LE = fromIntegral <$> getWord16le++-- | String of length `l`+getString :: Int -> Get String+getString l = filter (/= '\NUL') . C.unpack <$> getByteString l++-- | Char (presumably 8-bit)+getCharVal :: Get Char+getCharVal = C.head <$> getByteString 1++type Point = (Double, Double)++-- | Two doubles making up a point with two coordinates+getPoint :: Get Point+getPoint = do x <- getFloat64le+ y <- getFloat64le+ return (x, y)++-- | Get the increments between list values+steps :: Num a => [a] -> [a]+steps [] = []+steps (_:[]) = []+steps (x1:x2:xs) = x2 - x1 : steps (x2:xs)++-- | List of points of length `numPoints`+getPointList :: Int -> Get [Point]+getPointList numPoints = replicateM numPoints getPoint
+ src/depends/readshp/Geometry/Shapefile/MergeShpDbf.hs view
@@ -0,0 +1,30 @@+{-|+Module : Geometry.Shapefile.MergeShpDbf+Description : Code for reading ESRI shapefiles with DBF data+Author : Sam van Herwaarden <samvherwaarden@gmail.com>+-}++module Geometry.Shapefile.MergeShpDbf ( readShpWithDbf ) where++import System.FilePath++import qualified Data.ByteString.Lazy as BL++import Geometry.Shapefile.ReadDbf+import Geometry.Shapefile.ReadShp+import Geometry.Shapefile.Types++-- | Read a shp-file from `fp`, and a dbf file from the same path but with+-- modified extension.+readShpWithDbf :: String -> IO ShpData+readShpWithDbf fp = do+ shpData <- readShpData <$> BL.readFile fp+ let dbfPath = dropExtension fp ++ ".dbf"+ dbfData <- readDbfData <$> BL.readFile dbfPath+ return shpData {+ dbfFieldDescs = Just $ dbfFields dbfData,+ shpRecs = zipWith addRecLabel (shpRecs shpData) (dbfRecords dbfData)+ }++addRecLabel :: ShpRec -> [DbfRecord] -> ShpRec+addRecLabel sr labels = sr { shpRecLabel = Just labels }
+ src/depends/readshp/Geometry/Shapefile/ReadDbf.hs view
@@ -0,0 +1,63 @@+{-|+Module : Geometry.Shapefile.ReadDbf+Description : Code for reading DBF files.+ Not robust, handle with care. YMMV+ Based on http://www.dbf2002.com/dbf-file-format.html+Author : Sam van Herwaarden <samvherwaarden@gmail.com>+-}++module Geometry.Shapefile.ReadDbf ( readDbfFile,+ readDbfData+ ) where++import Control.Monad ( replicateM )+import Control.Monad.Loops ( whileM )+import Data.Binary.Get hiding (getInt8)++import qualified Data.ByteString.Lazy as BL++import Geometry.Shapefile.Internal+import Geometry.Shapefile.Types++-- | Read dbf file at `fp` into resident data format `DbfData`+readDbfFile :: String -> IO DbfData+readDbfFile fp = readDbfData <$> BL.readFile fp++-- | Parse a ByteString containing DBF data+readDbfData :: BL.ByteString -> DbfData+readDbfData = runGet $ do+ _ <- getByteString 4 -- DBF File type+ numRecs <- getIntLE -- Number of records+ firstRecPos <- getInt16LE -- Position of first record+ _ <- getByteString 22 -- Rec len, table flags, code page mark+ -- Field descriptors+ let fieldsRemain = (< firstRecPos - 1) . fromIntegral <$> bytesRead+ fields <- whileM fieldsRemain getDbfFieldDesc+ _ <- getWord8 -- Skip spacer+ -- Records+ recs <- replicateM numRecs (getWord8 >> mapM getDbfRecord fields)+ -- Everything together+ return DbfData { dbfNumRecs = numRecs,+ dbfFields = fields,+ dbfRecords = recs }++-- | Read header field descriptor+getDbfFieldDesc :: Get DbfFieldDesc+getDbfFieldDesc = do+ name <- getString 11 -- Field name+ fieldT <- getCharVal -- Field type+ _ <- getIntLE -- Field displacement (?)+ len <- getInt8 -- Field length+ _ <- getByteString 15 -- Num decimal/field flags/autoincrement+ return DbfFieldDesc { fieldName = name,+ fieldType = fieldT,+ fieldLen = len }++-- | Read a record. Not all record types are (meaningfully) implemented.+getDbfRecord :: DbfFieldDesc -> Get DbfRecord+getDbfRecord field = let n = fieldLen field in+ case fieldType field of+ 'C' -> DbfString <$> getString n+ 'N' -> DbfNum <$> getString n+ _ -> DbfBS <$> getByteString n+
+ src/depends/readshp/Geometry/Shapefile/ReadShp.hs view
@@ -0,0 +1,247 @@+{-|+Module : Geometry.Shapefile.ReadShp+Description : Code for reading the binary ESRI Shapefile format.+ https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf+Author : Sam van Herwaarden <samvherwaarden@gmail.com>+-}++module Geometry.Shapefile.ReadShp ( readShpFile,+ readShpData,+ ) where++import Control.Monad ( replicateM, when )+import Control.Monad.Loops ( whileM )+import Data.Binary.Get+import Data.Binary.IEEE754 ( getFloat64le )++import qualified Data.ByteString.Lazy as BL++import Geometry.Shapefile.Internal+import Geometry.Shapefile.Types++-- | Read shapefile at `fp` to resident data structure `ShpData`+readShpFile :: String -> IO ShpData+readShpFile fp = readShpData <$> BL.readFile fp++-- | Parse a shapefile ByteString+readShpData :: BL.ByteString -> ShpData+readShpData = runGet $ do+ shpH <- getShpHeader+ shpRs <- whileM (not <$> isEmpty) getShpRec+ return ShpData { shpHeader = shpH,+ dbfFieldDescs = Nothing, -- fill using readDbfData+ shpRecs = shpRs }++-- | Header of the shapefile+getShpHeader :: Get ShpHeader+getShpHeader = do+ fc <- getIntBE -- File code+ when (fc /= 9994) (error "getShpHeader: Input file is not a SHP file")+ _ <- replicateM 5 getWord32be -- Unused data+ shpLen <- getIntBE -- File length+ shpV <- getIntLE -- Version (little-endian!)+ shpT <- getShpType -- Shape type+ shpbb <- getShpBBox shpT -- Bounding box+ return ShpHeader { shpFileLength = shpLen,+ shpVersion = shpV,+ shpType = shpT,+ shpBB = shpbb }++-- | Get type of the record(s)+getShpType :: Get ShpType+getShpType = shpTypeFromId <$> getIntLE++-- | Read a bounding box for relevant record type.+-- Not all bounding boxes have Z/M coordinates.+getShpBBox :: ShpType -> Get ShpBBox+getShpBBox t = do+ [xMin, yMin, xMax, yMax] <- replicateM 4 getFloat64le+ [zMin, zMax] <- let ds = replicateM 2 getFloat64le+ in if t `elem` zTypes+ then map Just <$> ds+ else ds >> return [Nothing, Nothing]+ [mMin, mMax] <- let ds = replicateM 2 getFloat64le+ in if t `elem` mTypes+ then map Just <$> ds+ else ds >> return [Nothing, Nothing]+ return ShpBBox { shpXMin = xMin,+ shpXMax = xMax,+ shpYMin = yMin,+ shpYMax = yMax,+ shpZMin = zMin,+ shpZMax = zMax,+ shpMMin = mMin,+ shpMMax = mMax }++-- | Read a single record+getShpRec :: Get ShpRec+getShpRec = do+ recNum <- getIntBE -- Record number+ recLen <- getIntBE -- Record length+ recType <- getShpType -- Shape type+ recContents <- if recType == ShpNull -- Record contents+ then return Nothing+ else Just <$> getRecContents recType+ return ShpRec { shpRecNum = recNum,+ shpRecLen = recLen,+ shpRecContents = recContents,+ shpRecLabel = Nothing,+ shpRecType = recType }++-- | Get record contents for record of given type+getRecContents :: ShpType -> Get RecContents+getRecContents t = case t of++ ShpPoint -> do+ p <- getPoint+ return $ RecPoint p++ ShpPointM -> do+ p <- getPoint+ m <- getFloat64le+ return $ RecPointM { pmPoint = p, pmM = m }++ ShpPointZ -> do+ p <- getPoint+ z <- getFloat64le+ m <- getFloat64le+ return $ RecPointZ { pzPoint = p, pzZ = z, pzM = m }++ ShpMultiPoint -> do+ (bb, nPoints, points) <- getPointsData+ return RecMultiPoint { recMPBBox = bb,+ recMPNumPoints = nPoints,+ recMPPoints = points }++ ShpMultiPointM -> do+ (bb, nPoints, points) <- getPointsData+ (mMin, mMax, ms) <- getMData nPoints+ return RecMultiPointM { recMPMBBox = bb,+ recMPMNumPoints = nPoints,+ recMPMPoints = points,+ recMPMMRange = (mMin, mMax),+ recMPMMs = ms}++ ShpMultiPointZ -> do+ (bb, nPoints, points) <- getPointsData+ (zMin, zMax, zs) <- getZData nPoints+ (mMin, mMax, ms) <- getMData nPoints+ return RecMultiPointZ { recMPZBBox = bb,+ recMPZNumPoints = nPoints,+ recMPZPoints = points,+ recMPZZRange = (zMin, zMax),+ recMPZZs = zs,+ recMPZMRange = (mMin, mMax),+ recMPZMs = ms }++ ShpPolyLine -> do+ (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+ return RecPolyLine { recPolLBBox = bb,+ recPolLNumParts = nParts,+ recPolLNumPoints = nPoints,+ recPolLPartLengths = partLengths,+ recPolLPoints = pntLists }++ ShpPolyLineM -> do+ (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+ (mMin, mMax, ms) <- getMData nPoints+ return RecPolyLineM { recPolLMBBox = bb,+ recPolLMNumParts = nParts,+ recPolLMNumPoints = nPoints,+ recPolLMPartLengths = partLengths,+ recPolLMPoints = pntLists,+ recPolLMMRange = (mMin, mMax),+ recPolLMMs = ms }++ ShpPolyLineZ -> do+ (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+ (zMin, zMax, zs) <- getZData nPoints+ (mMin, mMax, ms) <- getMData nPoints+ return RecPolyLineZ { recPolLZBBox = bb,+ recPolLZNumParts = nParts,+ recPolLZNumPoints = nPoints,+ recPolLZPartLengths = partLengths,+ recPolLZPoints = pntLists,+ recPolLZZRange = (zMin, zMax),+ recPolLZZs = zs,+ recPolLZMRange = (mMin, mMax),+ recPolLZMs = ms }++ ShpPolygon -> do+ (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+ return RecPolygon { recPolBBox = bb,+ recPolNumParts = nParts,+ recPolNumPoints = nPoints,+ recPolPartLengths = partLengths,+ recPolPoints = pntLists }++ ShpPolygonM -> do+ (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+ (mMin, mMax, ms) <- getMData nPoints+ return RecPolygonM { recPolMBBox = bb,+ recPolMNumParts = nParts,+ recPolMNumPoints = nPoints,+ recPolMPartLengths = partLengths,+ recPolMPoints = pntLists,+ recPolMMRange = (mMin, mMax),+ recPolMMs = ms }++ ShpPolygonZ -> do+ (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+ (zMin, zMax, zs) <- getZData nPoints+ (mMin, mMax, ms) <- getMData nPoints+ return RecPolygonZ { recPolZBBox = bb,+ recPolZNumParts = nParts,+ recPolZNumPoints = nPoints,+ recPolZPartLengths = partLengths,+ recPolZPoints = pntLists,+ recPolZZRange = (zMin, zMax),+ recPolZZs = zs,+ recPolZMRange = (mMin, mMax),+ recPolZMs = ms }++ ShpNull ->+ return RecNull++ ShpMultiPatch ->+ error "getShpRec: MultiPatch type is not supported, sorry!"++-- | Recurring pattern of bounding box with a number of points+getPointsData :: Get (RecBBox, Int, [Point])+getPointsData = do+ bb <- getRecBBox+ nPoints <- getIntLE+ points <- replicateM nPoints getPoint+ return (bb, nPoints, points)++-- | Recurring pattern of a bounding box with polygon data+getPolyData :: Get (RecBBox, Int, Int, [Int], [[Point]])+getPolyData = do+ bb <- getRecBBox+ nParts <- getIntLE+ nPoints <- getIntLE+ partIndices <- replicateM nParts getIntLE+ let partLengths = steps $ partIndices ++ [nPoints]+ pntLists <- mapM getPointList partLengths+ return (bb, nParts, nPoints, partLengths, pntLists)++-- | Recurring pattern of M-valued data+getMData :: Int -> Get (Double, Double, [Double])+getMData nPoints = do+ [mMin, mMax] <- replicateM 2 getFloat64le+ ms <- replicateM nPoints getFloat64le+ return (mMin, mMax, ms)++-- | Recurring pattern of Z-valued data (same structure as M-valued data)+getZData :: Int -> Get (Double, Double, [Double])+getZData = getMData++-- | Record bounding boxes contain no information on M/Z+getRecBBox :: Get RecBBox+getRecBBox = do+ [xMin, yMin, xMax, yMax] <- replicateM 4 getFloat64le+ return RecBBox { recXMin = xMin,+ recXMax = xMax,+ recYMin = yMin,+ recYMax = yMax }+
+ src/depends/readshp/Geometry/Shapefile/Types.hs view
@@ -0,0 +1,207 @@+{-|+Module : Geometry.Shapefile.Types+Description : Type definitions used by the library. Currently (24 Nov 2015)+ MultiPatch record types are not implemented. Only Point and+ Polygon are (somewhat) tested. YMMV+ https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf+Author : Sam van Herwaarden <samvherwaarden@gmail.com>+-}++module Geometry.Shapefile.Types where++import qualified Data.ByteString as BS++import Geometry.Shapefile.Internal++-- * SHP Types++data ShpData =+ ShpData {+ shpHeader :: ShpHeader,+ dbfFieldDescs :: Maybe [DbfFieldDesc],+ shpRecs :: [ShpRec]+ } deriving (Eq, Show)++data ShpHeader =+ ShpHeader {+ shpFileLength :: Int,+ shpVersion :: Int,+ shpType :: ShpType,+ shpBB :: ShpBBox+ } deriving (Eq, Show)++data ShpType = ShpNull+ | ShpPoint+ | ShpPolyLine+ | ShpPolygon+ | ShpMultiPoint+ | ShpPointZ+ | ShpPolyLineZ+ | ShpPolygonZ+ | ShpMultiPointZ+ | ShpPointM+ | ShpPolyLineM+ | ShpPolygonM+ | ShpMultiPointM+ | ShpMultiPatch+ deriving (Eq, Show)++-- | Types with Z values+zTypes :: [ShpType]+zTypes = [ShpPointZ, ShpPolyLineZ, ShpPolygonZ, ShpMultiPointZ]++-- | Types with M values+mTypes :: [ShpType]+mTypes = [ShpPointM, ShpPolyLineM, ShpPolygonM, ShpMultiPointM]++-- | Numeric codes used for record types+shpTypeFromId :: Int -> ShpType+shpTypeFromId i =+ case i of 0 -> ShpNull+ 1 -> ShpPoint+ 3 -> ShpPolyLine+ 5 -> ShpPolygon+ 8 -> ShpMultiPoint+ 11 -> ShpPointZ+ 13 -> ShpPolyLineZ+ 15 -> ShpPolygonZ+ 18 -> ShpMultiPointZ+ 21 -> ShpPointM+ 23 -> ShpPolyLineM+ 25 -> ShpPolygonM+ 28 -> ShpMultiPointM+ 31 -> ShpMultiPatch+ _ -> error "shpTypeFromId: Unknown Shape Type"++data ShpBBox =+ ShpBBox {+ shpXMin :: Double,+ shpXMax :: Double,+ shpYMin :: Double,+ shpYMax :: Double,+ shpZMin :: Maybe Double,+ shpZMax :: Maybe Double,+ shpMMin :: Maybe Double,+ shpMMax :: Maybe Double+ } deriving (Eq, Show)+++data ShpRec =+ ShpRec {+ shpRecNum :: Int,+ shpRecLen :: Int,+ shpRecContents :: Maybe RecContents, -- Can be null type+ shpRecLabel :: Maybe [DbfRecord], -- Should be usable without dbf+ shpRecType :: ShpType+ } deriving (Eq, Show)++data RecContents =+ RecNull+ | RecPoint Point+ | RecPointM {+ pmPoint :: Point,+ pmM :: Double }+ | RecPointZ {+ pzPoint :: Point,+ pzZ :: Double,+ pzM :: Double }+ | RecMultiPoint {+ recMPBBox :: RecBBox,+ recMPNumPoints :: Int,+ recMPPoints :: [Point] }+ | RecMultiPointM {+ recMPMBBox :: RecBBox,+ recMPMNumPoints :: Int,+ recMPMPoints :: [Point],+ recMPMMRange :: (Double, Double),+ recMPMMs :: [Double] }+ | RecMultiPointZ {+ recMPZBBox :: RecBBox,+ recMPZNumPoints :: Int,+ recMPZPoints :: [Point],+ recMPZZRange :: (Double, Double),+ recMPZZs :: [Double],+ recMPZMRange :: (Double, Double),+ recMPZMs :: [Double] }+ | RecPolyLine {+ recPolLBBox :: RecBBox,+ recPolLNumParts :: Int,+ recPolLNumPoints :: Int,+ recPolLPartLengths :: [Int],+ recPolLPoints :: [[Point]] }+ | RecPolyLineM {+ recPolLMBBox :: RecBBox,+ recPolLMNumParts :: Int,+ recPolLMNumPoints :: Int,+ recPolLMPartLengths :: [Int],+ recPolLMPoints :: [[Point]],+ recPolLMMRange :: (Double, Double),+ recPolLMMs :: [Double] }+ | RecPolyLineZ {+ recPolLZBBox :: RecBBox,+ recPolLZNumParts :: Int,+ recPolLZNumPoints :: Int,+ recPolLZPartLengths :: [Int],+ recPolLZPoints :: [[Point]],+ recPolLZZRange :: (Double, Double),+ recPolLZZs :: [Double],+ recPolLZMRange :: (Double, Double),+ recPolLZMs :: [Double] }+ | RecPolygon {+ recPolBBox :: RecBBox,+ recPolNumParts :: Int,+ recPolNumPoints :: Int,+ recPolPartLengths :: [Int],+ recPolPoints :: [[Point]] }+ | RecPolygonM {+ recPolMBBox :: RecBBox,+ recPolMNumParts :: Int,+ recPolMNumPoints :: Int,+ recPolMPartLengths :: [Int],+ recPolMPoints :: [[Point]],+ recPolMMRange :: (Double, Double),+ recPolMMs :: [Double] }+ | RecPolygonZ {+ recPolZBBox :: RecBBox,+ recPolZNumParts :: Int,+ recPolZNumPoints :: Int,+ recPolZPartLengths :: [Int],+ recPolZPoints :: [[Point]],+ recPolZZRange :: (Double, Double),+ recPolZZs :: [Double],+ recPolZMRange :: (Double, Double),+ recPolZMs :: [Double] }+ -- RecMultiPatch+ deriving (Eq, Show)++data RecBBox =+ RecBBox {+ recXMin :: Double,+ recXMax :: Double,+ recYMin :: Double,+ recYMax :: Double+ } deriving (Eq, Show)++-- * DBF Types++data DbfData =+ DbfData {+ dbfNumRecs :: Int,+ dbfFields :: [DbfFieldDesc],+ dbfRecords :: [[DbfRecord]]+ } deriving (Eq, Show)++data DbfFieldDesc =+ DbfFieldDesc {+ fieldName :: String,+ fieldType :: Char,+ fieldLen :: Int+ } deriving (Eq, Show)++-- | Not all record types are implemented. Use your favorite method to+-- convert any bytestring (and feel free to add functionality).+data DbfRecord = DbfString String+ | DbfNum String+ | DbfBS BS.ByteString+ deriving (Eq, Show)+
+ stack.yaml view
@@ -0,0 +1,66 @@+# This file was automatically generated by 'stack init'+#+# Some commonly used options have been documented as comments in this file.+# For advanced use and comprehensive documentation of the format, please see:+# http://docs.haskellstack.org/en/stable/yaml_configuration/++# Resolver to choose a 'specific' stackage snapshot or a compiler version.+# A snapshot resolver dictates the compiler version and the set of packages+# to be used for project dependencies. For example:+#+# resolver: lts-3.5+# resolver: nightly-2015-09-21+# resolver: ghc-7.10.2+# resolver: ghcjs-0.1.0_ghc-7.10.2+# resolver:+# name: custom-snapshot+# location: "./custom-snapshot.yaml"+resolver: lts-8.3++# User packages to be built.+# Various formats can be used as shown in the example below.+#+# packages:+# - some-directory+# - https://example.com/foo/bar/baz-0.0.2.tar.gz+# - location:+# git: https://github.com/commercialhaskell/stack.git+# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a+# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a+# extra-dep: true+# subdirs:+# - auto-update+# - wai+#+# A package marked 'extra-dep: true' will only be built if demanded by a+# non-dependency (i.e. a user package), and its test suites and benchmarks+# will not be run. This is useful for tweaking upstream packages.+packages:+- '.'+# Dependency packages to be pulled from upstream that are not in the resolver+# (e.g., acme-missiles-0.3)+extra-deps: []++# Override default flag values for local packages and extra-deps+flags: {}++# Extra package databases containing global packages+extra-package-dbs: []++# Control whether we use the GHC we find on the path+# system-ghc: true+#+# Require a specific version of stack, using version ranges+# require-stack-version: -any # Default+# require-stack-version: ">=1.4"+#+# Override the architecture used by stack, especially useful on Windows+# arch: i386+# arch: x86_64+#+# Extra directories used by stack for building+# extra-include-dirs: [/path/to/dir]+# extra-lib-dirs: [/path/to/dir]+#+# Allow a newer minor version of GHC than the snapshot specifies+# compiler-check: newer-minor