PCL Features User Story

To date, PCL's feature model has been a bit weak. This wiki node is all about describing the use cases, and design of a good feature model.

Story

What do we want from a feature? It should encapsulate geometries and other attributes. It should provide simple, Python-ic access to the attributes (unlike MapScript?). It should be simple and use Python's capacity for introspection. Features should be equally valid in stand-alone mode or when selected from a FeatureSource?.

Features should be based on GML 3, but not necessarily be implemented as XML-ish infosets. Features should be serializeable to GML 2 and 3, also to JSON, and easy to use within Zope page templates. They should have a unique id. We should have ready access to the schema of types of features. A feature should be able to have several geometries.

Feature sources should be factories for feature types.

Example

Here's an example of how we'd get features from a data store

# open a feature store on an OGR virtual file
store = FeatureStore('world_borders.ovf')

# tap into a source by its typename
source = store.source('world_borders')

# get the schema of the source
assert source.schema() == \
{ 'CAT': 'float', 'FIPS_CNTRY': 'string', 
  'CNTRY_NAME': 'string', 'AREA': 'float',
  'POP_CNTRY: 'float', 'the_geom': "<class 'cartography.spatial.Polygon'>"}

# get the feature type of this source
featuretype = source.featuretype()
assert str(featuretype) == "<class '__main__.World_borders_Type'>"

# this class actually provides the schema
assert featuretype.schema() == \
{ 'CAT': 'float', 'FIPS_CNTRY': 'string', 
  'CNTRY_NAME': 'string', 'AREA': 'float',
  'POP_CNTRY: 'float', 'the_geom': "<class 'cartography.spatial.Polygon'>"}

# get a feature (the first) from the source
feature = source.iterfeatures().next()

# it's an instance of the featuretype
assert isinstance(feature, World_borders_Type)

# here's an example of iterating over all properties of the feature
f = feature.properties()
for pname in featuretype.schema().keys():
    print pname, getattr(f, pname)

# above produces something like
# 
# the_geom <cartography.spatial.Polygon instance at 0xf6d54c8c>
# CAT 1.0
# FIPS_CNTRY AA
# CNTRY_NAME Aruba
# AREA 193.0
# POP_CNTRY 71218.0

In a page template, you'd display all properties of a feature like

<tr tal:repeat="pname python:feature.schema().keys()">
<td tal:content="pname">NAME</td>
<td tal:content="feature/properties/?pname">VALUE</td>
</tr>

Design

Once we require features to have methods supporting serialization and schemas, we can no longer implement them as simple Python types like a dict. We will need classes.

Here's a very simple UML diagram showing a combo of specification and implementation:

FeatureStore? and FeatureSource? currently exist in PCL. A FeatureSource? shall be able to generate a new class ("DerivedFeature" in this example), derived from Feature, which serves as that source's FeatureType?. Python's type() function will let us do this kind of simple metaclass programming.

Geometries are shown in the diagram for completeness, but will be discussed elsewhere. Non-geometry attributes will be implemented as Python properties. All of these properties will be collected within a feature attribute.

Attachments