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
metadirectives.py files in the ZCO codebase.
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
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")
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.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
For an efficient WMS implementation we will need to be able to cache the rendered tiles, possible using an existing solution like TileCache.
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