geos-0.3.0: src/Data/Geometry/Geos/STRTree.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-|
Module : Data.Geometry.Geos.STRTree
Maintainer : pfrance@gmail.com
A query-only R-tree created using the Sort-Tile-Recursive (STR) algorithm. For two-dimensional spatial data.
The STR packed R-tree is simple to implement and maximizes space utilization; that is, as many leaves as possible are filled to capacity. Overlap between nodes is far less than in a basic R-tree. However, once the tree has been built (explicitly or on the first call to query), items may not be added or removed.
Described in: P. Rigaux, Michel Scholl and Agnes Voisard. Spatial Databases With Application To GIS. Morgan Kaufmann, San Francisco, 2002.
-}
module Data.Geometry.Geos.STRTree
( foldr
, toList
, toVector
, fromList
, empty
, build
, insert
, fromFoldable
, fromFoldable_
, lookup
, RT.STRTree
, RT.STRTreeBuilder
)
where
import Prelude hiding ( foldr
, lookup
)
import qualified Data.Geometry.Geos.Raw.STRTree
as RT
import qualified Data.Geometry.Geos.Raw.Geometry
as RG
import Data.Geometry.Geos.Geometry
import Data.Geometry.Geos.Raw.Base
import Foreign
import qualified Data.Vector as V
-- can't make instance of Foldable because of Storable constraint
foldr :: (Storable a) => (a -> b -> b) -> b -> RT.STRTree a -> b
foldr f a = runGeos . RT.foldr f a
-- unfortunately, the api exposed by geos does not allow retrieval of original geometries
toList :: Storable a => RT.STRTree a -> [a]
toList = foldr (:) []
toVector :: Storable a => RT.STRTree a -> V.Vector a
toVector = foldr V.cons V.empty
fromList :: Storable b => [(Geometry a, b)] -> RT.STRTree b
fromList = fromFoldable
empty :: RT.STRTreeBuilder a
empty = runGeos $ RT.createSTRTreeBuilder 10
build :: RT.STRTreeBuilder a -> RT.STRTree a
build = runGeos . RT.build
insert :: Storable a => Geometry b -> a -> RT.STRTreeBuilder a -> ()
insert geom item tree = runGeos $ do
rg :: RG.GeomConst <- convertGeometryToRaw geom
RT.insert tree rg item
return ()
{-|
`fromFoldable` creates an STRTree with a default node capacity of 10. For finer-grained control over the node capacity, `fromFoldable_` accepts a node-capacity argument.
-}
fromFoldable :: (Foldable f, Storable b) => f (Geometry a, b) -> RT.STRTree b
fromFoldable = fromFoldable_ 10
fromFoldable_
:: (Foldable f, Storable b) => Int -> f (Geometry a, b) -> RT.STRTree b
fromFoldable_ capacity things = runGeos $ do
tree <- RT.createSTRTreeBuilder capacity
mapM_ (ins tree) things
RT.build tree
where
ins tree' (g, b) = do
rg :: RG.GeomConst <- convertGeometryToRaw g
RT.insert tree' rg b
{-|
Queries the index for all items whose extents intersect the given search Envelope.
Note that some kinds of indexes may also return objects which do not in fact intersect the query envelope.
-}
lookup :: Storable b => Geometry a -> RT.STRTree b -> V.Vector b
lookup g tree = runGeos $ do
rg :: RG.GeomConst <- convertGeometryToRaw g
RT.query tree rg