.. _rfc48:

======================================================================
MS RFC 48: GEOTRANSFORM Geometry operations
======================================================================

:Date: 2008/11/01
:Authors: Thomas Bonfort, Stephen Lime, 
:Contact:  thomas.bonfort at camptocamp.com, Steve.Lime at DNR.State.MN.US
:Status: Implemented (2009/02)
:Last Edited: 2009/02
:Version: MapServer 5.4

Summary
------------------------------------------------------------------------------

The purpose of this RFC is to add the ability to MapServer  to interpret the
geometries based on a user-defined GEOMETRYTRANSFORM keyword, and to render
the interpreted geometry with the selected styling

An example usage would be:

::

    GEOMETRYTRANSFORM "start([geom])"

to treat the underlying geometry as a point rendered on the first vertex
current feature.

The directive to activate this behavior is the GEOMETRYTRANSFORM keyword, that
initially belongs to the STYLE object. Further developments could be to enable
the keyword at the LAYER level.

Usages of this parameter include drawing bounding boxes of underlying
geometries, or adding arrowheads/tails to lines.

Further developments would allow complex expressions to be passed to the
keyword, allowing nested transformations to the underlying geometry, eg:

::

    GEOMETRYTRANSFORM "difference([geom],buffer([geom],10))"

and binding to attributes, eg:

::

    GEOMETRYTRANSFORM "buffer([geom],[distance])"

Detailed functionality
------------------------------------------------------------------------------

The GEOMETRYTRANSFORM keyword initially accepts a shortcut version of
these parameters :

- *bbox* : render a shapeObj representing the bounding box of the 
  underlying geometry.
- *start/end* : render a point symbol at the first/last vertex of the
  underlying geometry. By default, the symbol is oriented to match the 
  orientation of the corresponding geometry segment. This would be used
  to add arrowheads/tails to linestrings.
- *vertices* : render a point symbol at each vertex of the geometry.
  The default orientation matches the half angle of the corresponding segments. 
  The start and end vertices are not included in the transformation.

These transforms are not initially implemented, but could be supported in the future:

- *buffer([geom],distance)* : render a shapeObj representing the buffered geometry.
  "distance" specifies the buffer distance, in layer units.
- *centroid([geom])* : render a pointObj at the location of the centroid of the
  geometry
- *labelpoint([geom])* : render a pointObj at the location of the at the point
  where the geometry will/would be labelled.
- *convexhull([geom])* 
- *simplify([geom])*

Implementation Details
------------------------------------------------------------------------------

Apart from the parsing and internal storage of which type should be used,
the modifications of this RFC only affect the high-level rendering functions
in mapdraw.c .

There are three main modifications:

- AUTO is added to the ANGLE parser for the STYLE block. styleObj has an autoangle
  member added accordingly.

- inside msDrawVectorLayer, a copy of the shape before being clipped by the
  current extent must be kept, as the whole shape must be used for all but
  the VERTICES type. Then, when looping through the different styles that 
  can be applied, we switch off to the type-specific function if a GEOMETRYTRANSFORM 
  keyword is set.

- inside mapgeomtransform.c, the type-specific drawing function is added. Depending
  on the current style type, it either computes a new shape from the
  original shape (types bbox, convexhull or buffer) and passes it to the
  msDrawShadeSymbol, or calls msDrawMarkerSymbol for points of the original
  shape (types start, end, vertices, centroid) after having adjusted the
  orientation accordingly.

Affected Files
------------------------------------------------------------------------------

- mapdraw.c

- maplexer.c/.l

- mapfile.c

- mapserver.h

- mapgeometrytransform.c is added, for the parsing of the transform expression,
  the transformation itself, and the calling of msDrawMarkerSymbol /
  msDrawShadeSymbol functions

Limitations
------------------------------------------------------------------------------

For line layers, the transformations do not fit in with the current cache
mechanism that draws the first style of each class in a first pass for all
shapes, and the remaining styles in a second pass. 

MapScript implications
------------------------------------------------------------------------------

Getters and setters will have to be added to the different mapscripts.

A possible enhancement could also be to expose the transformation function to
MapScript.

Documentation
------------------------------------------------------------------------------

completed

Backwards Incompatibility Issues
------------------------------------------------------------------------------

none expected.

Bug ID
------------------------------------------------------------------------------

https://github.com/mapserver/mapserver/issues/2825

Voting History
------------------------------------------------------------------------------

Vote completed on 2008/12/08:

- +1: Lime, Szekeres, Woodbridge, Nacionales, Morissette
- +0: Nicoletti
