RSS

PrimaGIS in Plone 3.0

12 Feb

Up to (and including) version 0.6 PrimaGIS has been a traditional Archetypes based project. Almost all map components (maps, layers, symbolizers, etc) were modelled and implemented as AT content types.

Having all the components be full-blown AT content types made development easy up to a certain point but also at the same time made the objects unnecessarily heavy. Also, most map components are not content-like by nature and thus, for example, having them all support Dublin Core and be indexed in the portal catalog is unnecessary.

The next major version of PrimaGIS is based on Zope 3 components.

Using the Component Architecture

The Zope 3 Component Architecture made it relatively easy to remodel the map components as light-weight domain objects . In most cases we are now able to use objects from the Python Cartographic Library (PCL) directly, where earlier versions needed to define wrappers around these PCL objects. One reason for this is that PCL uses zope.interface internally, so useful interfaces are already defined and available for use.

In Plone 3.0 map renderers, spatial data stores and feature symbolizers are registered as utilities in the Component Architecture using ZCML. The components are registered using custom ZCML directives defined under the http://namespaces.gispython.org/gis namespace. For details on the custom directive implementation you can refer to the metaconfigure.py and metadirectives.py files in the ZCO codebase.

Map renderer

A map renderer is a component that is responsible of rendering the final map image given a collection of map layers (and some metadata). The current map renderer in PrimaGIS is based on the MapServer project. It is registered using the following ZCML code:



  
      incoming="/tmp"
      fontset="/tmp/pg2/spatialdata/fonts/fontset.txt"
     />


which registers the MapServer based renderer as an unnamed utility providing cartography.styles.interfaces.IMapRenderer.

In the future we can also support other map renderers and swap them transparently by registering them instead of the MapServer renderer — without having to modify any existing map setups.

To acquire the map renderer in code we can now simply do:


>>> from cartography.styles.interfaces import IMapRenderer
>>> from zope.component import getUtility
>>> renderer = getUtility(IMapRenderer)

Spatial data stores

Data stores are components that provide the spatial data for map layers. Data stores can be divided into two categories: feature stores that provide vector data and raster stores that provide raster data.

The data stores are registered using custom ZCML directives. Each type of data store has its own parameters, but all are registered as named utilities providing cartography.data.interfaces.IDataStore. Below is an example of a Web Map Service (WMS) data store registered in ZCML.



    name="NASA Jet Propulsion Laboratory WMS"
    url="http://wms.jpl.nasa.gov/wms.cgi"
    version="1.1.1"
    incoming="/tmp"
    />

For a more comprehensive set of examples see the datastores.zcml.dist file in the ZCO codebase. Registered data stores can now be easily acquired in code:


>>> from cartography.data.interfaces import IDataStore
>>> from zope.component import getUtility
>>> datastore = getUtility(IDataStore, "Name of data store")

Symbolizers

Feature symbolizers determine how selected spatial features are rendered on the map and in concept are similar to CSS rules. In a similar manner the symbolizers are defined and registered using ZCML. The four different types of symbolizers: point, line, polygon and text symbolizers, are each registered using their respective ZCML directives.

The symbolizers get registered as named utilities providing cartography.styles.interfaces.ISLDSymbolizer. Below is an example of a line symbolizer defined in ZCML.



   


For a comprehensive set of examples see the symbolizers.zcml.dist in the ZCO codebase.

Maps and Layers

Maps are composite objects that contains one or more layers. Each layer draws data from a spatial data source and determines the styling (using rules and symbolizers) applied to its spatial features. For maps and layers there is benefit in modeling them as content types, for example to be able to apply workflow to maps or individual layers or allow the layers to be managed using the default folder management methods.

For this reason, primagis.map.Map and primagis.layer.Layer are Archetypes derived content types. However, the AT schema mechanism is not used to manage the configuration of the components themselves, but used only to manage the content like attributes such as Dublin Core metadata. This gives us a nice separation of concerns between the content related attributes and the actual mapping attributes.

The map configuration forms are implemented using Zope 3 schemas and formlib. There are some custom schema fields and widgets that make it easier to manage the mapping specific attributes, such as bounding boxes. KSS has also been used to make the editing screens more user-friendly. In the future KSS might also be used in the map view also.

Web Map Service (WMS)

The Web Map Service support makes it possible to share and re-use the imagery produced by PrimaGIS in other WMS compliant clients such as, for example, uDig, OpenLayers, and PrimaGIS itself. OpenLayers is of special interest to PrimaGIS since it allows us to provide an alternative UI for PrimaGIS itself.

OpenLayers uses a tiled approach where the map image is put together by tiling multiple smaller images requested from the WMS server. It also provides a nice Google Maps like panning mode previously not available in PrimaGIS.

The WMS support is implemented as a Zope 3 view registered as wms for primagis.interfaces.IMap. This means that you can just point your WMS client to an URL like http://domain.tld/path/to/primagis/@@wms.

For an efficient WMS implementation we will need to be able to cache the rendered tiles, possible using an existing solution like TileCache.

Future work

Below are listed some features (in no particular order) I would like to see in PrimaGIS.

  • Persistent local versions of data stores and symbolizers
  • Management UI for the local data stores and symbolizers
  • Cached WMS requests
  • GeoRSS support
  • Better OpenLayers integration / configuration support
  • Spatial indexing
  • ZODB datastores
 
5 Comments

Posted by on February 12, 2007 in plone, primagis, zope

 

5 responses to “PrimaGIS in Plone 3.0

  1. Joel

    February 14, 2007 at 18:54

    Kai,

    Thanks for taking the time to do this excellent write up.

     
  2. Yves Moisan

    February 23, 2007 at 23:55

    Kai,

    I remember reading your Archetypes code as a reference to help me learn AT way back when there was no release of PrimaGIS. At the time, I was pleased with the rigor, which also showed in some of the emails on the list where you patiently answered my questions about how to extend some of your classes for my purposes. That was two years ago.

    This post shows once again that you and Sean are outstanding programmers. No brown-nosing here : I mean it. I hope to be back on the PrimaGIS project soon. Come Plone 3.0 so that I can force my co-workers to hop in with me:-)

    Good luck !

     
  3. Richard Cooper

    April 20, 2007 at 6:36

    Kai,

    I would like to make available GIS layers on existing PrimaGIS instances as WMS/WFS layers.

    Would it be possible to enable WMS/WFS services with the existing PrimaGIS version?

    Kind regards,

    Richard.

     
  4. dokai

    April 21, 2007 at 21:04

    Hi Richard

    Currently, in the 0.6 series of PrimaGIS, there is unfortunately no switch to enable WMS/WFS server support.

    Implementing a subset of the WMS specification to enable PrimaGIS to serve images would not require much coding though. I wrote a rudimentary WMS server implementation on the primagis-plone-3.0 development branch which you can take a look at if you’re interested in backporting this to the 0.6 series. The code is at http://trac.gispython.org/projects/PrimaGIS/browser/PrimaGIS/branches/primagis-plone-3.0/primagis/browser/map/wms.py

    We should continue discussing this issue on the gispython.org mailing list.

    cheers,
    Kai

     

Leave a reply to Yves Moisan Cancel reply