packages feed

hgis 0.1.3.8 → 1.0.0.0

raw patch · 14 files changed

+120/−274 lines, 14 filesdep −optparse-applicativedep ~basePVP ok

version bump matches the API change (PVP)

Dependencies removed: optparse-applicative

Dependency ranges changed: base

API changes (from Hackage documentation)

- GIS.Exe.Opt: exec :: IO ()
- GIS.Exe.Opt: makeFoldersSVG :: [Map] -> IO ()
- GIS.Exe.Opt: pick :: Program -> IO ()
- GIS.Exe.OptCairo: Program :: Command -> FilePath -> Program
- GIS.Exe.OptCairo: [com] :: Program -> Command
- GIS.Exe.OptCairo: [file] :: Program -> FilePath
- GIS.Exe.OptCairo: data Program
- GIS.Exe.OptCairo: exec :: IO ()
- GIS.Math.Spherical: areaPolyRectangular :: Polygon -> Double
- GIS.Math.Spherical: avg :: (RealFrac a, Foldable t) => t a -> a
- GIS.Math.Spherical: centralAngle :: (Double, Double) -> (Double, Double) -> Double
- GIS.Math.Spherical: compactness1 :: Polygon -> Double
- GIS.Math.Spherical: shittyCentroid :: Polygon -> Point

Files

− app/MainPng.hs
@@ -1,6 +0,0 @@-module Main where--import GIS.Exe.OptCairo--main :: IO ()-main = exec
cabal.project.local view
@@ -1,4 +1,4 @@-constraints: hgis +development+constraints: hgis +development +cairo with-compiler: ghc-8.2.2 optimization: 2 documentation: true
hgis.cabal view
@@ -1,14 +1,14 @@ cabal-version: 1.18 name: hgis-version: 0.1.3.8+version: 1.0.0.0 license: BSD3 license-file: LICENSE copyright: Copyright: (c) 2016-2018 Vanessa McHale maintainer: vamchale@gmail.com author: Vanessa McHale-synopsis: Package and command-line for GIS with Haskell+synopsis: Library and for GIS with Haskell description:-    Package containting functions to make graphs, read+    Package containing functions to make graphs, read     shapefiles, and compute areas/perimeters of     geographic features. category: Web@@ -21,13 +21,8 @@                  src/depends/readshp/LICENSE  source-repository head-    type: git-    location: https://github.com/vmchale/hgis--flag llvm-fast-    description:-        Enable build with llvm backend-    default: False+    type: darcs+    location: https://hub.darcs.net/vmchale/hgis  flag development     description:@@ -35,23 +30,24 @@     default: False     manual: True +flag cairo+    description:+        Enable build using cairo backend, allowing generation of PNGs+    default: True+ library     exposed-modules:-        GIS.Exe.Opt-        GIS.Exe.OptCairo+        GIS.Math.Projections         GIS.Math.Spherical-        GIS.Graphics.PlotPNG-        GIS.Graphics.PlotSVG         GIS.Hylo-        GIS.Math.Projections+        GIS.Graphics.PlotSVG     hs-source-dirs: src src/depends/readshp     other-modules:+        GIS.Graphics.Types         GIS.Math.Utils         GIS.Utils         GIS.Graphics.Plot-        GIS.Graphics.Types         GIS.Types-        GIS.Exe.Parser         Geometry.Shapefile         Geometry.Shapefile.MergeShpDbf         Geometry.Shapefile.ReadDbf@@ -63,9 +59,7 @@     ghc-options: -Wall     build-depends:         base >=4.7 && <5,-        optparse-applicative -any,         Chart -any,-        Chart-cairo -any,         Chart-diagrams -any,         lens -any,         composition-prelude >=1.1.0.1,@@ -79,25 +73,13 @@         filepath -any,         monad-loops -any     -    if flag(development)-        ghc-options: -Werror-    -    if impl(ghc >=8.0)-        ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates--executable hgis-    main-is: MainPng.hs-    hs-source-dirs: app-    default-language: Haskell2010-    ghc-options: -Wall-    build-depends:-        base >4.9 && <5,-        hgis -any+    if flag(cairo)+        exposed-modules:+            GIS.Graphics.PlotPNG     -    if flag(llvm-fast)-        ghc-options: -threaded -rtsopts -with-rtsopts=-N -fllvm -optlo-O3-    else-        ghc-options: -threaded -rtsopts -with-rtsopts=-N+    if flag(cairo)+        build-depends:+            Chart-cairo -any          if flag(development)         ghc-options: -Werror
− src/GIS/Exe/Opt.hs
@@ -1,27 +0,0 @@-module GIS.Exe.Opt where--import           Control.Lens-import           Data.Semigroup-import           GIS.Exe.Parser       hiding (projection)-import           GIS.Graphics.PlotSVG-import           GIS.Graphics.Types   hiding (projection)-import           GIS.Hylo-import           Options.Applicative-import           System.Directory--pick :: Program -> IO ()-pick (Program (MapMaker outfile False projection) infile) = let p = pickProjection projection in-    mkMapSVG outfile =<< districtToMapP p <$> getDistricts infile-pick (Program (MapMaker _ True projection) infile) = let p = pickProjection projection in-    makeFoldersSVG =<< districtToMapFilesP p <$> getDistricts infile-pick (Program (MapLabel outfile False projection lensName) infile) = let p = pickProjection projection in-    mkMapSVG outfile =<< districtToMapLensP p (pickLens lensName) <$> getDistricts infile -- FIXME make it work with -a (generate-all)-pick _ = error "not yet implemented."--exec :: IO ()-exec = pick =<< execParser helpDisplay--makeFoldersSVG :: [Map] -> IO ()-makeFoldersSVG maps = do-    createDirectoryIfMissing False "maps"-    mapM_ (\m -> mkMapSVG ("maps/" <> view title m <> ".svg") m) maps
− src/GIS/Exe/OptCairo.hs
@@ -1,43 +0,0 @@--- | This contains the main program executable for the program when built with--- the Cairo libary-module GIS.Exe.OptCairo-    ( -- * Data types-    Program (..)-    -- * Functions-    , exec-    ) where--import           Control.Lens-import           Data.Semigroup-import           GIS.Exe.Parser       hiding (projection)-import           GIS.Graphics.PlotPNG-import           GIS.Graphics.Types   hiding (projection)-import           GIS.Hylo-import           Options.Applicative-import           System.Directory---- | Main executable; parses command line options and runs program-exec :: IO ()-exec = pick =<< execParser helpDisplay---- | Execute the program with parsed command-line input-pick :: Program -> IO ()-pick (Program (MapMaker outfile False projection) infile) = let p = pickProjection projection in-    mkMap outfile =<< districtToMapP p <$> getDistricts infile -- svg now idk?-pick (Program (MapMaker _ True projection) infile) = let p = pickProjection projection in-    makeFoldersPng =<< districtToMapFilesP p <$> getDistricts infile -- TODO fix this-pick (Program (Computation comp Nothing) infile) = --slightly wrong but eh.-    case comp of-        "perimeter" -> putStrLn =<< districtPerimeter <$> getDistricts infile-        "area" -> putStrLn =<< districtArea <$> getDistricts infile-        "compactness" -> putStrLn =<< districtCompactness <$> getDistricts infile-        _ -> putStrLn "computation not recognized"-pick (Program (MapLabel outfile False _ lensName) infile) =-    mkLensMap "" outfile (pickLens lensName) =<< getDistricts infile -- FIXME make it work with -a (generate-all) and make it not bind things together??-pick _ = error "not yet supported."---- | Make maps as png files.-makeFoldersPng :: [Map] -> IO ()-makeFoldersPng maps = do-    createDirectoryIfMissing False "maps"-    mapM_ (\m -> mkMapPng ("maps/" <> view title m <> ".png") m) maps
− src/GIS/Exe/Parser.hs
@@ -1,107 +0,0 @@-{-# LANGUAGE RankNTypes #-}--- | This module contains the parser for the command-line options-module GIS.Exe.Parser where--import           Control.Lens         hiding (argument)-import           Data.Monoid-import           GIS.Math.Projections-import           GIS.Types-import           Options.Applicative---- | Data type for one run of the program-data Program = Program { com  :: Command-                       , file :: FilePath -- "Path to dbf file"-                       }---- | Data type for the appropriate subcommand-data Command = Computation { computation :: String , outputM :: Maybe FilePath }-    | MapMaker { output :: FilePath , generateAll :: Bool , projection :: Maybe String }-    | MapLabel { output :: FilePath , generateAll :: Bool , projection :: Maybe String , computatation :: String }---- | Parses the `Program` data type-program :: Parser Program-program = Program-    <$> hsubparser-        ( command "compute" (info computationP ( progDesc "Compute perimeter, area, etc. of map" ))-        <> command "map" (info mapMaker ( progDesc "Make a map from a shapefile database." ))-        <> command "labelmap" (info mapLabelMaker ( progDesc "Make a map from a shapefile database, and label areas with relevant info" )))-    <*> argument str-            (metavar "SHAPEFILE"-            <> help "Path to .shp file"-            <> completer (bashCompleter "file -X '!*.shp' -o plusdirs"))---- | Parses the `Command` datatype into a Computation-computationP :: Parser Command-computationP = Computation-    <$> argument str-        ( metavar "COMPUTATION"-        <> help "which computation to perform, e.g. area, perimeter, etc." )-    <*> optional (strOption  -- because it's a maybe filepath-        ( long "output"-        <> short 'o'-        <> metavar "OUTPUT"-        <> help "Where to write output" ))---- | Parses the `Command` datatype into a map-mapLabelMaker :: Parser Command-mapLabelMaker = MapLabel-    <$> strOption-        (long "output"-        <> short 'o'-        <> metavar "OUTPUT"-        <> help "Where to write the image/map" )-    <*> switch-        (long "generate-all"-        <> short 'a'-        <> help "Whether to generate a separate file for each object in the shapefile" )-    <*> optional (strOption-        (long "projection"-        <> short 'p'-        <> help "Which projection to use, e.g. mercator etc."))-    <*> strOption-        (long "label"-        <> short 'p'-        <> help "What aspect to label (area, perimeter, compactness)")---- | Parses the `Command` datatype into a map-mapMaker :: Parser Command-mapMaker = MapMaker-    <$> strOption-        (long "output"-        <> short 'o'-        <> metavar "OUTPUT"-        <> help "Where to write the image/map" )-    <*> switch-        (long "generate-all"-        <> short 'a'-        <> help "Whether to generate a separate file for each object in the shapefile" )-    <*> optional (strOption-        (long "projection"-        <> short 'p'-        <> help "Which projection to use, e.g. mercator etc."))---- | display help if user enters e.g.------ > hgis --help wrongcommand-helpDisplay :: ParserInfo Program-helpDisplay = info ( program <**> helper)-    ( fullDesc-    <> progDesc "GIS for Haskell. Can make maps, compute areas/perimeters for shapefiles."-    <> header "hgis - GIS in Haskell" )--pickLens :: String -> Lens' District Double-pickLens "compactness" = compactness-pickLens "perimeter"   = perimeter-pickLens _             = error "must be one of 'compactness', 'perimeter'"---- | Parse a `Maybe String` into the appropriate `Projection`, doing nothing for--- a `Nothing`-pickProjection :: Maybe String -> Projection-pickProjection s = case s of-    Just "mercator" -> mercator-    Just "bonne"    -> bonne-    Just "albers"   -> albers washingtonDC-    Just "winkel3"  -> winkel3-    Just "littow"   -> littow-    Just _ -> error "unknown projection. try one of 'mercator', 'bonne', 'albers', 'winkel3', or 'littow'"-    Nothing         -> id
src/GIS/Graphics/Plot.hs view
@@ -1,11 +1,13 @@-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE RecordWildCards #-}  -- | Module containing renderable objects and plots for our maps module GIS.Graphics.Plot where +import           Control.Arrow import           Data.Colour.Names import           GIS.Graphics.Types            hiding (title)-import           GIS.Math.Spherical+import           GIS.Math.Utils import           GIS.Types import           GIS.Utils import           Graphics.Rendering.Chart@@ -14,7 +16,9 @@ -- | Given a map, return a `Renderable ()` for use with the -- """Graphics.Rendering.Char""" module. mkMapR :: Map -> Renderable ()-mkMapR Map { _title = tit , _labelEntities = le , _labelledDistricts = points } = if le then mkRenderableLabelled tit points else mkRenderableLabelled tit $ fmap (over _2 (pure "")) points+mkMapR Map{..} = if _labelEntities+    then mkRenderableLabelled _title _labelledDistricts+    else mkRenderableLabelled _title $ second (pure "") <$> _labelledDistricts  mkRenderablePlots :: String -> [Plot Double Double] -> Renderable () mkRenderablePlots title plots = toRenderable $@@ -34,13 +38,13 @@  -- | Set labels via a lens field. labelByLens :: (Show a) => Lens' District a -> [District] -> [([Polygon], String)]-labelByLens lens districts = zip (fmap (view shape) districts) (fmap (show . view lens) districts)+labelByLens lens districts = zip (fmap _shape districts) (fmap (show . view lens) districts)  -- | Helper function to plot labels on a map. The ordinate will be plotted at -- the centroid of the abscissa, which may be outside the polygon if it is -- concave. plotLabels :: [([Polygon], String)] -> Plot Double Double plotLabels points = toPlot texts-    where pairs = fmap (flatten . over _1 (shittyCentroid . concat)) points+    where pairs = fmap (flatten . first (shittyCentroid . concat)) points           fontStyle = font_size .~ 15 $ font_weight .~ FontWeightBold $ def           texts = plot_annotation_values .~ pairs $ plot_annotation_style .~ fontStyle $ def
src/GIS/Hylo.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE RecordWildCards #-}+ -- | Module to transform shapefiles. module GIS.Hylo where @@ -13,7 +15,7 @@ import           GIS.Graphics.Types import           GIS.Math.Projections import           GIS.Math.Spherical-import           GIS.Types                      hiding (area, perimeter)+import           GIS.Types                      hiding (area) import           GIS.Utils import           System.Directory @@ -63,16 +65,18 @@ getDistricts filepath = do         dbfExists <- doesFileExist (stripExt filepath <> ".dbf")         file <- if dbfExists then readShpWithDbf filepath else readShpFile filepath-        let districtLabels = fromJust $ fmap labels $ mapM shpRecLabel . shpRecs $ file -- labels + field descriptions?-        let shapes = fmap (getPolygon . fromJust . shpRecContents) . shpRecs $ file-        let perimeters = fmap (totalPerimeter . getPolygon . fromJust . shpRecContents) . shpRecs $ file-        let areas = fmap (fmap areaPolygon . getPolygon . fromJust . shpRecContents) . shpRecs $ file-        let compacticity = fmap (relativeCompactness . concat . getPolygon . fromJust . shpRecContents) . shpRecs $ file+        -- FIXME throw a real error.+        let extract f = fmap (f . getPolygon . fromJust . shpRecContents) . shpRecs $ file+            districtLabels = fromJust $ fmap labels $ traverse shpRecLabel . shpRecs $ file+            shapes = extract id+            perimeters = extract totalPerimeter+            areas = extract (fmap areaPolygon)+            compacticity = extract (relativeCompactness . concat)         pure $ zipWith5 District shapes districtLabels perimeters areas compacticity  -- | Helper function for extracting from shapefiles. getPolygon :: RecContents -> [Polygon]-getPolygon RecPolygon { recPolPoints = pt }   = pt-getPolygon RecPolygonM { recPolMPoints = pt } = pt-getPolygon RecPolygonZ { recPolZPoints = pt } = pt+getPolygon RecPolygon {..} = recPolPoints+getPolygon RecPolygonM {..} = recPolMPoints+getPolygon RecPolygonZ {..} = recPolZPoints getPolygon _ = error "shapefile contents not supported. please ensure the shapefile contains a list of polygons."
src/GIS/Math/Projections.hs view
@@ -1,18 +1,32 @@ -- | Module containing several useful projections for generating maps.-module GIS.Math.Projections where+module GIS.Math.Projections ( -- * Reference points+                              washingtonDC+                            , mecca+                            -- * Projections+                            , littow+                            , craig+                            , winkel3+                            , mercator+                            , bonne+                            , albers+                            -- * Helper functions+                            , project+                            , projectMap+                            ) where +import           Control.Arrow import           Control.Lens import           GIS.Graphics.Types import           GIS.Math.Utils import           GIS.Types --- | For use as a reference point in certain projections.+-- | For use as a reference point washingtonDC :: Point-washingtonDC = over _2 radians $ over _1 radians (38.9072, -77.0369)+washingtonDC = toRadians (38.9072, -77.0369) --- | For use as a reference point with the Craig retroazimuthal projection+-- | For use as a reference point mecca :: Point-mecca = over _2 radians $ over _1 radians (21.3891, 39.8579)+mecca = toRadians (21.3891, 39.8579)  -- | Littow retroazimuthal + conformal projection littow :: Projection@@ -20,14 +34,14 @@     where referenceLong = radians 0  -- | Craig retroazimuthal projection--- (works on a subset of the world) craig :: Point -> Projection craig referencePoint (long, lat) = (long - referenceLong, y)     where (referenceLong, referenceLat) = referencePoint-          y = if long - referenceLong == 0 then expr else (long - referenceLong)/sin(long - referenceLong) * expr           expr = sin lat * cos (long - referenceLong) - tan referenceLat * cos lat+          y | long - referenceLong == 0 = expr+            | otherwise = (long - referenceLong) / sin (long - referenceLong) * expr --- | Winkel Tripel projection (standard for the National Geographic Society since+-- | Winkel Tripel projection winkel3 :: Projection winkel3 (long, lat) = ((lambda * cos phi1 + (2 * cos lat * sin (lambda/2)/sinc alpha))/2, (lat + sin lat/sinc alpha)/2)     where lambda = long - lambda0@@ -41,7 +55,7 @@     where meridian = radians (-98.5795)  -- | Bonne projection with standard parallel at 45 N and central meridian--- centered at Washington DC+-- centered at Washington DC. bonne :: Projection bonne (long, lat) = (rho * sin e, cot phi1 - rho * cos e)     where rho = cot phi1 + phi1 - lat@@ -50,17 +64,18 @@           meridian = radians (-77.0369) -- central meridian @ dc           cot = (1/) . tan --- | Albers projection for a given reference point. To make it usable you can--- use+-- | Albers projection for a given reference point.+-- -- > ablers washingtonDC albers :: Point -> Projection albers referencePoint (long, lat) = (rho * sin theta, rho' - rho * cos theta)-    where n = (sin phi1 + sin phi2)/2+    where n = (sin phi1 + sin phi2) / 2           theta = n * (long - referenceLong)           c = cos phi1^(2 :: Int) + 2 * n * sin phi1           rho = sqrt (c - 2 * n * sin lat) / n           rho' = sqrt (c - 2 * n * sin referenceLat) / n-          phi1 = radians 20 -- standard parallels @ 20, 50 degrees+          -- standard parallels @ 20, 50 degrees+          phi1 = radians 20           phi2 = radians 50           (referenceLong, referenceLat) = referencePoint @@ -70,4 +85,4 @@  -- | Helper to apply a projection given a `Map`. projectMap :: Projection -> Map -> Map-projectMap p = over labelledDistricts (fmap (over _1  (fmap (project p))))+projectMap p = over labelledDistricts (fmap (first (fmap (project p))))
src/GIS/Math/Spherical.hs view
@@ -1,20 +1,20 @@ -- | Utilities to compute area, perimeterPolygon, etc. on the surface of a sphere.-module GIS.Math.Spherical where+module GIS.Math.Spherical ( areaPolygon+                          , perimeterPolygon+                          , relativeCompactness+                          , totalPerimeter+                          -- * Spherical geometry+                          , areaTriangle+                          , areaConvex+                          -- * Internal functions+                          , distance+                          ) where  import           Control.Composition-import           Control.Lens import           GIS.Math.Projections import           GIS.Math.Utils import           GIS.Types --- | averages the coördinates of a polygon, returning a point.-shittyCentroid :: Polygon -> Point-shittyCentroid poly = (avg $ fmap fst poly, avg $ fmap snd poly)---- | Average over a foldable container-avg :: (RealFrac a, Foldable t) => t a -> a-avg list = sum list / (fromIntegral . length $ list)- -- | Compute the area of a triangle using L'Huillier's formula areaTriangle :: Point -> Point -> Point -> Double areaTriangle x1 x2 x3 = r^(2 :: Int) * e@@ -29,18 +29,18 @@ -- TODO mandelbrot/fractal dimension? -- consider "area of largest circumscribable circle" as well. --- | Relative compactness, i.e. compactness divided by the compactness of a Euclidean circle+-- | Relative compactness. Dimensionless. relativeCompactness :: Polygon -> Double relativeCompactness = (*scale) . compactness1     where scale = 1/4*pi --- | Take the area of the polygon and divide by the perimeter squared. This is a dimensionless measurement.+-- | Take the area of the polygon and divide by the perimeter squared. Dimensionless. compactness1 :: Polygon -> Double compactness1 p = areaPolygon p/perimeterPolygon p^(2 :: Int)  -- | Compute the area of a convex polygon on the surface of a sphere. areaConvex :: Polygon -> Double-areaConvex (base1:base2:pts) = view _1 $ foldr stepArea (0,base2) pts+areaConvex (base1:base2:pts) = fst $ foldr stepArea (0,base2) pts     where stepArea point (sum', base) = (sum' + areaTriangle base1 base point, point) areaConvex _ = error "attempted to take area of polygon with < 3 points" @@ -50,9 +50,9 @@ areaPolygon = (*factor) . areaPolyRectangular . fmap (bonne . toRadians)     where factor = 1717856/4.219690791828533e-2 --- | Given a list of polygons, return the total area.+-- | Given a list of polygons, return the total perimeter. totalPerimeter :: [Polygon] -> Double-totalPerimeter ps = sum $ fmap perimeterPolygon ps+totalPerimeter = sum . fmap perimeterPolygon  perimeterPolygon :: Polygon -> Double perimeterPolygon [x1, x2]       = distance x1 x2
src/GIS/Math/Utils.hs view
@@ -1,9 +1,22 @@ -- | Miscellaneous utils for math-module GIS.Math.Utils where+module GIS.Math.Utils ( radians+                      , toRadians+                      , sinc+                      , avg+                      , shittyCentroid+                      ) where -import           Control.Lens+import           Control.Composition import           GIS.Types +-- | Averages the coördinates of a polygon, returning a point.+shittyCentroid :: Polygon -> Point+shittyCentroid poly = (avg $ fmap fst poly, avg $ fmap snd poly)++-- | Average over a foldable container+avg :: (RealFrac a, Foldable t) => t a -> a+avg list = sum list / (fromIntegral . length $ list)+ sinc :: Floating a => a -> a sinc x = sin x / x @@ -13,4 +26,4 @@  -- | Convert both coördinates to radians. toRadians :: Point -> Point-toRadians = over _1 radians . over _2 radians+toRadians = both radians
src/GIS/Types.hs view
@@ -2,7 +2,16 @@ {-# LANGUAGE TemplateHaskell   #-}  -- | Module containing types for various geometrical objects. Lenses included.-module GIS.Types where+module GIS.Types ( -- * Types+                   Point+                 , Polygon+                 , Projection+                 , District (..)+                 , DbfReadError (..)+                 -- * Lenses+                 , districtLabel+                 , area+                 ) where  import           Control.Lens import           GHC.Generics@@ -21,7 +30,7 @@                          , _compactness   :: Double                          } deriving (Generic, Show) -makeLenses ''District+makeLensesFor [("_districtLabel", "districtLabel"), ("_area", "area")] ''District  data DbfReadError = NotAPolygon | ShpNull 
stack.yaml view
@@ -1,5 +1,5 @@ ----resolver: lts-11.3+resolver: lts-11.6 extra-deps:   - Chart-diagrams-1.8.3   - composition-prelude-1.3.0.8
test/Spec.hs view
@@ -1,3 +1,5 @@+module Main (main) where+ import           GIS.Graphics.PlotPNG import           GIS.Graphics.PlotSVG import           GIS.Hylo@@ -9,10 +11,10 @@ main = hspec $ do     describe "distance" $         it "computes distances along geodesics" $-        distance (-74.0059, 40.7128) (-118.2347, 34.0522) `shouldBe` 3934.997673163554+            distance (-74.0059, 40.7128) (-118.2347, 34.0522) `shouldBe` 3934.997673163554     describe "mercatorFullPng" $         it "Reads a map and writes a .png with the mercator projection" $-        (mkMapPng "test/testmap.png" =<< districtToMapP bonne <$> getDistricts "test/data/worldmap/TM_WORLD_BORDERS-0.3.shp") >>= (`shouldBe` ())+            (mkMapPng "test/testmap.png" =<< districtToMapP bonne <$> getDistricts "test/data/worldmap/TM_WORLD_BORDERS-0.3.shp") >>= (`shouldBe` ())     describe "mercatorFullSVG" $         it "Reads a map and writes a .svg with the mercator projection" $-        (mkMapSVG "test/testmap.svg" =<< districtToMapP bonne <$> getDistricts "test/data/worldmap/TM_WORLD_BORDERS-0.3.shp") >>= (`shouldBe` ())+            (mkMapSVG "test/testmap.svg" =<< districtToMapP bonne <$> getDistricts "test/data/worldmap/TM_WORLD_BORDERS-0.3.shp") >>= (`shouldBe` ())