diff --git a/hgeos.cabal b/hgeos.cabal
--- a/hgeos.cabal
+++ b/hgeos.cabal
@@ -1,9 +1,10 @@
 name:                 hgeos
-version:              0.1.1.0
+version:              0.1.2.0
 synopsis:             Simple Haskell bindings to GEOS C API
 description:
-  Simple Haskell bindings to the GEOS C API heavily inspired by
-  <https://github.com/django/django/tree/master/django/contrib/gis/geos Django GEOS bindings>
+  Simple Haskell bindings to the <https://trac.osgeo.org/geos/ GEOS>
+  <http://geos.osgeo.org/doxygen/geos__c_8h_source.html C API> heavily inspired
+  by <https://github.com/django/django/tree/master/django/contrib/gis/geos Django GEOS bindings>
 homepage:             https://github.com/rcook/hgeos#readme
 bug-reports:          https://github.com/rcook/hgeos/issues
 license:              MIT
@@ -25,9 +26,8 @@
   default-language:   Haskell2010
   build-depends:      base >= 4.7 && < 5
   extra-libraries:    geos_c
-  c-sources:          src/lib/helpers.c
-                    , src/lib/helpers.h
-  includes:           src/lib/helpers.h
+  c-sources:          src/lib/Data/Geolocation/GEOS/helpers.c
+                    , src/lib/Data/Geolocation/GEOS/helpers.h
   cc-options:         -std=c99 -pthread
   exposed-modules:    Data.Geolocation.GEOS
                     , Data.Geolocation.GEOS.Imports
@@ -40,6 +40,10 @@
   hs-source-dirs:     src/app
   main-is:            Main.hs
   default-language:   Haskell2010
-  build-depends:      base >= 4.7 && < 5
+  build-depends:      MissingH
+                    , base >= 4.7 && < 5
                     , hgeos
-  other-modules:      Main
+  other-modules:      HighLevelAPI
+                    , LowLevelAPI
+                    , Main
+                    , Sample
diff --git a/src/app/HighLevelAPI.hs b/src/app/HighLevelAPI.hs
new file mode 100644
--- /dev/null
+++ b/src/app/HighLevelAPI.hs
@@ -0,0 +1,18 @@
+module HighLevelAPI (demo) where
+
+import Data.Geolocation.GEOS
+
+-- 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
+    withGEOS $ \ctx -> do
+        reader <- mkReader ctx
+        g0 <- readGeometry reader "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"
+        g1 <- readGeometry reader "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"
+        g2 <- intersection g0 g1
+        writer <- mkWriter ctx
+        str <- writeGeometry writer g2
+        putStrLn str
+        putStrLn "HighLevelAPI.demo done"
diff --git a/src/app/LowLevelAPI.hs b/src/app/LowLevelAPI.hs
new file mode 100644
--- /dev/null
+++ b/src/app/LowLevelAPI.hs
@@ -0,0 +1,39 @@
+module LowLevelAPI (demo) where
+
+import Control.Exception
+import Data.Geolocation.GEOS.Imports
+import Foreign.C
+
+-- Demonstrates direct use of imports
+-- Lifetimes of various GEOS objects, including readers, writers and
+-- geometries, must be managed explicitly by clients using explicit calls to
+-- various destroy/free functions
+demo :: IO ()
+demo = do
+    wkt0 <- newCString "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"
+    wkt1 <- newCString "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"
+
+    withGEOS $ \ctx -> do
+        withWKTReader ctx $ \reader -> do
+            withGeometry ctx reader wkt0 $ \g0 -> do
+                withGeometry ctx reader wkt1 $ \g1 -> do
+                    bracket (c_GEOSIntersection_r ctx g0 g1) (c_GEOSGeom_destroy_r ctx) $ \g2 -> do
+                        withWKTWriter ctx $ \writer -> do
+                            str <- bracket
+                                (c_GEOSWKTWriter_write_r ctx writer g2)
+                                (c_GEOSFree_r_CString ctx)
+                                peekCString
+                            putStrLn str
+                            putStrLn "LowLevelAPI.demo done"
+    where
+        withGEOS :: (GEOSContextHandle_t -> IO a) -> IO a
+        withGEOS = bracket c_initializeGEOSWithHandlers c_finishGEOS_r
+        withWKTReader :: GEOSContextHandle_t -> (GEOSWKTReaderPtr -> IO a) -> IO a
+        withWKTReader ctx = bracket (c_GEOSWKTReader_create_r ctx) (c_GEOSWKTReader_destroy_r ctx)
+        withWKTWriter :: GEOSContextHandle_t -> (GEOSWKTWriterPtr -> IO a) -> IO a
+        withWKTWriter ctx = bracket (c_GEOSWKTWriter_create_r ctx) (c_GEOSWKTWriter_destroy_r ctx)
+        withGeometry :: GEOSContextHandle_t -> GEOSWKTReaderPtr -> CString -> (GEOSGeometryPtr -> IO a) -> IO a
+        withGeometry ctx reader wkt =
+            bracket
+                (c_GEOSWKTReader_read_r ctx reader wkt)
+                (c_GEOSGeom_destroy_r ctx)
diff --git a/src/app/Main.hs b/src/app/Main.hs
--- a/src/app/Main.hs
+++ b/src/app/Main.hs
@@ -1,84 +1,17 @@
+{-# LANGUAGE RecordWildCards #-}
+
 module Main (main) where
 
-import Control.Exception
 import Data.Geolocation.GEOS
-import Data.Geolocation.GEOS.Imports
 import Foreign.C
-import Foreign.Ptr
-import Paths_hgeos
-
--- Demonstrates direct use of imports
--- Lifetimes of various GEOS objects, including readers, writers and
--- geometries, must be managed explicitly by clients using explicit calls to
--- various destroy/free functions
-lowLevelAPIDemo :: IO ()
-lowLevelAPIDemo = do
-    wkt0 <- newCString "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"
-    wkt1 <- newCString "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"
-
-    withGEOS $ \ctx -> do
-        withWKTReader ctx $ \reader -> do
-            withGeometry ctx reader wkt0 $ \g0 -> do
-                withGeometry ctx reader wkt1 $ \g1 -> do
-                    bracket (c_GEOSIntersection_r ctx g0 g1) (c_GEOSGeom_destroy_r ctx) $ \g2 -> do
-                        withWKTWriter ctx $ \writer -> do
-                            str <- bracket
-                                (c_GEOSWKTWriter_write_r ctx writer g2)
-                                (c_GEOSFree_r_CString ctx)
-                                peekCString
-                            putStrLn str
-                            putStrLn "lowLevelAPIDemo done"
-    where
-        withGEOS :: (GEOSContextHandle_t -> IO a) -> IO a
-        withGEOS = bracket c_initializeGEOSWithHandlers c_uninitializeGEOS
-        withWKTReader :: GEOSContextHandle_t -> (GEOSWKTReaderPtr -> IO a) -> IO a
-        withWKTReader ctx = bracket (c_GEOSWKTReader_create_r ctx) (c_GEOSWKTReader_destroy_r ctx)
-        withWKTWriter :: GEOSContextHandle_t -> (GEOSWKTWriterPtr -> IO a) -> IO a
-        withWKTWriter ctx = bracket (c_GEOSWKTWriter_create_r ctx) (c_GEOSWKTWriter_destroy_r ctx)
-        withGeometry :: GEOSContextHandle_t -> GEOSWKTReaderPtr -> CString -> (GEOSGeometryPtr -> IO a) -> IO a
-        withGeometry ctx reader wkt =
-            bracket
-                (c_GEOSWKTReader_read_r ctx reader wkt)
-                (c_GEOSGeom_destroy_r ctx)
-
--- 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
-highLevelAPIDemo :: IO ()
-highLevelAPIDemo = do
-    withContext $ \ctx -> do
-        reader <- mkReader ctx
-        g0 <- readGeometry reader "POLYGON (( 10 10, 10 20, 20 20, 20 10, 10 10 ))"
-        g1 <- readGeometry reader "POLYGON (( 11 11, 11 12, 12 12, 12 11, 11 11 ))"
-        g2 <- intersection g0 g1
-        writer <- mkWriter ctx
-        str <- writeGeometry writer g2
-        putStrLn str
-        putStrLn "highLevelAPIDemo done"
+import qualified HighLevelAPI
+import qualified LowLevelAPI
+import qualified Sample
 
 main :: IO ()
 main = do
-    --s <- peekCString c_GEOSversion
-    --putStrLn s
-    --lowLevelAPIDemo
-    --highLevelAPIDemo
-    namibiaDemo
-
-printGeometry :: Writer -> Geometry -> IO ()
-printGeometry r g = writeGeometry r g >>= putStrLn
-
-namibiaDemo :: IO ()
-namibiaDemo = do
-    fileName <- getDataFileName "data/namibia.wkt"
-    wkt <- readFile fileName
-    withContext $ \ctx -> do
-        reader <- mkReader ctx
-        writer <- mkWriter ctx
-        let p = printGeometry writer
-
-        country <- readGeometry reader wkt
-        env <- envelope country
-        shell <- exteriorRing env
-        coordSeq <- coordinateSequence shell
-        p shell
-        return ()
+    v <- version
+    putStrLn v
+    LowLevelAPI.demo
+    HighLevelAPI.demo
+    Sample.demo
diff --git a/src/app/Sample.hs b/src/app/Sample.hs
new file mode 100644
--- /dev/null
+++ b/src/app/Sample.hs
@@ -0,0 +1,150 @@
+{-# LANGUAGE RecordWildCards #-}
+
+module Sample (demo) where
+
+import Control.Monad
+import Data.Geolocation.GEOS
+import Data.List
+import Data.String.Utils
+import Paths_hgeos
+import Text.Printf
+
+printGeometry :: Writer -> Geometry -> IO ()
+printGeometry r g = writeGeometry r g >>= putStrLn
+
+type Coordinate = (Double, Double, Double)
+
+getXYZs :: CoordinateSequence -> IO (Maybe [Coordinate])
+getXYZs coordSeq = do
+    maybeSize <- getSize coordSeq
+    case maybeSize of
+         Nothing -> return Nothing
+         Just size -> do
+             xyzs <- forM [0..(size - 1)] $ \i -> do
+                 (Just x) <- getX coordSeq i
+                 (Just y) <- getY coordSeq i
+                 (Just z) <- getZ coordSeq i
+                 return (x, y, z)
+             return $ Just xyzs
+
+data Extent = Extent
+    { minX :: Double
+    , maxX :: Double
+    , minY :: Double
+    , maxY :: Double
+    , minZ :: Double
+    , maxZ :: Double
+    } deriving Show
+
+extent :: [Coordinate] -> Extent
+extent ((x, y, z) : cs) =
+    let (minX, maxX, minY, maxY, minZ, maxZ) =
+            foldr (\(x', y', z') (minX, maxX, minY, maxY, minZ, maxZ) ->
+                   (if x' < minX then x' else minX,
+                    if x' > maxX then x' else maxX,
+                    if y' < minY then y' else minY,
+                    if y' > maxY then y' else maxY,
+                    if z' < minZ then z' else minZ,
+                    if z' > maxX then z' else maxZ)) (x, x, y, y, z, z) cs
+    in Extent minX maxX minY maxY minZ maxZ
+
+mfloor :: Double -> Double -> Double
+mfloor m x = (fromInteger $ floor (x / m)) * m
+
+frange :: Double -> Double -> Double -> [Double]
+frange lower upper step =
+    let count = (upper - lower) / step
+    in [lower + (fromIntegral i) * step | i <- [0..(round count - 1)]]
+
+type Longitude = Double
+type Latitude = Double
+type Resolution = Double
+
+mkSquare :: Reader -> Longitude -> Latitude -> Resolution -> IO Geometry
+mkSquare reader longitude latitude resolution =
+    let points = [
+            (longitude, latitude),
+            (longitude + resolution, latitude),
+            (longitude + resolution, latitude + resolution),
+            (longitude, latitude + resolution),
+            (longitude, latitude)
+            ]
+        wkt = printf "POLYGON ((%s))" (intercalate "," (map (\(a, b) -> printf "%f %f" a b) points))
+    in readGeometry reader wkt
+
+getGeometries :: Geometry -> IO [Geometry]
+getGeometries geometry = do
+    count <- getNumGeometries geometry
+    forM [0..(count - 1)] (getGeometry geometry)
+
+findBiggestPolygon :: Geometry -> IO Geometry
+findBiggestPolygon geometry = do
+    geometries@(g : gs) <- getGeometries geometry
+    a : as <- sequence $ map area geometries
+    let (g', _) = foldr (\p@(_, a') biggest@(_, aBiggest) -> if a' > aBiggest then p else biggest) (g, a) (zip gs as)
+    return g'
+
+resolution :: Double
+resolution = 1.0
+
+processPolygon :: String -> Resolution -> Longitude -> Latitude -> Geometry -> IO ()
+processPolygon tableName resolution longitude latitude p = do
+    let pId = polygonId resolution longitude latitude
+    shell <- exteriorRing p
+    coordSeq <- coordinateSequence shell
+    (Just xyzs) <- getXYZs coordSeq
+    forM_ (zip [0..] xyzs) $ \(pointId, (x, y, _)) -> do
+        let s = printf
+                    "INSERT INTO %s (polygon_id, point_id, longitude, latitude) VALUES ('%s', %d, %f, %f);\n"
+                    tableName
+                    pId
+                    (pointId :: Int)
+                    x
+                    y
+        putStr s
+
+polygonId :: Resolution -> Longitude -> Latitude -> String
+polygonId resolution longitude latitude = "id_" ++ formatValue longitude ++ "_" ++ formatValue latitude
+    where
+        formatValue :: Double -> String
+        formatValue = replace "-" "m" . replace "." "_" . (printf "%.2f") . mfloor resolution
+
+-- A more involved example of use of API
+demo :: IO ()
+demo = do
+    fileName <- getDataFileName "data/namibia.wkt"
+    wkt <- readFile fileName
+    withGEOS $ \ctx -> do
+        reader <- mkReader ctx
+        writer <- mkWriter ctx
+        let p = printGeometry writer
+
+        country <- readGeometry reader wkt
+        env <- envelope country
+        shell <- exteriorRing env
+        coordSeq <- coordinateSequence shell
+        (Just xyzs) <- getXYZs coordSeq
+        forM_ xyzs $ \(x, y, z) -> print (x, y, z)
+        let Extent{..} = extent xyzs
+            mfloorRes = mfloor resolution
+            longitudeBegin = mfloorRes minX
+            longitudeEnd = mfloorRes maxX + resolution
+            latitudeBegin = mfloorRes minY
+            latitudeEnd = mfloorRes maxY + resolution
+        print longitudeBegin
+        print longitudeEnd
+        print latitudeBegin
+        print 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 <- intersection square country
+            x <- isEmpty overlap
+            unless x $ do
+                id <- geometryTypeId overlap
+                polygon <- case id of
+                                MultiPolygon -> findBiggestPolygon overlap
+                                Polygon -> return overlap
+                processPolygon "foo" resolution longitude latitude polygon
+    putStrLn "Sample.demo done"
diff --git a/src/lib/Data/Geolocation/GEOS.hs b/src/lib/Data/Geolocation/GEOS.hs
--- a/src/lib/Data/Geolocation/GEOS.hs
+++ b/src/lib/Data/Geolocation/GEOS.hs
@@ -11,6 +11,10 @@
 management of lifetimes of objects such as readers, writers and geometries.
 
 For the low-level FFI bindings, see "Data.Geolocation.GEOS.Imports".
+
+<https://github.com/rcook/hgeos/blob/master/src/app/HighLevelAPI.hs View sample 1>
+
+<https://github.com/rcook/hgeos/blob/master/src/app/Sample.hs View sample 2>
 -}
 
 {-# LANGUAGE RecordWildCards #-}
@@ -19,23 +23,38 @@
     ( Context ()
     , CoordinateSequence ()
     , Geometry ()
+    , GeometryTypeId (..)
     , Reader ()
     , Writer ()
+    , area
     , coordinateSequence
     , envelope
     , exteriorRing
+    , geometryTypeId
+    , getGeometry
+    , getNumGeometries
+    , getSize
+    , getX
+    , getY
+    , getZ
     , intersection
+    , isEmpty
     , mkReader
     , mkWriter
     , readGeometry
-    , withContext
+    , version
+    , withGEOS
     , writeGeometry
     ) where
 
 import Control.Exception
 import Data.Geolocation.GEOS.Imports
 import Data.IORef
+import Data.Word
 import Foreign.C
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+import Foreign.Storable
 
 -- |Represents a <https://trac.osgeo.org/geos/ GEOS> context
 data Context = Context ContextStateRef
@@ -53,6 +72,17 @@
 -- |References a <https://trac.osgeo.org/geos/ GEOS> coordinate sequence
 data CoordinateSequence = CoordinateSequence ContextStateRef GEOSCoordSequencePtr
 
+-- |Represents a <https://trac.osgeo.org/geos/ GEOS> geometry type ID
+data GeometryTypeId =
+    Point |
+    LineString |
+    LinearRing |
+    Polygon |
+    MultiPoint |
+    MultlLineString |
+    MultiPolygon |
+    GeometryCollection deriving (Enum, Show)
+
 -- |References a <https://en.wikipedia.org/wiki/Well-known_text WKT> reader
 data Reader = Reader ContextStateRef GEOSWKTReaderPtr
 
@@ -62,6 +92,18 @@
 -- |References a <https://trac.osgeo.org/geos/ GEOS> geometry
 data Geometry = Geometry ContextStateRef GEOSGeometryPtr
 
+-- |Returns area of a 'Geometry' instance
+area :: Geometry -> IO (Maybe 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
+             _ -> do
+                value <- peek valuePtr
+                return $ Just (realToFrac value)
+
 -- |Returns a 'CoordinateSequence' from the supplied 'Geometry'
 coordinateSequence :: Geometry -> IO CoordinateSequence
 coordinateSequence (Geometry sr hGeometry) = do
@@ -89,12 +131,74 @@
 exteriorRing (Geometry sr h) =
     doNotTrack sr (\hCtx -> c_GEOSGetExteriorRing_r hCtx h)
 
+-- |Returns type ID of a 'Geometry' instance
+geometryTypeId :: Geometry -> IO GeometryTypeId
+geometryTypeId (Geometry sr h) = do
+    ContextState{..} <- readIORef sr
+    value <- c_GEOSGeomTypeId_r hCtx h
+    return $ toEnum (fromIntegral value)
+
+-- |Returns child 'Geometry' at given index
+getGeometry :: Geometry -> Int -> IO Geometry
+getGeometry (Geometry sr h) index =
+    doNotTrack sr (\hCtx -> c_GEOSGetGeometryN_r hCtx h (fromIntegral index))
+
+-- |Gets the number of geometries in a 'Geometry' instance
+getNumGeometries :: Geometry -> IO Int
+getNumGeometries (Geometry sr h) = do
+    ContextState{..} <- readIORef sr
+    value <- c_GEOSGetNumGeometries_r hCtx h
+    return $ fromIntegral value
+
+getOrdinate :: (GEOSContextHandle_t -> GEOSCoordSequencePtr -> CUInt -> Ptr CDouble -> IO CInt) ->
+    CoordinateSequence -> Word -> IO (Maybe Double)
+getOrdinate f (CoordinateSequence sr h) index = do
+    ContextState{..} <- readIORef sr
+    alloca $ \valuePtr -> do
+        status <- f hCtx h (fromIntegral index) valuePtr
+        case status of
+             0 -> return Nothing
+             _ -> do
+                value <- peek valuePtr
+                return $ Just (realToFrac value)
+
+-- |Gets the size from a coordinate sequence
+getSize :: CoordinateSequence -> IO (Maybe 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
+             _ -> do
+                 size <- peek sizePtr
+                 return $ Just (fromIntegral size)
+
+-- |Gets an "x" ordinate value from a coordinate sequence
+getX :: CoordinateSequence -> Word -> IO (Maybe Double)
+getX = getOrdinate c_GEOSCoordSeq_getX_r
+
+-- |Gets a "y" ordinate value from a coordinate sequence
+getY :: CoordinateSequence -> Word -> IO (Maybe Double)
+getY = getOrdinate c_GEOSCoordSeq_getY_r
+
+-- |Gets a "z" ordinate value from a coordinate sequence
+getZ :: CoordinateSequence -> Word -> IO (Maybe Double)
+getZ = getOrdinate c_GEOSCoordSeq_getZ_r
+
 -- |Returns a 'Geometry' instance representing the intersection of the two
 -- supplied 'Geometry' instances:
 intersection :: Geometry -> Geometry -> IO Geometry
 intersection (Geometry sr0 h0) (Geometry sr1 h1) =
     track sr0 (\hCtx -> c_GEOSIntersection_r hCtx h0 h1)
 
+-- |Returns value indicating if specified 'Geometry' instance is empty
+isEmpty :: Geometry -> IO Bool
+isEmpty (Geometry sr h) = do
+    ContextState{..} <- readIORef sr
+    value <- c_GEOSisEmpty_r hCtx h
+    return $ value /= 0
+
 mkContext :: IO Context
 mkContext = do
     hCtx <- c_initializeGEOSWithHandlers
@@ -132,7 +236,7 @@
     mapM_ (c_GEOSGeom_destroy_r hCtx) hGeometries
     mapM_ (c_GEOSWKTWriter_destroy_r hCtx) hWriters
     mapM_ (c_GEOSWKTReader_destroy_r hCtx) hReaders
-    c_uninitializeGEOS hCtx
+    c_finishGEOS_r hCtx
 
 track :: ContextStateRef -> (GEOSContextHandle_t -> IO GEOSGeometryPtr) -> IO Geometry
 track sr f = do
@@ -141,19 +245,23 @@
     modifyIORef' sr $ (\p@ContextState{..} -> p { hGeometries = h : hGeometries })
     return $ Geometry sr h
 
+-- |Reports version of GEOS API
+version :: IO String
+version = c_GEOSversion >>= peekCString
+
 -- |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:
 --
 -- @
---    withContext $ \ctx -> do
+--    withGEOS $ \ctx -> do
 --
 --        -- Use context
 --
 --        return ()
 -- @
-withContext :: (Context -> IO a) -> IO a
-withContext = bracket mkContext releaseContext
+withGEOS :: (Context -> IO a) -> IO a
+withGEOS = bracket mkContext releaseContext
 
 -- |Serializes a 'Geometry' instance to a 'String' using the supplied 'Writer':
 writeGeometry :: Writer -> Geometry -> IO String
diff --git a/src/lib/Data/Geolocation/GEOS/Imports.hs b/src/lib/Data/Geolocation/GEOS/Imports.hs
--- a/src/lib/Data/Geolocation/GEOS/Imports.hs
+++ b/src/lib/Data/Geolocation/GEOS/Imports.hs
@@ -13,6 +13,8 @@
 high-level wrappers do not yet exist.
 
 For the high-level API, see "Data.Geolocation.GEOS".
+
+<https://github.com/rcook/hgeos/blob/master/src/app/LowLevelAPI.hs View sample>
 -}
 
 module Data.Geolocation.GEOS.Imports
@@ -21,12 +23,20 @@
     , GEOSGeometryPtr ()
     , GEOSWKTReaderPtr ()
     , GEOSWKTWriterPtr ()
+    , c_GEOSArea_r
+    , c_GEOSCoordSeq_destroy_r
+    , c_GEOSCoordSeq_getSize_r
+    , c_GEOSCoordSeq_getX_r
+    , c_GEOSCoordSeq_getY_r
+    , c_GEOSCoordSeq_getZ_r
     , c_GEOSEnvelope_r
     , c_GEOSFree_r_CString
-    , c_GEOSCoordSeq_destroy_r
+    , c_GEOSGeomTypeId_r
     , c_GEOSGeom_destroy_r
     , c_GEOSGeom_getCoordSeq_r
     , c_GEOSGetExteriorRing_r
+    , c_GEOSGetGeometryN_r
+    , c_GEOSGetNumGeometries_r
     , c_GEOSIntersection_r
     , c_GEOSWKTReader_create_r
     , c_GEOSWKTReader_destroy_r
@@ -34,9 +44,10 @@
     , c_GEOSWKTWriter_create_r
     , c_GEOSWKTWriter_destroy_r
     , c_GEOSWKTWriter_write_r
+    , c_GEOSisEmpty_r
     , c_GEOSversion
+    , c_finishGEOS_r
     , c_initializeGEOSWithHandlers
-    , c_uninitializeGEOS
     ) where
 
 import Foreign.C
@@ -57,10 +68,30 @@
 -- |Wraps @GEOSWKTWriter*@
 newtype GEOSWKTWriterPtr = GEOSWKTWriterPtr (Ptr GEOSWKTWriterPtr)
 
+-- |Wraps @GEOSArea_r@
+foreign import ccall "GEOSArea_r"
+    c_GEOSArea_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> Ptr CDouble -> IO CInt
+
 -- |Wraps @GEOSCoordSeq_destroy_r@
 foreign import ccall "GEOSCoordSeq_destroy_r"
     c_GEOSCoordSeq_destroy_r :: GEOSContextHandle_t -> GEOSCoordSequencePtr -> IO ()
 
+-- |Wraps @GEOSCoordSeq_getSize_r@
+foreign import ccall "GEOSCoordSeq_getSize_r"
+    c_GEOSCoordSeq_getSize_r :: GEOSContextHandle_t -> GEOSCoordSequencePtr -> Ptr CUInt -> IO CInt
+
+-- |Wraps @GEOSCoordSeq_getX_r@
+foreign import ccall "GEOSCoordSeq_getX_r"
+    c_GEOSCoordSeq_getX_r :: GEOSContextHandle_t -> GEOSCoordSequencePtr -> CUInt -> Ptr CDouble -> IO CInt
+
+-- |Wraps @GEOSCoordSeq_getY_r@
+foreign import ccall "GEOSCoordSeq_getY_r"
+    c_GEOSCoordSeq_getY_r :: GEOSContextHandle_t -> GEOSCoordSequencePtr -> CUInt -> Ptr CDouble -> IO CInt
+
+-- |Wraps @GEOSCoordSeq_getZ_r@
+foreign import ccall "GEOSCoordSeq_getZ_r"
+    c_GEOSCoordSeq_getZ_r :: GEOSContextHandle_t -> GEOSCoordSequencePtr -> CUInt -> Ptr CDouble -> IO CInt
+
 -- |Wraps @GEOSEnvelope_r@
 foreign import ccall "GEOSEnvelope_r"
     c_GEOSEnvelope_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO GEOSGeometryPtr
@@ -69,13 +100,9 @@
 foreign import ccall "GEOSFree_r"
     c_GEOSFree_r_CString :: GEOSContextHandle_t -> CString -> IO ()
 
--- |Wraps @GEOSGetExteriorRing_r@
-foreign import ccall "GEOSGetExteriorRing_r"
-    c_GEOSGetExteriorRing_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO GEOSGeometryPtr
-
--- |Wraps @GEOSIntersection_r@
-foreign import ccall "GEOSIntersection_r"
-    c_GEOSIntersection_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> GEOSGeometryPtr -> IO GEOSGeometryPtr
+-- |Wraps @GEOSGeomTypeId_r@
+foreign import ccall "GEOSGeomTypeId_r"
+    c_GEOSGeomTypeId_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO CInt
 
 -- |Wraps @GEOSGeom_destroy_r@
 foreign import ccall "GEOSGeom_destroy_r"
@@ -85,6 +112,22 @@
 foreign import ccall "GEOSGeom_getCoordSeq_r"
     c_GEOSGeom_getCoordSeq_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO GEOSCoordSequencePtr
 
+-- |Wraps @GEOSGetExteriorRing_r@
+foreign import ccall "GEOSGetExteriorRing_r"
+    c_GEOSGetExteriorRing_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO GEOSGeometryPtr
+
+-- |Wraps @GEOSGetGeometryN_r@
+foreign import ccall "GEOSGetGeometryN_r"
+    c_GEOSGetGeometryN_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> CInt -> IO GEOSGeometryPtr
+
+-- |Wraps @GEOSGetNumGeometries_r@
+foreign import ccall "GEOSGetNumGeometries_r"
+    c_GEOSGetNumGeometries_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO CInt
+
+-- |Wraps @GEOSIntersection_r@
+foreign import ccall "GEOSIntersection_r"
+    c_GEOSIntersection_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> GEOSGeometryPtr -> IO GEOSGeometryPtr
+
 -- |Wraps @GEOSWKTReader_create_r@
 foreign import ccall "GEOSWKTReader_create_r"
     c_GEOSWKTReader_create_r :: GEOSContextHandle_t -> IO GEOSWKTReaderPtr
@@ -109,10 +152,18 @@
 foreign import ccall "GEOSWKTWriter_write_r"
     c_GEOSWKTWriter_write_r :: GEOSContextHandle_t -> GEOSWKTWriterPtr -> GEOSGeometryPtr -> IO CString
 
+-- |Wraps @GEOSisEmpty_r@
+foreign import ccall "GEOSisEmpty_r"
+    c_GEOSisEmpty_r :: GEOSContextHandle_t -> GEOSGeometryPtr -> IO CChar
+
 -- |Wraps @GEOSversion@
 foreign import ccall "GEOSversion"
-    c_GEOSversion :: CString
+    c_GEOSversion :: IO CString
 
+-- |Wraps @finishGEOS_r@ helper function
+foreign import ccall "finishGEOS_r"
+    c_finishGEOS_r :: GEOSContextHandle_t -> IO ()
+
 -- |Wraps @getErrorMessage@ helper function
 foreign import ccall "helpers.h getErrorMessage"
     c_getErrorMessage :: IO CString
@@ -124,7 +175,3 @@
 -- |Wraps @initializeGEOSWithHandlers@ helper function
 foreign import ccall "helpers.h initializeGEOSWithHandlers"
     c_initializeGEOSWithHandlers :: IO GEOSContextHandle_t
-
--- |Wraps @uninitializeGEOS@ helper function
-foreign import ccall "helpers.h uninitializeGEOS"
-    c_uninitializeGEOS :: GEOSContextHandle_t -> IO ()
diff --git a/src/lib/Data/Geolocation/GEOS/helpers.c b/src/lib/Data/Geolocation/GEOS/helpers.c
new file mode 100644
--- /dev/null
+++ b/src/lib/Data/Geolocation/GEOS/helpers.c
@@ -0,0 +1,43 @@
+#include "helpers.h"
+#include <geos_c.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+//#define TRACE(message) printf(message "\n")
+#define TRACE(message) do {} while (0)
+
+__thread char g_noticeMessage[256];
+static const size_t s_noticeMessageLen = sizeof(g_noticeMessage) / sizeof(g_noticeMessage[0]);
+__thread char g_errorMessage[256];
+static const size_t s_errorMessageLen = sizeof(g_errorMessage) / sizeof(g_errorMessage[0]);
+
+static void noticeHandler(const char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    vsnprintf(g_noticeMessage, s_noticeMessageLen, format, args);
+    va_end(args);
+}
+
+static void errorHandler(const char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    vsnprintf(g_errorMessage, s_errorMessageLen, format, args);
+    va_end(args);
+}
+
+GEOSContextHandle_t initializeGEOSWithHandlers()
+{
+    return initGEOS_r(noticeHandler, errorHandler);
+}
+
+const char* getNoticeMessage()
+{
+    return g_noticeMessage;
+}
+
+const char* getErrorMessage()
+{
+    return g_errorMessage;
+}
diff --git a/src/lib/Data/Geolocation/GEOS/helpers.h b/src/lib/Data/Geolocation/GEOS/helpers.h
new file mode 100644
--- /dev/null
+++ b/src/lib/Data/Geolocation/GEOS/helpers.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "geos_c.h"
+
+GEOSContextHandle_t initializeGEOSWithHandlers();
+const char* getNoticeMessage();
+const char* getErrorMessage();
diff --git a/src/lib/helpers.c b/src/lib/helpers.c
deleted file mode 100644
--- a/src/lib/helpers.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "helpers.h"
-#include <geos_c.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-//#define TRACE(message) printf(message "\n")
-#define TRACE(message) do {} while (0)
-
-__thread char g_noticeMessage[256];
-static const size_t s_noticeMessageLen = sizeof(g_noticeMessage) / sizeof(g_noticeMessage[0]);
-__thread char g_errorMessage[256];
-static const size_t s_errorMessageLen = sizeof(g_errorMessage) / sizeof(g_errorMessage[0]);
-
-static void noticeHandler(const char* format, ...)
-{
-    va_list args;
-    va_start(args, format);
-    vsnprintf(g_noticeMessage, s_noticeMessageLen, format, args);
-    va_end(args);
-}
-
-static void errorHandler(const char* format, ...)
-{
-    va_list args;
-    va_start(args, format);
-    vsnprintf(g_errorMessage, s_errorMessageLen, format, args);
-    va_end(args);
-}
-
-GEOSContextHandle_t initializeGEOSWithHandlers()
-{
-    return initGEOS_r(noticeHandler, errorHandler);
-}
-
-void uninitializeGEOS(GEOSContextHandle_t handle)
-{
-    finishGEOS_r(handle);
-}
-
-const char* getNoticeMessage()
-{
-    return g_noticeMessage;
-}
-
-const char* getErrorMessage()
-{
-    return g_errorMessage;
-}
diff --git a/src/lib/helpers.h b/src/lib/helpers.h
deleted file mode 100644
--- a/src/lib/helpers.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-
-#include "geos_c.h"
-
-GEOSContextHandle_t initializeGEOSWithHandlers();
-void uninitializeGEOS(GEOSContextHandle_t handle);
-const char* getNoticeMessage();
-const char* getErrorMessage();
