packages feed

hgeos 0.1.7.4 → 0.1.8.0

raw patch · 7 files changed

+270/−428 lines, 7 filesdep −mtldep −transformersPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: mtl, transformers

API changes (from Hackage documentation)

- Data.Geolocation.GEOS.Trans: areaM :: Geometry -> MaybeT IO Double
- Data.Geolocation.GEOS.Trans: createCollectionM :: GeometryType -> [Geometry] -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: createCoordSeqM :: Context -> Word -> Word -> MaybeT IO CoordinateSequence
- Data.Geolocation.GEOS.Trans: createEmptyPolygonM :: Context -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: createLinearRingM :: CoordinateSequence -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: createPolygonM :: Geometry -> [Geometry] -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: envelopeM :: Geometry -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: geomTypeIdM :: Geometry -> MaybeT IO GeometryType
- Data.Geolocation.GEOS.Trans: getCoordSeqM :: Geometry -> MaybeT IO CoordinateSequence
- Data.Geolocation.GEOS.Trans: getExteriorRingM :: Geometry -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: getGeometryM :: Geometry -> Int -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: getNumGeometriesM :: Geometry -> MaybeT IO Int
- Data.Geolocation.GEOS.Trans: getOrdinateM :: CoordinateSequence -> Word -> Word -> MaybeT IO Double
- Data.Geolocation.GEOS.Trans: getSizeM :: CoordinateSequence -> MaybeT IO Word
- Data.Geolocation.GEOS.Trans: getXM :: CoordinateSequence -> Word -> MaybeT IO Double
- Data.Geolocation.GEOS.Trans: getYM :: CoordinateSequence -> Word -> MaybeT IO Double
- Data.Geolocation.GEOS.Trans: getZM :: CoordinateSequence -> Word -> MaybeT IO Double
- Data.Geolocation.GEOS.Trans: intersectionM :: Geometry -> Geometry -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: isEmptyM :: Geometry -> MaybeT IO Bool
- Data.Geolocation.GEOS.Trans: mkReaderM :: Context -> MaybeT IO Reader
- Data.Geolocation.GEOS.Trans: mkWriterM :: Context -> MaybeT IO Writer
- Data.Geolocation.GEOS.Trans: readGeometryM :: Reader -> String -> MaybeT IO Geometry
- Data.Geolocation.GEOS.Trans: runGEOS :: (Context -> MaybeT IO a) -> IO (Maybe a)
- Data.Geolocation.GEOS.Trans: runGEOSEither :: (Context -> MaybeT IO a) -> IO (Either String a)
- Data.Geolocation.GEOS.Trans: setOrdinateM :: CoordinateSequence -> Word -> Word -> Double -> MaybeT IO ()
- Data.Geolocation.GEOS.Trans: setXM :: CoordinateSequence -> Word -> Double -> MaybeT IO ()
- Data.Geolocation.GEOS.Trans: setYM :: CoordinateSequence -> Word -> Double -> MaybeT IO ()
- Data.Geolocation.GEOS.Trans: setZM :: CoordinateSequence -> Word -> Double -> MaybeT IO ()
- Data.Geolocation.GEOS.Trans: writeGeometryM :: Writer -> Geometry -> MaybeT IO String
+ Data.Geolocation.GEOS: data GEOSError
+ Data.Geolocation.GEOS: instance GHC.Exception.Exception Data.Geolocation.GEOS.GEOSError
+ Data.Geolocation.GEOS: instance GHC.Show.Show Data.Geolocation.GEOS.GEOSError
- Data.Geolocation.GEOS: area :: Geometry -> IO (Maybe Double)
+ Data.Geolocation.GEOS: area :: Geometry -> IO Double
- Data.Geolocation.GEOS: createCollection :: GeometryType -> [Geometry] -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: createCollection :: GeometryType -> [Geometry] -> IO Geometry
- Data.Geolocation.GEOS: createCoordSeq :: Context -> Word -> Word -> IO (Maybe CoordinateSequence)
+ Data.Geolocation.GEOS: createCoordSeq :: Context -> Word -> Word -> IO CoordinateSequence
- Data.Geolocation.GEOS: createEmptyPolygon :: Context -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: createEmptyPolygon :: Context -> IO Geometry
- Data.Geolocation.GEOS: createLinearRing :: CoordinateSequence -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: createLinearRing :: CoordinateSequence -> IO Geometry
- Data.Geolocation.GEOS: createPolygon :: Geometry -> [Geometry] -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: createPolygon :: Geometry -> [Geometry] -> IO Geometry
- Data.Geolocation.GEOS: envelope :: Geometry -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: envelope :: Geometry -> IO Geometry
- Data.Geolocation.GEOS: geomTypeId :: Geometry -> IO (Maybe GeometryType)
+ Data.Geolocation.GEOS: geomTypeId :: Geometry -> IO GeometryType
- Data.Geolocation.GEOS: getCoordSeq :: Geometry -> IO (Maybe CoordinateSequence)
+ Data.Geolocation.GEOS: getCoordSeq :: Geometry -> IO CoordinateSequence
- Data.Geolocation.GEOS: getExteriorRing :: Geometry -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: getExteriorRing :: Geometry -> IO Geometry
- Data.Geolocation.GEOS: getGeometry :: Geometry -> Int -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: getGeometry :: Geometry -> Int -> IO Geometry
- Data.Geolocation.GEOS: getNumGeometries :: Geometry -> IO (Maybe Int)
+ Data.Geolocation.GEOS: getNumGeometries :: Geometry -> IO Int
- Data.Geolocation.GEOS: getOrdinate :: CoordinateSequence -> Word -> Word -> IO (Maybe Double)
+ Data.Geolocation.GEOS: getOrdinate :: CoordinateSequence -> Word -> Word -> IO Double
- Data.Geolocation.GEOS: getSize :: CoordinateSequence -> IO (Maybe Word)
+ Data.Geolocation.GEOS: getSize :: CoordinateSequence -> IO Word
- Data.Geolocation.GEOS: getX :: CoordinateSequence -> Word -> IO (Maybe Double)
+ Data.Geolocation.GEOS: getX :: CoordinateSequence -> Word -> IO Double
- Data.Geolocation.GEOS: getY :: CoordinateSequence -> Word -> IO (Maybe Double)
+ Data.Geolocation.GEOS: getY :: CoordinateSequence -> Word -> IO Double
- Data.Geolocation.GEOS: getZ :: CoordinateSequence -> Word -> IO (Maybe Double)
+ Data.Geolocation.GEOS: getZ :: CoordinateSequence -> Word -> IO Double
- Data.Geolocation.GEOS: intersection :: Geometry -> Geometry -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: intersection :: Geometry -> Geometry -> IO Geometry
- Data.Geolocation.GEOS: isEmpty :: Geometry -> IO (Maybe Bool)
+ Data.Geolocation.GEOS: isEmpty :: Geometry -> IO Bool
- Data.Geolocation.GEOS: mkReader :: Context -> IO (Maybe Reader)
+ Data.Geolocation.GEOS: mkReader :: Context -> IO Reader
- Data.Geolocation.GEOS: mkWriter :: Context -> IO (Maybe Writer)
+ Data.Geolocation.GEOS: mkWriter :: Context -> IO Writer
- Data.Geolocation.GEOS: readGeometry :: Reader -> String -> IO (Maybe Geometry)
+ Data.Geolocation.GEOS: readGeometry :: Reader -> String -> IO Geometry
- Data.Geolocation.GEOS: setOrdinate :: CoordinateSequence -> Word -> Word -> Double -> IO (Maybe ())
+ Data.Geolocation.GEOS: setOrdinate :: CoordinateSequence -> Word -> Word -> Double -> IO ()
- Data.Geolocation.GEOS: setX :: CoordinateSequence -> Word -> Double -> IO (Maybe ())
+ Data.Geolocation.GEOS: setX :: CoordinateSequence -> Word -> Double -> IO ()
- Data.Geolocation.GEOS: setY :: CoordinateSequence -> Word -> Double -> IO (Maybe ())
+ Data.Geolocation.GEOS: setY :: CoordinateSequence -> Word -> Double -> IO ()
- Data.Geolocation.GEOS: setZ :: CoordinateSequence -> Word -> Double -> IO (Maybe ())
+ Data.Geolocation.GEOS: setZ :: CoordinateSequence -> Word -> Double -> IO ()
- Data.Geolocation.GEOS: writeGeometry :: Writer -> Geometry -> IO (Maybe String)
+ Data.Geolocation.GEOS: writeGeometry :: Writer -> Geometry -> IO String

Files

hgeos.cabal view
@@ -1,5 +1,5 @@ name:                 hgeos-version:              0.1.7.4+version:              0.1.8.0 synopsis:             Simple Haskell bindings to GEOS C API description:   Simple Haskell bindings to the <https://trac.osgeo.org/geos/ GEOS>@@ -25,13 +25,11 @@   hs-source-dirs:     src/lib   default-language:   Haskell2010   build-depends:      base >= 4.6 && < 5-                    , transformers   extra-libraries:    geos_c   c-sources:          src/lib/Data/Geolocation/GEOS/helpers.c   cc-options:         -std=c99 -pthread   exposed-modules:    Data.Geolocation.GEOS                     , Data.Geolocation.GEOS.Imports-                    , Data.Geolocation.GEOS.Trans  test-suite hgeos-app   type:               exitcode-stdio-1.0@@ -41,10 +39,7 @@   build-depends:      MissingH                     , base >= 4.6 && < 5                     , hgeos-                    , mtl-                    , transformers   other-modules:      GEOSTest.Arith                     , GEOSTest.HighLevelAPI                     , GEOSTest.LowLevelAPI                     , GEOSTest.Sample-                    , GEOSTest.TransAPI
src/lib/Data/Geolocation/GEOS.hs view
@@ -20,11 +20,13 @@ <https://github.com/rcook/hgeos/blob/master/src/test/GEOSTest/Sample.hs View sample 2> -} +{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE RecordWildCards #-}  module Data.Geolocation.GEOS     ( Context ()     , CoordinateSequence ()+    , GEOSError ()     , Geometry ()     , GeometryType (..)     , Reader ()@@ -66,6 +68,7 @@ import Control.Monad import Data.Geolocation.GEOS.Imports import Data.IORef+import Data.Typeable import Data.Word import Foreign.C import Foreign.Marshal.Alloc@@ -105,6 +108,13 @@ -- |References a <https://en.wikipedia.org/wiki/Well-known_text WKT> writer data Writer = Writer ContextStateRef DeleteAction GEOSWKTWriterPtr +-- |Encapsulates an exception thrown by GEOS library+data GEOSError = GEOSError+    { context :: String+    , message :: String+    } deriving (Show, Typeable)+instance Exception GEOSError+ -- |References a <https://trac.osgeo.org/geos/ GEOS> geometry data Geometry = Geometry     { geometryStateRef :: ContextStateRef@@ -112,17 +122,23 @@     , geometryRawPtr :: GEOSGeometryPtr     } +throwGEOSError :: String -> IO a+throwGEOSError context = do+    m <- c_getErrorMessage+    message <- peekCString m+    throw $ GEOSError context message+ -- |Returns area of a 'Geometry' instance-area :: Geometry -> IO (Maybe Double)+area :: Geometry -> IO Double area (Geometry sr _ h) = do     ContextState{..} <- readIORef sr     alloca $ \valuePtr -> do         status <- c_GEOSArea_r hCtx h valuePtr         case status of-             0 -> return Nothing+             0 -> throwGEOSError "GEOSArea_r"              _ -> do                 value <- peek valuePtr-                return $ Just (realToFrac value)+                return $ realToFrac value  checkAndDoNotTrack :: ContextStateRef -> (GEOSContextHandle -> IO GEOSGeometryPtr) -> IO (Maybe Geometry) checkAndDoNotTrack sr f = do@@ -132,6 +148,14 @@                 then Nothing                 else Just $ Geometry sr emptyDeleteAction h +checkAndDoNotTrack2 :: String -> ContextStateRef -> (GEOSContextHandle -> IO GEOSGeometryPtr) -> IO Geometry+checkAndDoNotTrack2 context sr f = do+    ContextState{..} <- readIORef sr+    h <- f hCtx+    if isNullPtr h+       then throwGEOSError context+       else return $ Geometry sr emptyDeleteAction h+ checkAndTrack :: NullablePtr a =>     ContextStateRef ->     (GEOSContextHandle -> IO a) ->@@ -148,76 +172,108 @@         modifyIORef' sr (\p@ContextState{..} -> p { deleteActions = deleteAction : deleteActions })         return $ Just (wrap sr deleteAction h) +checkAndTrack2 :: NullablePtr a =>+    String ->+    ContextStateRef ->+    (GEOSContextHandle -> IO a) ->+    (GEOSContextHandle -> a -> IO ()) ->+    (ContextStateRef -> DeleteAction -> a -> b) ->+    IO b+checkAndTrack2 context sr create destroy wrap = do+    ContextState{..} <- readIORef sr+    h <- create hCtx+    if isNullPtr h+    then throwGEOSError context+    else do+        let deleteAction = DeleteAction (rawIntPtr h) (destroy hCtx h)+        modifyIORef' sr (\p@ContextState{..} -> p { deleteActions = deleteAction : deleteActions })+        return $ wrap sr deleteAction h+ checkAndTrackGeometry :: ContextStateRef -> (GEOSContextHandle -> IO GEOSGeometryPtr) -> IO (Maybe Geometry) checkAndTrackGeometry sr create = checkAndTrack sr create c_GEOSGeom_destroy_r Geometry +checkAndTrackGeometry2 :: String -> ContextStateRef -> (GEOSContextHandle -> IO GEOSGeometryPtr) -> IO Geometry+checkAndTrackGeometry2 context sr create = checkAndTrack2 context sr create c_GEOSGeom_destroy_r Geometry+ emptyDeleteAction :: DeleteAction emptyDeleteAction = DeleteAction (ptrToIntPtr nullPtr) (return ())  -- |Creates a 'Geometry' collection-createCollection :: GeometryType -> [Geometry] -> IO (Maybe Geometry)+createCollection :: GeometryType -> [Geometry] -> IO Geometry createCollection geometryType gs@((Geometry sr _ _) : _) = do     untrack sr (map geometryDeleteAction gs)     withArrayLen (map geometryRawPtr gs) $ \count array ->-        checkAndTrackGeometry+        checkAndTrackGeometry2+            "GEOSGeom_createCollection_r"             sr             (\hCtx -> c_GEOSGeom_createCollection_r hCtx (fromIntegral $ fromEnum geometryType) array (fromIntegral count))  -- |Creates an empty 'CoordinateSequence' instance-createCoordSeq :: Context -> Word -> Word -> IO (Maybe CoordinateSequence)+createCoordSeq :: Context -> Word -> Word -> IO CoordinateSequence createCoordSeq (Context sr) size dims =-    checkAndTrack+    checkAndTrack2+        "GEOSCoordSeq_create_r"         sr         (\hCtx -> c_GEOSCoordSeq_create_r hCtx (fromIntegral size) (fromIntegral dims))         c_GEOSCoordSeq_destroy_r         CoordinateSequence  -- |Returns an empty polygon 'Geometry' instance-createEmptyPolygon :: Context -> IO (Maybe Geometry)+createEmptyPolygon :: Context -> IO Geometry createEmptyPolygon (Context sr) = do     ContextState{..} <- readIORef sr-    checkAndTrackGeometry sr c_GEOSGeom_createEmptyPolygon_r+    checkAndTrackGeometry2+        "GEOSGeom_createEmptyPolygon_r"+        sr+        c_GEOSGeom_createEmptyPolygon_r  -- |Returns a linear ring 'Geometry' instance from the given coordinate -- sequence-createLinearRing :: CoordinateSequence -> IO (Maybe Geometry)+createLinearRing :: CoordinateSequence -> IO Geometry createLinearRing (CoordinateSequence sr deleteAction h) = do     untrack sr [deleteAction]-    checkAndTrackGeometry sr (\hCtx -> c_GEOSGeom_createLinearRing_r hCtx h)+    checkAndTrackGeometry2+        "GEOSGeom_createLinearRing_r"+        sr+        (\hCtx -> c_GEOSGeom_createLinearRing_r hCtx h)  -- |Returns a polygon 'Geometry' instance from the given shell and optional -- array of holes-createPolygon :: Geometry -> [Geometry] -> IO (Maybe Geometry)+createPolygon :: Geometry -> [Geometry] -> IO Geometry createPolygon (Geometry sr deleteAction h) holes = do     untrack sr (deleteAction : map geometryDeleteAction holes)     withArrayLen (map geometryRawPtr holes) $ \count array ->-        checkAndTrackGeometry+        checkAndTrackGeometry2+            "GEOSGeom_createPolygon_r"             sr             (\hCtx -> c_GEOSGeom_createPolygon_r hCtx h array (fromIntegral count))  -- |Returns a 'Geometry' instance representing the envelope of the supplied -- 'Geometry'-envelope :: Geometry -> IO (Maybe Geometry)+envelope :: Geometry -> IO Geometry envelope (Geometry sr _ h) =-    checkAndTrackGeometry sr (\hCtx -> c_GEOSEnvelope_r hCtx h)+    checkAndTrackGeometry2+        "GEOSEnvelope_r"+        sr+        (\hCtx -> c_GEOSEnvelope_r hCtx h)  -- |Returns type of a 'Geometry' instance-geomTypeId :: Geometry -> IO (Maybe GeometryType)+geomTypeId :: Geometry -> IO GeometryType geomTypeId (Geometry sr _ h) = do     ContextState{..} <- readIORef sr     value <- c_GEOSGeomTypeId_r hCtx h-    return $ if value == -1-                then Nothing-                else Just $ toEnum (fromIntegral value)+    if value == -1+       then throwGEOSError "GEOSGeomTypeId_r"+       else return $ toEnum (fromIntegral value)  -- |Returns a 'CoordinateSequence' from the supplied 'Geometry'-getCoordSeq :: Geometry -> IO (Maybe CoordinateSequence)+getCoordSeq :: Geometry -> IO CoordinateSequence getCoordSeq (Geometry sr _ hGeometry) = do     ContextState{..} <- readIORef sr     h <- c_GEOSGeom_getCoordSeq_r hCtx hGeometry-    return $ if isNullPtr h-                then Nothing-                else Just $ CoordinateSequence sr emptyDeleteAction h+    if isNullPtr h+       then throwGEOSError "GEOSGeom_getCoordSeq_r"+       else return $ CoordinateSequence sr emptyDeleteAction h  -- |Returns message in case of error getErrorMessage :: IO String@@ -225,85 +281,95 @@  -- |Returns a 'Geometry' instance representing the exterior ring of the -- supplied 'Geometry'-getExteriorRing :: Geometry -> IO (Maybe Geometry)+getExteriorRing :: Geometry -> IO Geometry getExteriorRing (Geometry sr _ h) =-    checkAndDoNotTrack sr (\hCtx -> c_GEOSGetExteriorRing_r hCtx h)+    checkAndDoNotTrack2+        "GEOSGetExteriorRing_r"+        sr+        (\hCtx -> c_GEOSGetExteriorRing_r hCtx h)  -- |Returns child 'Geometry' at given index-getGeometry :: Geometry -> Int -> IO (Maybe Geometry)+getGeometry :: Geometry -> Int -> IO Geometry getGeometry (Geometry sr _ h) n =-    checkAndDoNotTrack sr (\hCtx -> c_GEOSGetGeometryN_r hCtx h (fromIntegral n))+    checkAndDoNotTrack2+        "GEOSGetGeometryN_r"+        sr+        (\hCtx -> c_GEOSGetGeometryN_r hCtx h (fromIntegral n))  -- |Gets the number of geometries in a 'Geometry' instance-getNumGeometries :: Geometry -> IO (Maybe Int)+getNumGeometries :: Geometry -> IO Int getNumGeometries (Geometry sr _ h) = do     ContextState{..} <- readIORef sr     value <- c_GEOSGetNumGeometries_r hCtx h-    return $ if value == -1-                then Nothing-                else Just $ fromIntegral value+    if value == -1+       then throwGEOSError "GEOSGetNumGeometries_r"+       else return $ fromIntegral value  -- |Gets an ordinate value from a coordinate sequence-getOrdinate :: CoordinateSequence -> Word -> Word -> IO (Maybe Double)+getOrdinate :: CoordinateSequence -> Word -> Word -> IO Double getOrdinate coords idx dim =     getOrdinateHelper+        "GEOSCoordSeq_getOrdinate_r"         (\hCtx h idx' -> c_GEOSCoordSeq_getOrdinate_r hCtx h idx' (fromIntegral dim))         coords         idx -getOrdinateHelper :: (GEOSContextHandle -> GEOSCoordSequencePtr -> CUInt -> Ptr CDouble -> IO CInt) ->+getOrdinateHelper :: String -> (GEOSContextHandle -> GEOSCoordSequencePtr -> CUInt -> Ptr CDouble -> IO CInt) ->     CoordinateSequence ->     Word ->-    IO (Maybe Double)-getOrdinateHelper f (CoordinateSequence sr _ h) idx = do+    IO Double+getOrdinateHelper context f (CoordinateSequence sr _ h) idx = do     ContextState{..} <- readIORef sr     alloca $ \valuePtr -> do         status <- f hCtx h (fromIntegral idx) valuePtr         case status of-             0 -> return Nothing+             0 -> throwGEOSError context              _ -> do                 value <- peek valuePtr-                return $ Just (realToFrac value)+                return $ realToFrac value  -- |Gets the size from a coordinate sequence-getSize :: CoordinateSequence -> IO (Maybe Word)+getSize :: CoordinateSequence -> IO Word getSize (CoordinateSequence sr _ h) = do     ContextState{..} <- readIORef sr     alloca $ \sizePtr -> do         status <- c_GEOSCoordSeq_getSize_r hCtx h sizePtr         case status of-             0 -> return Nothing+             0 -> throwGEOSError "GEOSCoordSeq_getSize_r"              _ -> do                  size <- peek sizePtr-                 return $ Just (fromIntegral size)+                 return $ fromIntegral size  -- |Gets an x-ordinate value from a coordinate sequence-getX :: CoordinateSequence -> Word -> IO (Maybe Double)-getX = getOrdinateHelper c_GEOSCoordSeq_getX_r+getX :: CoordinateSequence -> Word -> IO Double+getX = getOrdinateHelper "GEOSCoordSeq_getX_r" c_GEOSCoordSeq_getX_r  -- |Gets a y-ordinate value from a coordinate sequence-getY :: CoordinateSequence -> Word -> IO (Maybe Double)-getY = getOrdinateHelper c_GEOSCoordSeq_getY_r+getY :: CoordinateSequence -> Word -> IO Double+getY = getOrdinateHelper "GEOSCoordSeq_getY_r" c_GEOSCoordSeq_getY_r  -- |Gets a z-ordinate value from a coordinate sequence-getZ :: CoordinateSequence -> Word -> IO (Maybe Double)-getZ = getOrdinateHelper c_GEOSCoordSeq_getZ_r+getZ :: CoordinateSequence -> Word -> IO Double+getZ = getOrdinateHelper "GEOSCoordSeq_getZ_r" c_GEOSCoordSeq_getZ_r  -- |Returns a 'Geometry' instance representing the intersection of the two -- supplied 'Geometry' instances:-intersection :: Geometry -> Geometry -> IO (Maybe Geometry)+intersection :: Geometry -> Geometry -> IO Geometry intersection (Geometry sr0 _ h0) (Geometry sr1 _ h1) =-    checkAndTrackGeometry sr0 (\hCtx -> c_GEOSIntersection_r hCtx h0 h1)+    checkAndTrackGeometry2+        "GEOSIntersection_r"+        sr0+        (\hCtx -> c_GEOSIntersection_r hCtx h0 h1)  -- |Returns value indicating if specified 'Geometry' instance is empty-isEmpty :: Geometry -> IO (Maybe Bool)+isEmpty :: Geometry -> IO Bool isEmpty (Geometry sr _ h) = do     ContextState{..} <- readIORef sr     value <- c_GEOSisEmpty_r hCtx h-    return $ case value of-                  0 -> Just False-                  1 -> Just True-                  _ -> Nothing+    case value of+         0 -> return False+         1 -> return True+         _ -> throwGEOSError "GEOSisEmpty_r"  mkContext :: IO Context mkContext = do@@ -313,19 +379,34 @@  -- |Creates a reader used to deserialize 'Geometry' instances from -- <https://en.wikipedia.org/wiki/Well-known_text WKT>-format text:-mkReader :: Context -> IO (Maybe Reader)-mkReader (Context sr) = checkAndTrack sr c_GEOSWKTReader_create_r c_GEOSWKTReader_destroy_r Reader+mkReader :: Context -> IO Reader+mkReader (Context sr) =+    checkAndTrack2+        "GEOSWKTReader_create_r"+        sr+        c_GEOSWKTReader_create_r+        c_GEOSWKTReader_destroy_r+        Reader  -- |Creates a writer used to serialize 'Geometry' instances to -- <https://en.wikipedia.org/wiki/Well-known_text WKT>-format text:-mkWriter :: Context -> IO (Maybe Writer)-mkWriter (Context sr) = checkAndTrack sr c_GEOSWKTWriter_create_r c_GEOSWKTWriter_destroy_r Writer+mkWriter :: Context -> IO Writer+mkWriter (Context sr) =+    checkAndTrack2+        "GEOSWKTWriter_destroy_r"+        sr+        c_GEOSWKTWriter_create_r+        c_GEOSWKTWriter_destroy_r+        Writer  -- |Deserializes a 'Geometry' instance from the given 'String' using the -- supplied 'Reader':-readGeometry :: Reader -> String -> IO (Maybe Geometry)+readGeometry :: Reader -> String -> IO Geometry readGeometry (Reader sr _ h) str = withCString str $ \cs -> do-    checkAndTrackGeometry sr (\hCtx -> c_GEOSWKTReader_read_r hCtx h cs)+    checkAndTrackGeometry2+        "GEOSWKTReader_read_r"+        sr+        (\hCtx -> c_GEOSWKTReader_read_r hCtx h cs)  releaseContext :: Context -> IO () releaseContext (Context sr) = do@@ -334,32 +415,33 @@     c_finishGEOS_r hCtx  -- |Sets an x-ordinate value within a coordinate sequence-setOrdinate :: CoordinateSequence -> Word -> Word -> Double -> IO (Maybe ())+setOrdinate :: CoordinateSequence -> Word -> Word -> Double -> IO () setOrdinate coords idx dim =     setOrdinateHelper+        "GEOSCoordSeq_setOrdinate_r"         (\hCtx h idx' -> c_GEOSCoordSeq_setOrdinate_r hCtx h idx' (fromIntegral dim))         coords         idx -setOrdinateHelper :: (GEOSContextHandle -> GEOSCoordSequencePtr -> CUInt -> CDouble -> IO CInt ) -> CoordinateSequence -> Word -> Double -> IO (Maybe ())-setOrdinateHelper f (CoordinateSequence sr _ h) idx val = do+setOrdinateHelper :: String -> (GEOSContextHandle -> GEOSCoordSequencePtr -> CUInt -> CDouble -> IO CInt ) -> CoordinateSequence -> Word -> Double -> IO ()+setOrdinateHelper context f (CoordinateSequence sr _ h) idx val = do     ContextState{..} <- readIORef sr     status <- f hCtx h (fromIntegral idx) (realToFrac val)-    return $ case status of-                  0 -> Nothing-                  _ -> Just ()+    if status == 0+       then throwGEOSError context+       else return ()  -- |Sets an x-ordinate value within a coordinate sequence-setX :: CoordinateSequence -> Word -> Double -> IO (Maybe ())-setX = setOrdinateHelper c_GEOSCoordSeq_setX_r+setX :: CoordinateSequence -> Word -> Double -> IO ()+setX = setOrdinateHelper "GEOSCoordSeq_setX_r" c_GEOSCoordSeq_setX_r  -- |Sets a y-ordinate value within a coordinate sequence-setY :: CoordinateSequence -> Word -> Double -> IO (Maybe ())-setY = setOrdinateHelper c_GEOSCoordSeq_setY_r+setY :: CoordinateSequence -> Word -> Double -> IO ()+setY = setOrdinateHelper "GEOSCoordSeq_setY_r" c_GEOSCoordSeq_setY_r  -- |Sets a z-ordinate value within a coordinate sequence-setZ :: CoordinateSequence -> Word -> Double -> IO (Maybe ())-setZ = setOrdinateHelper c_GEOSCoordSeq_setZ_r+setZ :: CoordinateSequence -> Word -> Double -> IO ()+setZ = setOrdinateHelper "GEOSCoordSeq_setZ_r" c_GEOSCoordSeq_setZ_r  untrack :: ContextStateRef -> [DeleteAction] -> IO () untrack sr deleteActions = do@@ -385,10 +467,10 @@ withGEOS = bracket mkContext releaseContext  -- |Serializes a 'Geometry' instance to a 'String' using the supplied 'Writer':-writeGeometry :: Writer -> Geometry -> IO (Maybe String)+writeGeometry :: Writer -> Geometry -> IO String writeGeometry (Writer sr _ hWriter) (Geometry _ _ hGeometry) = do     ContextState{..} <- readIORef sr     bracket         (c_GEOSWKTWriter_write_r hCtx hWriter hGeometry)         (c_GEOSFree_r_CString hCtx)-        (\cs -> if cs == nullPtr then return Nothing else Just <$> peekCString cs)+        (\cs -> if cs == nullPtr then throwGEOSError "GEOSWKTWriter_write_r" else peekCString cs)
− src/lib/Data/Geolocation/GEOS/Trans.hs
@@ -1,207 +0,0 @@-{-|-Module      : Data.Geolocation.GEOS.Trans-Description : @MaybeT@ wrappers for high-level GEOS API-Copyright   : (C) Richard Cook, 2016-Licence     : MIT-Maintainer  : rcook@rcook.org-Stability   : experimental-Portability : portable--These are @MaybeT@ monad transformer wrapper functions for the high-level API-to simplify error handling in client code.--For the low-level FFI bindings, see "Data.Geolocation.GEOS.Imports".--For the high-level API, see "Data.Geolocation.GEOS".--<https://github.com/rcook/hgeos/blob/master/src/test/GEOSTest/TransAPI.hs View sample>--}--module Data.Geolocation.GEOS.Trans-    ( areaM-    , createCollectionM-    , createCoordSeqM-    , createEmptyPolygonM-    , createLinearRingM-    , createPolygonM-    , envelopeM-    , geomTypeIdM-    , getCoordSeqM-    , getExteriorRingM-    , getGeometryM-    , getNumGeometriesM-    , getOrdinateM-    , getSizeM-    , getXM-    , getYM-    , getZM-    , intersectionM-    , isEmptyM-    , mkReaderM-    , mkWriterM-    , readGeometryM-    , runGEOS-    , runGEOSEither-    , setOrdinateM-    , setXM-    , setYM-    , setZM-    , writeGeometryM-    ) where--import Control.Applicative-import Control.Monad.Trans.Maybe-import Data.Geolocation.GEOS-import Data.Word--unaryGEOSFunc :: (a -> IO (Maybe b)) -> a -> MaybeT IO b-unaryGEOSFunc = (MaybeT .)--binaryGEOSFunc :: (a -> b -> IO (Maybe c)) -> a -> b -> MaybeT IO c-binaryGEOSFunc f a b = MaybeT (f a b)--ternaryGEOSFunc :: (a -> b -> c -> IO (Maybe d)) -> a -> b -> c -> MaybeT IO d-ternaryGEOSFunc f a b c = MaybeT (f a b c)--quaternaryGEOSFunc :: (a -> b -> c -> d -> IO (Maybe e)) -> a -> b -> c -> d -> MaybeT IO e-quaternaryGEOSFunc f a b c d = MaybeT (f a b c d)---- |@MaybeT@-wrapped version of 'area'-areaM :: Geometry -> MaybeT IO Double-areaM = unaryGEOSFunc area---- |@MaybeT@-wrapped version of 'createCollection'-createCollectionM :: GeometryType -> [Geometry] -> MaybeT IO Geometry-createCollectionM = binaryGEOSFunc createCollection---- |@MaybeT@-wrapped version of 'createCoordSeq'-createCoordSeqM :: Context -> Word -> Word -> MaybeT IO CoordinateSequence-createCoordSeqM = ternaryGEOSFunc createCoordSeq---- |@MaybeT@-wrapped version of 'createEmptyPolygon'-createEmptyPolygonM :: Context -> MaybeT IO Geometry-createEmptyPolygonM = unaryGEOSFunc createEmptyPolygon---- |@MaybeT@-wrapped version of 'createLinearRing'-createLinearRingM :: CoordinateSequence -> MaybeT IO Geometry-createLinearRingM = unaryGEOSFunc createLinearRing---- |@MaybeT@-wrapped version of 'createPolygon'-createPolygonM :: Geometry -> [Geometry] -> MaybeT IO Geometry-createPolygonM = binaryGEOSFunc createPolygon---- |@MaybeT@-wrapped version of 'envelope'-envelopeM :: Geometry -> MaybeT IO Geometry-envelopeM = unaryGEOSFunc envelope---- |@MaybeT@-wrapped version of 'geomTypeId'-geomTypeIdM :: Geometry -> MaybeT IO GeometryType-geomTypeIdM = unaryGEOSFunc geomTypeId---- |@MaybeT@-wrapped version of 'getCoordSeq'-getCoordSeqM :: Geometry -> MaybeT IO CoordinateSequence-getCoordSeqM = unaryGEOSFunc getCoordSeq---- |@MaybeT@-wrapped version of 'getExteriorRing'-getExteriorRingM :: Geometry -> MaybeT IO Geometry-getExteriorRingM = unaryGEOSFunc getExteriorRing---- |@MaybeT@-wrapped version of 'getGeometry'-getGeometryM :: Geometry -> Int -> MaybeT IO Geometry-getGeometryM = binaryGEOSFunc getGeometry---- |@MaybeT@-wrapped version of 'getNumGeometries'-getNumGeometriesM :: Geometry -> MaybeT IO Int-getNumGeometriesM = unaryGEOSFunc getNumGeometries---- |@MaybeT@-wrapped version of 'getOrdinate'-getOrdinateM :: CoordinateSequence -> Word -> Word -> MaybeT IO Double-getOrdinateM = ternaryGEOSFunc getOrdinate---- |@MaybeT@-wrapped version of 'getSize'-getSizeM :: CoordinateSequence -> MaybeT IO Word-getSizeM = unaryGEOSFunc getSize---- |@MaybeT@-wrapped version of 'getX'-getXM :: CoordinateSequence -> Word -> MaybeT IO Double-getXM = binaryGEOSFunc getX---- |@MaybeT@-wrapped version of 'getY'-getYM :: CoordinateSequence -> Word -> MaybeT IO Double-getYM = binaryGEOSFunc getY---- |@MaybeT@-wrapped version of 'getZ'-getZM :: CoordinateSequence -> Word -> MaybeT IO Double-getZM = binaryGEOSFunc getZ---- |@MaybeT@-wrapped version of 'intersection'-intersectionM :: Geometry -> Geometry -> MaybeT IO Geometry-intersectionM = binaryGEOSFunc intersection---- |@MaybeT@-wrapped version of 'isEmpty'-isEmptyM :: Geometry -> MaybeT IO Bool-isEmptyM = unaryGEOSFunc isEmpty---- |@MaybeT@-wrapped version of 'mkReader'-mkReaderM :: Context -> MaybeT IO Reader-mkReaderM = unaryGEOSFunc mkReader---- |@MaybeT@-wrapped version of 'mkWriter'-mkWriterM :: Context -> MaybeT IO Writer-mkWriterM = unaryGEOSFunc mkWriter---- |@MaybeT@-wrapped version of 'readGeometry'-readGeometryM :: Reader -> String -> MaybeT IO Geometry-readGeometryM = binaryGEOSFunc readGeometry---- |Creates a <https://trac.osgeo.org/geos/ GEOS> context, passes it to a block--- and releases the context and all associated objects such as readers, writers--- and geometries at the end inside a @MaybeT IO@ monad:------ @---    runGEOS $ \ctx -> do------        -- Use context------        return ()--- @-runGEOS :: (Context -> MaybeT IO a) -> IO (Maybe a)-runGEOS = withGEOS . (runMaybeT .)---- |Creates a <https://trac.osgeo.org/geos/ GEOS> context, passes it to a block--- and releases the context and all associated objects such as readers, writers--- and geometries at the end inside a @MaybeT IO@ monad returning a message in--- case of error:------ @---    result <- runGEOSEither $ \ctx -> do------        -- Use context------        return ()---    case result of---          Left m -> putStrLn $ "Failed: " ++ m---          Right r -> putStrLn $ "Succeeded: " ++ show r--- @-runGEOSEither :: (Context -> MaybeT IO a) -> IO (Either String a)-runGEOSEither action = do-    result <- runGEOS action-    case result of-         Nothing -> Left <$> getErrorMessage-         Just r -> return $ Right r---- |@MaybeT@-wrapped version of 'setOrdinate'-setOrdinateM = quaternaryGEOSFunc setOrdinate---- |@MaybeT@-wrapped version of 'setX'-setXM = ternaryGEOSFunc setX---- |@MaybeT@-wrapped version of 'setY'-setYM = ternaryGEOSFunc setY---- |@MaybeT@-wrapped version of 'setZ'-setZM = ternaryGEOSFunc setZ---- |@MaybeT@-wrapped version of 'area'-writeGeometryM :: Writer -> Geometry -> MaybeT IO String-writeGeometryM = binaryGEOSFunc writeGeometry
src/test/GEOSTest/HighLevelAPI.hs view
@@ -1,22 +1,88 @@ module GEOSTest.HighLevelAPI (demo) where -import Control.Monad.Trans-import Control.Monad.Trans.Maybe+import Control.Monad import Data.Geolocation.GEOS import Data.Maybe +check :: Bool -> IO ()+check True = return ()+check False = error "Check failed"++type Coordinate = (Double, Double)++createLinearRingHelper :: Context -> [Coordinate] -> IO Geometry+createLinearRingHelper ctx cs = do+    let count = length cs+    coords <- createCoordSeq ctx (fromIntegral count) 2+    forM_ (zip [0..] cs) $ \(i, (x, y)) -> do+        setX coords i x+        setY coords i y+    createLinearRing coords+ -- Demonstrates use of high-level API -- Lifetimes of GEOS objects are automatically managed by the context objects -- which guarantees that they are released when the context goes out of scope demo :: IO () demo = do-    result <- withGEOS $ \ctx -> runMaybeT $ do-        reader <- MaybeT $ mkReader ctx-        g0 <- MaybeT $ readGeometry reader "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"-        g1 <- MaybeT $ readGeometry reader "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"-        g2 <- MaybeT $ intersection g0 g1-        writer <- MaybeT $ mkWriter ctx-        str <- MaybeT $ writeGeometry writer g2-        lift $ putStrLn str+    withGEOS $ \ctx -> do+        reader <- mkReader ctx+        writer <- mkWriter ctx -    putStrLn $ "HighLevelAPI.demo: " ++ (if isJust result then "succeeded" else error "HighLevelAPI.demo failed")+        g0 <- readGeometry reader "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"+        a0 <- area g0+        putStrLn $ show a0++        g1 <- readGeometry reader "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"+        a1 <- area g1+        putStrLn $ show a1++        g2 <- intersection g0 g1+        str0 <- writeGeometry writer g2+        putStrLn str0++        coords <- createCoordSeq ctx 10 3+        size <- getSize coords+        forM_ [0..size - 2] $ \i -> do+            setX coords i (fromIntegral (i + 1) * 10.0)+            setY coords i (fromIntegral (i + 1) * 20.0)+            setZ coords i (fromIntegral (i + 1) * 30.0)+        setOrdinate coords (size - 1) 0 10.0+        setOrdinate coords (size - 1) 1 20.0+        setOrdinate coords (size - 1) 2 30.0+        g3 <- createLinearRing coords+        str1 <- writeGeometry writer g3+        putStrLn str1++        x0 <- getX coords 0+        check $ x0 == 10.0+        y0 <- getY coords 0+        check $ y0 == 20.0+        z0 <- getZ coords 0+        check $ z0 == 30.0++        x1 <- getOrdinate coords 1 0+        check $ x1 == 20.0+        y1 <- getOrdinate coords 1 1+        check $ y1 == 40.0+        z1 <- getOrdinate coords 1 2+        check $ z1 == 60.0++        p <- createPolygon g3 []+        str2 <- writeGeometry writer p+        putStrLn str2++        shell <- createLinearRingHelper ctx [(-10.0, -10.0), (-10.0, 10.0), (10.0, 10.0), (10.0, -10.0), (-10.0, -10.0)]+        hole <- createLinearRingHelper ctx [(-5.0, -5.0), (-5.0, 5.0), (5.0, 5.0), (5.0, -5.0), (-5.0, -5.0)]+        polygon <- createPolygon shell [hole]+        str3 <- writeGeometry writer polygon+        putStrLn str3++        coll <- createCollection MultiPolygon [polygon]+        str4 <- writeGeometry writer coll+        putStrLn str4++        p <- createEmptyPolygon ctx+        str5 <- writeGeometry writer p+        putStrLn str5++    putStrLn "HighLevelAPI2.demo succeeded"
src/test/GEOSTest/Sample.hs view
@@ -3,8 +3,6 @@ module GEOSTest.Sample (demo) where  import Control.Monad-import Control.Monad.Trans-import Control.Monad.Trans.Maybe import Data.Geolocation.GEOS import Data.List import Data.Maybe@@ -27,13 +25,13 @@     , maxZ :: Double     } deriving Show -getXYZs :: CoordinateSequence -> MaybeT IO [Coordinate]+getXYZs :: CoordinateSequence -> IO [Coordinate] getXYZs coordSeq = do-    size <- MaybeT $ getSize coordSeq+    size <- getSize coordSeq     forM [0..(size - 1)] $ \i -> do-        x <- MaybeT $ getX coordSeq i-        y <- MaybeT $ getY coordSeq i-        z <- MaybeT $ getZ coordSeq i+        x <- getX coordSeq i+        y <- getY coordSeq i+        z <- getZ coordSeq i         return (x, y, z)  extent :: [Coordinate] -> Extent@@ -49,7 +47,7 @@     in Extent minX maxX minY maxY minZ maxZ  -- TODO: Build polygon using API instead of string parsing-mkSquare :: Reader -> Longitude -> Latitude -> Resolution -> MaybeT IO Geometry+mkSquare :: Reader -> Longitude -> Latitude -> Resolution -> IO Geometry mkSquare reader longitude latitude resolution =     let points = [             (longitude, latitude),@@ -59,32 +57,32 @@             (longitude, latitude)             ]         wkt = printf "POLYGON ((%s))" (intercalate "," (map (\(a, b) -> printf "%f %f" a b) points))-    in MaybeT $ readGeometry reader wkt+    in readGeometry reader wkt -getGeometries :: Geometry -> IO (Maybe [Geometry])-getGeometries geometry = runMaybeT $ do-    count <- MaybeT $ getNumGeometries geometry-    mapM (MaybeT . getGeometry geometry) [0..(count - 1)]+getGeometries :: Geometry -> IO [Geometry]+getGeometries geometry = do+    count <- getNumGeometries geometry+    mapM (getGeometry geometry) [0..(count - 1)] -findBiggestPolygon :: Geometry -> IO (Maybe Geometry)-findBiggestPolygon geometry = runMaybeT $ do-    gs@(gHead : gTail) <- MaybeT (getGeometries geometry)-    as@(aHead : aTail) <- mapM (MaybeT . area) gs+findBiggestPolygon :: Geometry -> IO Geometry+findBiggestPolygon geometry = do+    gs@(gHead : gTail) <- getGeometries geometry+    as@(aHead : aTail) <- mapM area gs     return $ fst $ foldr         (\p'@(_, a') p@(_, a) -> if a' > a then p' else p)         (gHead, aHead)         (zip gTail aTail) -processPolygon :: String -> Resolution -> Longitude -> Latitude -> Geometry -> MaybeT IO ()+processPolygon :: String -> Resolution -> Longitude -> Latitude -> Geometry -> IO () processPolygon tableName resolution longitude latitude p = do-    shell <- MaybeT $ getExteriorRing p-    coordSeq <- MaybeT $ getCoordSeq shell+    shell <- getExteriorRing p+    coordSeq <- getCoordSeq shell     xyzs <- getXYZs coordSeq     let pId = polygonId resolution longitude latitude         format :: Int -> Double -> Double -> String         format = printf "INSERT INTO %s (polygon_id, point_id, longitude, latitude) VALUES ('%s', %d, %f, %f);\n" tableName pId         strs = map (\(pointId, (x, y, _)) -> format pointId x y) (zip [0..] xyzs)-    lift $ forM_ strs putStr+    forM_ strs putStr  polygonId :: Resolution -> Longitude -> Latitude -> String polygonId resolution longitude latitude = "id_" ++ formatValue longitude ++ "_" ++ formatValue latitude@@ -92,19 +90,18 @@         formatValue :: Double -> String         formatValue = replace "-" "m" . replace "." "_" . (printf "%.2f") . mfloor resolution -generatePolygonMeshSQL :: Context -> String -> Resolution -> MaybeT IO ()+generatePolygonMeshSQL :: Context -> String -> Resolution -> IO () generatePolygonMeshSQL ctx wkt resolution = do-    reader <- MaybeT $ mkReader ctx-    writer <- MaybeT $ mkWriter ctx-    country <- MaybeT $ readGeometry reader wkt-    env <- MaybeT $ envelope country-    shell <- MaybeT $ getExteriorRing env-    coordSeq <- MaybeT $ getCoordSeq shell+    reader <- mkReader ctx+    writer <- mkWriter ctx+    country <- readGeometry reader wkt+    env <- envelope country+    shell <- getExteriorRing env+    coordSeq <- getCoordSeq shell     xyzs <- getXYZs coordSeq -    lift $ do-        putStrLn "Shell:"-        mapM_ print xyzs+    putStrLn "Shell:"+    mapM_ print xyzs      let Extent{..} = extent xyzs         mfloorRes = mfloor resolution@@ -113,21 +110,20 @@         latitudeBegin = mfloorRes minY         latitudeEnd = mfloorRes maxY + resolution -    lift $ do-        putStrLn "Longitude and latitude ranges:"-        putStrLn $ printf "  longitude %f to %f" longitudeBegin longitudeEnd-        putStrLn $ printf "  latitude %f to %f" latitudeBegin latitudeEnd+    putStrLn "Longitude and latitude ranges:"+    putStrLn $ printf "  longitude %f to %f" longitudeBegin longitudeEnd+    putStrLn $ printf "  latitude %f to %f" latitudeBegin latitudeEnd      let longitudes = frange longitudeBegin longitudeEnd 1.0         latitudes = frange latitudeBegin latitudeEnd 1.0     forM_ [(i, j) | i <- longitudes, j <- latitudes] $ \(longitude, latitude) -> do         square <- mkSquare reader longitude latitude resolution-        overlap <- MaybeT $ intersection square country-        isOverlapEmpty <- MaybeT $ isEmpty overlap+        overlap <- intersection square country+        isOverlapEmpty <- isEmpty overlap         unless isOverlapEmpty $ do-            typeId <- MaybeT $ geomTypeId overlap+            typeId <- geomTypeId overlap             polygon <- case typeId of-                            MultiPolygon -> MaybeT $ findBiggestPolygon overlap+                            MultiPolygon -> findBiggestPolygon overlap                             Polygon -> return overlap             processPolygon "TABLE_NAME" resolution longitude latitude polygon     return ()@@ -136,6 +132,5 @@ demo = do     fileName <- getDataFileName "data/namibia.wkt"     wkt <- readFile fileName-    result <- withGEOS $ \ctx -> runMaybeT (generatePolygonMeshSQL ctx wkt 1.0)--    putStrLn $ "Sample.demo: " ++ (if isJust result then "succeeded" else error "Sample.demo failed")+    withGEOS $ \ctx -> generatePolygonMeshSQL ctx wkt 1.0+    putStrLn "Sample.demo: succeeded"
− src/test/GEOSTest/TransAPI.hs
@@ -1,87 +0,0 @@-module GEOSTest.TransAPI (demo) where--import Control.Monad-import Control.Monad.Trans-import Control.Monad.Trans.Maybe-import Data.Geolocation.GEOS (Context, Geometry, GeometryType (..))-import Data.Geolocation.GEOS.Trans-import Data.Maybe--check :: Bool -> MaybeT IO ()-check True = return ()-check False = error "Check failed"--type Coordinate = (Double, Double)--createLinearRing :: Context -> [Coordinate] -> MaybeT IO Geometry-createLinearRing ctx cs = do-    let count = length cs-    coords <- createCoordSeqM ctx (fromIntegral count) 2-    forM_ (zip [0..] cs) $ \(i, (x, y)) -> do-        setXM coords i x-        setYM coords i y-    createLinearRingM coords---- Demonstrates use of monad transformer API--- Lifetimes of GEOS objects are automatically managed by the context objects--- which guarantees that they are released when the context goes out of scope-demo :: IO ()-demo = do-    result <- runGEOSEither $ \ctx -> do-        reader <- mkReaderM ctx-        writer <- mkWriterM ctx--        g0 <- readGeometryM reader "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"-        g1 <- readGeometryM reader "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"-        g2 <- intersectionM g0 g1-        str0 <- writeGeometryM writer g2-        lift $ putStrLn str0--        coords <- createCoordSeqM ctx 10 3-        size <- getSizeM coords-        forM_ [0..size - 2] $ \i -> do-            setXM coords i (fromIntegral (i + 1) * 10.0)-            setYM coords i (fromIntegral (i + 1) * 20.0)-            setZM coords i (fromIntegral (i + 1) * 30.0)-        setOrdinateM coords (size - 1) 0 10.0-        setOrdinateM coords (size - 1) 1 20.0-        setOrdinateM coords (size - 1) 2 30.0-        g3 <- createLinearRingM coords-        str1 <- writeGeometryM writer g3-        lift $ putStrLn str1--        x0 <- getXM coords 0-        check $ x0 == 10.0-        y0 <- getYM coords 0-        check $ y0 == 20.0-        z0 <- getZM coords 0-        check $ z0 == 30.0--        x1 <- getOrdinateM coords 1 0-        check $ x1 == 20.0-        y1 <- getOrdinateM coords 1 1-        check $ y1 == 40.0-        z1 <- getOrdinateM coords 1 2-        check $ z1 == 60.0--        p <- createPolygonM g3 []-        str2 <- writeGeometryM writer p-        lift $ putStrLn str2--        shell <- createLinearRing ctx [(-10.0, -10.0), (-10.0, 10.0), (10.0, 10.0), (10.0, -10.0), (-10.0, -10.0)]-        hole <- createLinearRing ctx [(-5.0, -5.0), (-5.0, 5.0), (5.0, 5.0), (5.0, -5.0), (-5.0, -5.0)]-        polygon <- createPolygonM shell [hole]-        str3 <- writeGeometryM writer polygon-        lift $ putStrLn str3--        coll <- createCollectionM MultiPolygon [polygon]-        str4 <- writeGeometryM writer coll-        lift $ putStrLn str4--        p <- createEmptyPolygonM ctx-        str5 <- writeGeometryM writer p-        lift $ putStrLn str5--    case result of-         Left m -> error $ "TransAPI.demo failed: " ++ m-         Right _ -> putStrLn "TransAPI.demo succeeded"
src/test/Main.hs view
@@ -6,7 +6,6 @@ import qualified GEOSTest.HighLevelAPI as HighLevelAPI import qualified GEOSTest.LowLevelAPI as LowLevelAPI import qualified GEOSTest.Sample as Sample-import qualified GEOSTest.TransAPI as TransAPI  main :: IO () main = do@@ -14,5 +13,4 @@     putStrLn v     LowLevelAPI.demo     HighLevelAPI.demo-    TransAPI.demo     Sample.demo