At the 2006 Plone Conference sprint, Shaun Walbridge and I wrote a Quadtree-based spatial index for Plone. Unlike the portal catalog, it was a localized index, turning a Plone folder of georeferenced content into a shapefile of sorts. It was a nice proof of concept, but was limited by lack of persistence. A few months ago Howard Butler made it possible to persist Rtree indexes on the filesystem, and last week I finally made the time to rewrite the original Plone product into a persistent R-tree index for Zope/Plone data.
SpatialIndex keeps its original design. Adapting a Plone folder to Products.SpatialIndex.interfaces.ISpatialIndex creates an index on disk alongside the ZODB data, with a name that corresponds to the folder's physical path. Content objects can then be adapted to Products.PleiadesGeocoder.interfaces.IGeoItemSimple and added to the index. Ultimately, the index may be queried for the records of items that intersect with a bounding box. The capabilities are summarized in the session below, using a parks folder that contains a lee-martinez document:
>>> parks = app['plone']['parks']
>>> document = parks['lee-martinez']
>>> from Products.SpatialIndex.interfaces import ISpatialIndex
>>> index = ISpatialIndex(parks)
>>> from Products.PleiadesGeocoder.interfaces import IGeoItemSimple
>>> geoitem = IGeoItemSimple(document)
>>> geoitem.setGeoInterface('Point', (-105.08442, 40.59512))
>>> index.add(geoitem)
>>> hits = index.intersects((-106, 40, -105, 41))
>>> [h for h in hits]
[('lee-martinez', (-105.08442, 40.59512, -105.08442, 40.59512)]
SpatialIndex depends on
You should get PleiadesGeocoder 1.0a1 and SpatialIndex 1.0a1 from the repositories:
$ svn co http://icon.stoa.org/svn/pleiades/PleiadesGeocoder/tags/rel-1.0a1\ PleiadesGeocoder $ svn co http://svn.gispython.org/svn/primagis/SpatialIndex/tags/rel-1.0a1\ SpatialIndex
Additionally, SpatialIndex provides a yet-under-construction index management view through which you count the indexed items and reindex folders, and another public view (@@spatialindex) that can be used in various custom forms and pages.
>>> import pickle
>>> import rtree
>>> import shapely
>>> store['geom0'] = shapely.geometry.Point(0, 0)
>>> index = rtree.Rtree('the_points')
>>> for key, geom in store.items():
... index.add(hash(key), geom.bounds)
>>> f = open('the_points.pik', 'wb')
>>> pickle.dump(store, f)
>>> f.close()
That would produce a Python shapefile of sorts: the_points.pik, the_points.idx, and the_points.dat.
Comments are closed after 13 days.
Some rights reserved 2008 by Sean Gillies.
1Re: Plone R-Tree Spatial Index
Yves Moisan, 2007-10-23T17:40:19Z