===============================================================
  MS RFC 2: Creating line features and/or shapes using WKT
===============================================================

:Date: 2005/07/13 
:Author: Steve Lime
:Contact: steve.lime@DNR.STATE.MN.US
:Last Edited: $Date: 2007-09-05 13:56:10 -0700 (Wed, 05 Sep 2007) $
:Status: Proposed
:Version: MapServer 4.8

Description: Developing inline features or shapes within MapScript can be a 
bit cumbersome.  One alternative would be to allow users to define feature 
using the Well-Known Text format.  The proposed solution would allow users 
to use this format:

1) within a mapfile
2) via URL
3) via MapScript
4) via MapServer query template

Instead of writing a new WKT parser we would provide access to underlying GEOS 
or OGR functionality to do this. Notes about the actual implementation are
included below.

Files affected
~~~~~~~~~~~~~~~~~

- mapfile.h => new constant, WKT
- maplexer.l => recognize the new constant
- mapfile.c => process new mapfile parameter with FEATURE block (WKT), and 
  update URL parsing in a similar manner
- mapgeos.cpp => wrap GEOS WKT reading/writing code
- mapogr.cpp => wrap OGR WKT reading/writing code
- mapprimitive.c => wrap the GEOS and OGR WKT writer/reading code, this would 
  be the "public" interface 
- maptemplate.c => update the shpxy tag with a "-wkt" option so it would output
  the WKT version of a shape. Placing here would allow us to take advantage of
  the projection support already in place, plus any future options (thining, buffers
  and so on).
- mapscript/swiginc/shape.i => update constructor to pass a WKT string and to
  define a "toString" method that would output a WKT string. Similar modifications
  would have to be made within PHP/MapScript, patterned after the SWIG-based
  interface.

Backwards compatabilty issues
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

N/A, new functionality

Implementation Details
~~~~~~~~~~~~~~~~~~~~~~

 - The C API will take the form:

  ::
  
    shapeObj *msShapeFromWKT( const char * );
    char *msShapeToWKT( shapeObj * ); 

  These are contrary to some of the older code (e.g. msLayerNextShape()). However there 
  are 2 places the WKT APIs will be used: 1) MapScript and 2) creating inline features 
  via URL or MapFiles. In both cases the above functions would be prefered.

 - In MapScript, creating a shape will take the form of an overloaded constructor, e.g.:

   $shape = new shapeObj($mapscript::MS_SHAPE_LINE);  OR
   $shape = new shapeObj('LINESTRING(0 0,1 1,1 2)');

 - In MapScript, a toWKT() method will be added to shapeObj object. 

 - WKT is geometry only.  The attributes, index, tileindex, classindex,
   and text fields do not exist in WKT and will have to be set "elsewhere".

 - There is no widely supported, or standardized approach to "measure"
   values in WKT though Refractions does support it in "EWKT".  For now it
   is assumed that measure values will not be preserved from WKT.

 - There is a well defined way of including Z coordinates and these should
   be carried through if MapServer is built with Z and M support enabled.

 - Development will be accompanied by a set of tests. Sean Gillies has already created
   a test case or two.

Transformations shapeObj to WKT
-------------------------------

 - MS_SHAPE_POINT: If numlines and numpoints are one, then this is converted
   to a POINT object in WKT.  If there are more points, this is converted
   to a MULTIPOINT object.

 - MS_SHAPE_LINE: if numlines is 1 then this will be translated to a LINESTRING
   otherwise it will be translated to a MULTILINESTRING.

 - MS_SHAPE_POLYGON: MapServer does not keep track of interior and exterior
   rings in a shape, since the scanline rasterization mechanism of GD 
   does not require this information.  However, when converting to WKT we
   need to know whether we have a single polygon with holes, or multiple
   polygons (more than one exterior ring).   If numlines is 1, we can directly
   translate to POLYGON(), otherwise the rings will need to be analysed to 
   identify outer rings, and to associate inner rings with their outher ring.
   If more than one outer ring exist, a MULTIPOLYGON will be produced, 
   otherwise a POLYGON will be produced.

 - MS_SHAPE_NULL: This results in an empty WKT string.  

Transformations WKT to shapeObj
-------------------------------

 - POINT: Translates to an MS_SHAPE_POINT object with one point and one line.

 - LINESTRING: Translates to an MS_SHAPE_LINE object with one line. 

 - POLYGON: Translates to an MS_SHAPE_POLYGON object with one line for the
   outer ring and one line for each inner ring.

 - MULTIPOINT: Translates to an MS_SHAPE_POINT object with one line, and one
   point for each line. 

 - MULTILINESTRING: Translates to an MS_SHAPE_LINE object with one line for
   each linestring in the container. 

 - MULTIPOLYGON: Translates into an MS_SHAPE_POLYGON with each ring of each
   polygon being a line in the resulting polygon object. 

 - GEOMETRYCOLLECTION: Treat as MULTIPOINT, MULTILINESTRING or MULTIPOLYGON if
   the contents are all compatible, otherwise throw an exception. 

Bug ID
~~~~~~~~

1466 (primary bug, addition entries for MapScript and OGR will follow)

Voting history
~~~~~~~~~~~~~~~~~

Vote proposed by Steve Lime on 9/4/2005, result was +4 (3 non-voting members).

Voting +1: Lime, Warmerdam, Morissette, Gillies

Proposal passes and will move forward.



