packages feed

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 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