packages feed

hgis 1.0.0.1 → 1.0.0.2

raw patch · 21 files changed

+698/−692 lines, 21 filesdep ~base

Dependency ranges changed: base

Files

cabal.project.local view
@@ -1,2 +1,4 @@ constraints: hgis +development +cairo +diagrams optimization: 2++max-backjumps: 120000
+ dbf/Geometry/Shapefile/Internal.hs view
@@ -0,0 +1,67 @@+{-|+Module      : Geometry.Shapefile.Internal+Description : Some functions for reuse inside the library+Author      : Sam van Herwaarden <samvherwaarden@gmail.com>+-}++module Geometry.Shapefile.Internal ( getInt8+                                   , getIntBE+                                   , getInt16BE+                                   , getIntLE+                                   , getInt16LE+                                   , getString+                                   , getPoint+                                   , getCharVal+                                   , getPointList+                                   , steps+                                   , Point+                                   ) where++import           Control.Monad         (replicateM)+import           Data.Binary.Get       hiding (getInt8)+import           Data.Binary.IEEE754   (getFloat64le)+import qualified Data.ByteString.Char8 as ASCII++-- | 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 = fmap (filter (/= '\NUL') . ASCII.unpack) . getByteString++-- | Char (presumably 8-bit)+getCharVal :: Get Char+getCharVal = ASCII.head <$> getByteString 1++type Point = (Double, Double)++-- | Two doubles making up a point with two coordinates+getPoint :: Get Point+getPoint = (,) <$> getFloat64le <*> getFloat64le++-- | 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 = flip replicateM getPoint
+ dbf/Geometry/Shapefile/MergeShpDbf.hs view
@@ -0,0 +1,27 @@+{-|+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 qualified Data.ByteString.Lazy       as BL+import           Geometry.Shapefile.ReadDbf+import           Geometry.Shapefile.ReadShp+import           Geometry.Shapefile.Types+import           System.FilePath++-- | Read a shp-file from `fp`, and a dbf file from the same path but with+--   modified extension.+readShpWithDbf :: FilePath -> IO ShpData+readShpWithDbf fp = do+  shpData <- readShpData <$> BL.readFile fp+  let dbfPath = dropExtension fp <> ".dbf"+  dbfData <- readDbfData <$> BL.readFile dbfPath+  pure shpData { dbfFieldDescs = Just $ dbfFields dbfData+               , shpRecs = zipWith addRecLabel (shpRecs shpData) (dbfRecords dbfData)+               }++addRecLabel :: ShpRec -> [DbfRecord] -> ShpRec+addRecLabel sr labels = sr { shpRecLabel = Just labels } -- FIXME add field name as string
+ dbf/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 :: FilePath -> 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+  pure 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+  pure 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+
+ dbf/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, 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+  pure 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+  pure 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 fmap Just <$> ds+                                     else ds >> pure [Nothing, Nothing]+  [mMin, mMax]             <- let ds = replicateM 2 getFloat64le+                               in if t `elem` mTypes+                                     then fmap Just <$> ds+                                     else ds >> pure [Nothing, Nothing]+  pure 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 pure Nothing+                    else Just <$> getRecContents recType+  pure 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 -> RecPoint <$> getPoint++        ShpPointM -> do+          p <- getPoint+          m <- getFloat64le+          pure RecPointM { pmPoint = p, pmM = m }++        ShpPointZ -> do+          p <- getPoint+          z <- getFloat64le+          m <- getFloat64le+          pure RecPointZ { pzPoint = p, pzZ = z, pzM = m }++        ShpMultiPoint -> do+          (bb, nPoints, points) <- getPointsData+          pure RecMultiPoint { recMPBBox      = bb,+                               recMPNumPoints = nPoints,+                               recMPPoints    = points }++        ShpMultiPointM -> do+          (bb, nPoints, points) <- getPointsData+          (mMin, mMax, ms)      <- getMData nPoints+          pure 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+          pure 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+          pure RecPolyLine { recPolLBBox        = bb,+                             recPolLNumParts    = nParts,+                             recPolLNumPoints   = nPoints,+                             recPolLPartLengths = partLengths,+                             recPolLPoints      = pntLists }++        ShpPolyLineM -> do+          (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+          (mMin, mMax, ms)                             <- getMData nPoints+          pure 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+          pure 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+          pure RecPolygon { recPolBBox        = bb,+                         recPolNumParts    = nParts,+                         recPolNumPoints   = nPoints,+                         recPolPartLengths = partLengths,+                         recPolPoints      = pntLists }++        ShpPolygonM -> do+          (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData+          (mMin, mMax, ms)                             <- getMData nPoints+          pure 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+          pure RecPolygonZ { recPolZBBox        = bb,+                          recPolZNumParts    = nParts,+                          recPolZNumPoints   = nPoints,+                          recPolZPartLengths = partLengths,+                          recPolZPoints      = pntLists,+                          recPolZZRange      = (zMin, zMax),+                          recPolZZs          = zs,+                          recPolZMRange      = (mMin, mMax),+                          recPolZMs          = ms }++        ShpNull ->+          pure 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+  pure (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        <- traverse getPointList partLengths+  pure (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+  pure (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+  pure RecBBox { recXMin = xMin,+              recXMax = xMax,+              recYMin = yMin,+              recYMax = yMax }+
+ dbf/Geometry/Shapefile/Types.hs view
@@ -0,0 +1,217 @@+{-|+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 ( ShpData (..)+                                , ShpHeader (..)+                                , ShpType (..)+                                , zTypes+                                , mTypes+                                , shpTypeFromId+                                , RecBBox (..)+                                , RecContents (..)+                                , ShpRec (..)+                                , ShpBBox (..)+                                , DbfFieldDesc (..)+                                , DbfData (..)+                                , DbfRecord (..)+                                ) where++import qualified Data.ByteString             as BS+import           Geometry.Shapefile.Internal++-- * SHP Types++data ShpData =+  ShpData {+    shpHeader     :: ShpHeader,+    dbfFieldDescs :: Maybe [DbfFieldDesc],+    shpRecs       :: [ShpRec]+  }++data ShpHeader =+  ShpHeader {+    shpFileLength :: Int,+    shpVersion    :: Int,+    shpType       :: ShpType,+    shpBB         :: ShpBBox+  }++data ShpType = ShpNull+             | ShpPoint+             | ShpPolyLine+             | ShpPolygon+             | ShpMultiPoint+             | ShpPointZ+             | ShpPolyLineZ+             | ShpPolygonZ+             | ShpMultiPointZ+             | ShpPointM+             | ShpPolyLineM+             | ShpPolygonM+             | ShpMultiPointM+             | ShpMultiPatch+             deriving (Eq)++-- | 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+  }+++data ShpRec =+  ShpRec {+    shpRecNum      :: Int,+    shpRecLen      :: Int,+    shpRecContents :: Maybe RecContents, -- Can be null type+    shpRecLabel    :: Maybe [DbfRecord], -- Should be usable without dbf+    shpRecType     :: ShpType+  }++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++data RecBBox =+  RecBBox {+    recXMin :: Double,+    recXMax :: Double,+    recYMin :: Double,+    recYMax :: Double+  }++-- * DBF Types++data DbfData =+  DbfData {+    dbfNumRecs :: Int,+    dbfFields  :: [DbfFieldDesc],+    dbfRecords :: [[DbfRecord]]+  }++data DbfFieldDesc =+  DbfFieldDesc {+    fieldName :: String,+    fieldType :: Char,+    fieldLen  :: Int+  }++-- | 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 (Show)
+ dbf/LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Sam van Herwaarden++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
docs/manual.tex view
@@ -32,8 +32,8 @@  \begin{appendices}   \section{Installation}-  HGIS is supported and tested with nix and stack, available from-  \url{http://nixos.org/nix/} and \url{https://haskellstack.org}, respectively.+  HGIS is supported and tested with cabal, available from+  \url{https://www.haskell.org/cabal/}.    % opinionated: nix is best when you just want the binaries!    \section{Using the libaries}
hgis.cabal view
@@ -1,6 +1,6 @@-cabal-version: 1.18+cabal-version: 2.0 name: hgis-version: 1.0.0.1+version: 1.0.0.2 license: BSD3 license-file: LICENSE copyright: Copyright: (c) 2016-2018 Vanessa McHale@@ -17,7 +17,7 @@     cabal.project.local extra-doc-files: README.md                  docs/manual.tex-                 src/depends/readshp/LICENSE+                 dbf/LICENSE  source-repository head     type: darcs@@ -42,23 +42,16 @@         GIS.Math.Projections         GIS.Math.Spherical         GIS.Hylo-    hs-source-dirs: src src/depends/readshp+    hs-source-dirs: src     other-modules:         GIS.Graphics.Types         GIS.Math.Utils         GIS.Utils         GIS.Graphics.Plot         GIS.Types-        Geometry.Shapefile-        Geometry.Shapefile.MergeShpDbf-        Geometry.Shapefile.ReadDbf-        Geometry.Shapefile.ReadShp-        Geometry.Shapefile.Types-        Geometry.Shapefile.Internal     default-language: Haskell2010     default-extensions: DeriveGeneric OverloadedStrings-    other-extensions: RankNTypes TemplateHaskell FlexibleInstances-                      RecordWildCards+    other-extensions: RankNTypes FlexibleInstances RecordWildCards     ghc-options: -Wall -Wincomplete-uni-patterns                  -Wincomplete-record-updates -Wmissing-export-lists     build-depends:@@ -70,11 +63,7 @@         directory -any,         colour -any,         data-default -any,-        binary -any,-        bytestring -any,-        data-binary-ieee754 -any,-        filepath -any,-        monad-loops -any+        hgis-readshp -any          if flag(cairo)         exposed-modules:@@ -94,6 +83,24 @@          if flag(development)         ghc-options: -Werror++library hgis-readshp+    exposed-modules:+        Geometry.Shapefile.Types+        Geometry.Shapefile.MergeShpDbf+        Geometry.Shapefile.ReadShp+    hs-source-dirs: dbf+    other-modules:+        Geometry.Shapefile.ReadDbf+        Geometry.Shapefile.Internal+    default-language: Haskell2010+    build-depends:+        base -any,+        binary -any,+        bytestring -any,+        data-binary-ieee754 -any,+        monad-loops -any,+        filepath -any  test-suite hgis-test     type: exitcode-stdio-1.0
src/GIS/Graphics/Plot.hs view
@@ -13,6 +13,7 @@  import           Control.Arrow import           Data.Colour.Names+import           Data.Foldable                 (fold) import           GIS.Graphics.Types            hiding (title) import           GIS.Math.Utils import           GIS.Types@@ -52,6 +53,6 @@ -- concave. plotLabels :: [([Polygon], String)] -> Plot Double Double plotLabels points = toPlot texts-    where pairs = fmap (flatten . first (shittyCentroid . concat)) points+    where pairs = fmap (flatten . first (shittyCentroid . fold)) points           fontStyle = font_size .~ 15 $ font_weight .~ FontWeightBold $ def           texts = plot_annotation_values .~ pairs $ plot_annotation_style .~ fontStyle $ def
src/GIS/Graphics/Types.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TemplateHaskell #-}- -- | Module for types associated with generating maps. Includes lenses. module GIS.Graphics.Types ( Map (..)                           , projection@@ -19,7 +17,17 @@                , _labelledDistricts :: [([Polygon], String)] -- the data we actually want to map                } -makeLenses ''Map+projection :: Lens' Map Projection+projection f s = fmap (\x -> s { _projection = x }) (f (_projection s))++title :: Lens' Map String+title f s = fmap (\x -> s { _title = x }) (f (_title s))++labelEntities :: Lens' Map Bool+labelEntities f s = fmap (\x -> s { _labelEntities = x }) (f (_labelEntities s))++labelledDistricts :: Lens' Map [([Polygon], String)]+labelledDistricts f s = fmap (\x -> s { _labelledDistricts = x }) (f (_labelledDistricts s))  instance Default Map where     def = Map { _projection = id , _title = mempty , _labelEntities = False , _labelledDistricts = mempty }
src/GIS/Hylo.hs view
@@ -16,6 +16,7 @@  import           Control.Lens                   hiding (lens) import           Data.Default+import           Data.Foldable                  (fold) import           Data.List import           Data.Maybe import           Geometry.Shapefile.MergeShpDbf@@ -30,17 +31,17 @@  -- | Get the areas of various objects and return a string suitable for printing districtArea :: [District] -> String-districtArea districts = concat . intercalate (pure "\n") $ fmap (pure . show . distA) districts+districtArea districts = fold . intercalate (pure "\n") $ fmap (pure . show . distA) districts     where distA (District _ label _ area _) = (label, sum area) -- TODO figure out which one is the correct one  -- | Get the perimeters of various objects and return a string suitable for printing districtPerimeter :: [District] -> String-districtPerimeter districts = concat . intercalate (pure "\n") $ fmap (pure . show . distP) districts+districtPerimeter districts = fold . intercalate (pure "\n") $ fmap (pure . show . distP) districts     where distP (District _ label perimeter _ _) = (label, perimeter)  -- | Label with relative compactness districtCompactness :: [District] -> String-districtCompactness districts = concat . intercalate (pure "\n") $ fmap (pure . show . distC) districts+districtCompactness districts = fold . intercalate (pure "\n") $ fmap (pure . show . distC) districts     where distC (District _ label _ _ compacticity) = (label, compacticity)  -- | Given a projection and lists of districts, draw a map.@@ -80,12 +81,12 @@             shapes = extract id             perimeters = extract totalPerimeter             areas = extract (fmap areaPolygon)-            compacticity = extract (relativeCompactness . concat)+            compacticity = extract (relativeCompactness . fold)         pure $ zipWith5 District shapes districtLabels perimeters areas compacticity  -- | Helper function for extracting from shapefiles. getPolygon :: RecContents -> [Polygon]-getPolygon RecPolygon {..} = recPolPoints+getPolygon RecPolygon {..}  = recPolPoints getPolygon RecPolygonM {..} = recPolMPoints getPolygon RecPolygonZ {..} = recPolZPoints-getPolygon _ = error "shapefile contents not supported. please ensure the shapefile contains a list of polygons."+getPolygon _                = error "shapefile contents not supported. please ensure the shapefile contains a list of polygons."
src/GIS/Math/Spherical.hs view
@@ -57,7 +57,7 @@ perimeterPolygon :: Polygon -> Double perimeterPolygon [x1, x2]       = distance x1 x2 perimeterPolygon (x1:x2:points) = perimeterPolygon (x2:points) + distance x1 x2-perimeterPolygon _ = error "Attempted to take area of polygon with no points"+perimeterPolygon _              = error "Attempted to take area of polygon with no points"  -- | Find the area of a polygon with rectangular coördinates given. This -- function will error if given a polygon with no points.@@ -67,10 +67,10 @@ areaPolyRectangular _ = error "Attempted to take area of polygon with no points"  -- | Distance in kilometers between two points given in degrees.-distance :: (Double, Double) -> (Double, Double) -> Double+distance :: Point -> Point -> Double distance = (*6371) .* on centralAngle toRadians  -- | Compute central angle from points given in radians-centralAngle :: (Double, Double) -> (Double, Double) -> Double+centralAngle :: Point -> Point -> Double centralAngle (long1, lat1) (long2, lat2) =     acos $ sin lat1 * sin lat2 + cos lat1 * cos lat2 * cos (long1 - long2)
src/GIS/Types.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TemplateHaskell   #-}  -- | Module containing types for various geometrical objects. Lenses included. module GIS.Types ( -- * Types@@ -19,7 +18,7 @@  type Point = (Double, Double) type Polygon = [Point]-type Projection = (Double, Double) -> (Double, Double)+type Projection = Point -> Point  -- | Data type for one record in a shape file, also capable of storing basic -- information about the district.@@ -30,7 +29,11 @@                          , _compactness   :: Double                          } deriving (Generic, Show) -makeLensesFor [("_districtLabel", "districtLabel"), ("_area", "area")] ''District+districtLabel :: Lens' District String+districtLabel f s = fmap (\x -> s { _districtLabel = x }) (f (_districtLabel s))++area :: Lens' District [Double]+area f s = fmap (\x -> s { _area = x }) (f (_area s))  data DbfReadError = NotAPolygon | ShpNull 
− src/depends/readshp/Geometry/Shapefile.hs
@@ -1,16 +0,0 @@-{-|-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
@@ -1,67 +0,0 @@-{-|-Module      : Geometry.Shapefile.Internal-Description : Some functions for reuse inside the library-Author      : Sam van Herwaarden <samvherwaarden@gmail.com>--}--module Geometry.Shapefile.Internal ( getInt8-                                   , getIntBE-                                   , getInt16BE-                                   , getIntLE-                                   , getInt16LE-                                   , getString-                                   , getPoint-                                   , getCharVal-                                   , getPointList-                                   , steps-                                   , Point-                                   ) where--import           Control.Monad         (replicateM)-import           Data.Binary.Get hiding (getInt8)-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 = (,) <$> getFloat64le <*> getFloat64le---- | 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
@@ -1,28 +0,0 @@-{-|-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 qualified Data.ByteString.Lazy       as BL-import           Geometry.Shapefile.ReadDbf-import           Geometry.Shapefile.ReadShp-import           Geometry.Shapefile.Types-import           System.FilePath---- | 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-  pure shpData {-      dbfFieldDescs = Just $ dbfFields dbfData,-      shpRecs = zipWith addRecLabel (shpRecs shpData) (dbfRecords dbfData)-    }--addRecLabel :: ShpRec -> [DbfRecord] -> ShpRec-addRecLabel sr labels = sr { shpRecLabel = Just labels } -- FIXME add field name as string
− src/depends/readshp/Geometry/Shapefile/ReadDbf.hs
@@ -1,63 +0,0 @@-{-|-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-  pure 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-  pure 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
@@ -1,243 +0,0 @@-{-|-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, 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-  pure 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-  pure 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 fmap Just <$> ds-                                     else ds >> pure [Nothing, Nothing]-  [mMin, mMax]             <- let ds = replicateM 2 getFloat64le-                               in if t `elem` mTypes-                                     then fmap Just <$> ds-                                     else ds >> pure [Nothing, Nothing]-  pure 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 pure Nothing-                    else Just <$> getRecContents recType-  pure 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 -> RecPoint <$> getPoint--        ShpPointM -> do-          p <- getPoint-          m <- getFloat64le-          pure RecPointM { pmPoint = p, pmM = m }--        ShpPointZ -> do-          p <- getPoint-          z <- getFloat64le-          m <- getFloat64le-          pure RecPointZ { pzPoint = p, pzZ = z, pzM = m }--        ShpMultiPoint -> do-          (bb, nPoints, points) <- getPointsData-          pure RecMultiPoint { recMPBBox      = bb,-                               recMPNumPoints = nPoints,-                               recMPPoints    = points }--        ShpMultiPointM -> do-          (bb, nPoints, points) <- getPointsData-          (mMin, mMax, ms)      <- getMData nPoints-          pure 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-          pure 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-          pure RecPolyLine { recPolLBBox        = bb,-                             recPolLNumParts    = nParts,-                             recPolLNumPoints   = nPoints,-                             recPolLPartLengths = partLengths,-                             recPolLPoints      = pntLists }--        ShpPolyLineM -> do-          (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData-          (mMin, mMax, ms)                             <- getMData nPoints-          pure 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-          pure 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-          pure RecPolygon { recPolBBox        = bb,-                         recPolNumParts    = nParts,-                         recPolNumPoints   = nPoints,-                         recPolPartLengths = partLengths,-                         recPolPoints      = pntLists }--        ShpPolygonM -> do-          (bb, nParts, nPoints, partLengths, pntLists) <- getPolyData-          (mMin, mMax, ms)                             <- getMData nPoints-          pure 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-          pure RecPolygonZ { recPolZBBox        = bb,-                          recPolZNumParts    = nParts,-                          recPolZNumPoints   = nPoints,-                          recPolZPartLengths = partLengths,-                          recPolZPoints      = pntLists,-                          recPolZZRange      = (zMin, zMax),-                          recPolZZs          = zs,-                          recPolZMRange      = (mMin, mMax),-                          recPolZMs          = ms }--        ShpNull ->-          pure 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-  pure (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-  pure (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-  pure (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-  pure RecBBox { recXMin = xMin,-              recXMax = xMax,-              recYMin = yMin,-              recYMax = yMax }-
− src/depends/readshp/Geometry/Shapefile/Types.hs
@@ -1,220 +0,0 @@-{-|-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 ( ShpData (..)-                                , ShpHeader (..)-                                , ShpType (..)-                                , zTypes-                                , mTypes-                                , shpTypeFromId-                                , RecBBox (..)-                                , RecContents (..)-                                , ShpRec (..)-                                , ShpBBox (..)-                                , DbfFieldDesc (..)-                                , DbfData (..)-                                , DbfRecord (..)-                                ) 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)-
− src/depends/readshp/LICENSE
@@ -1,20 +0,0 @@-Copyright (c) 2015 Sam van Herwaarden--Permission is hereby granted, free of charge, to any person obtaining-a copy of this software and associated documentation files (the-"Software"), to deal in the Software without restriction, including-without limitation the rights to use, copy, modify, merge, publish,-distribute, sublicense, and/or sell copies of the Software, and to-permit persons to whom the Software is furnished to do so, subject to-the following conditions:--The above copyright notice and this permission notice shall be included-in all copies or substantial portions of the Software.--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.