.. rfc37: ****************************************************************************** MS RFC 37: MapServer Spatial Reference Improvements and Additions ****************************************************************************** :Author: Howard Butler :Contact: hobu.inc at gmail.com :Author: Frank Warmerdam :Contact: warmerdam at pobox.com :Revision: $Revision$ :Date: $Date$ :Status: Draft :Id: $Id$ Purpose ============================================================================== To provide MapServer with the ability to set its PROJECTION information from a number of sources, including directly from the datasource itself, in an attempt to lessen the burden related to dealing with coordinate system information on users. These improvements will be optionally available and not interfere with previous PROJECTION defintion methods. The History of Spatial References in MapServer ============================================================================== MapServer's spatial reference support is quite anemic by many standards. While most of the data sources MapServer interacts with support describing the spatial reference of contained layers, MapServer has historically dropped the information on the floor or completely ignored it. MapServer's reprojection machinery keys off the fact that a LAYER's PROJECTION is different than the MAP's. When this is the case, MapServer reprojects the LAYER's data to the MAP's spatial reference during a map draw. OGC services also interact here, and when a spatial reference is specified as "available" using the METADATA mechanism, a client can request maps in a different spatial reference than is specified by default, which starts the reprojection machinery. Definition ---------- MapServer has historically used two different approaches for defining the spatial reference of its data -- EPSG/ESRI codes in the form: :: PROJECTION "init=epsg:4326" END And proj4-formated definitions in the form: :: PROJECTION "proj=cea" "lon_0=0" "lat_ts=45" "x_0=0" "y_0=0" "ellps=WGS84" "units=m" "no_defs" END A third, and rather unknown option is available exclusively to WMS -- the EPSG AUTO definition, where MapServer attempts to determine the spatial reference from the data itself. This method currently only works for OGR and GDAL data sources, and it is only available when GDAL/OGR is linked into MapServer. Performance Observations ------------------------ MapServer's current spatial reference story is focussed on two things -- simple description and ensuring that unnecessary data reprojection doesn't happen. MapServer currently uses proj4 directly to do its data reprojection, and this is the impetus for defining coordinate systems in proj4 format. For people wanting the best performance but still requiring data reprojection, defining your spatial references in proj4 format is a must. Alternatively, the EPSG/ESRI code definition of MapServer's spatial references allows MapServer to offload the lookup of proj4 descriptions to proj4 itself, with a simple file-based lookup table. This mechanism is currently a bottleneck, however, as each lookup requires trolling through a file to match the given identifier and returning the proj4 definition. .. note:: This penalty was lessened in early 2009 by the addition of a caching mechanism in proj4 that allows subsequent lookups to be fast. Usability --------- The usability of these two mechanism can be a nightmare for users. First, most of the spatial reference descriptions that people work with are of the WKT variety -- not proj4. While it is straightforward to set the PROJECTION information for data with a known EPSG value, custom projections or those not generally available in the EPSG database require the user to somehow translate their WKT into proj4 format and paste it into their mapfile. Additionally, http://spatialreference.org exists to help ease this pain, but it is ultimately a stopgap, and not a permanent solution to the problem. It is not practical to be downloading the spatial reference for each and every layer in a mapfile on every map draw from a website. spatialreference.org does provide some conversion utilities to allow a user to paste in WKT and have it return MapServer PROJECTION blocks, but this approach still foists pain and misery on the users. Specification Features ============================================================================== MapServer will continue to behave as before, assuming the inputted projection is either an EPSG code or proj4 definition. The user will also have the ability to optionally add a TYPE enumeration that will hint the processing of the projection object. :: PROJECTION TYPE TYPEENUM "A definition" END The following optional TYPE enumerations would be supported: * AUTO * PROJ4 * EPSG * FILE * OGCWKT * ESRIWKT See below for some examples: :: # Use the what the layer defines as the projection definition. # This may not be available for all data sources or layer types # (shapefile, SDE, OGR, etc.). PROJECTION AUTO END :: # Use a proj4 definition PROJECTION "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" END :: # Use an EPSG code PROJECTION "init=epsg:4326" END :: # Read the definition from a file PROJECTION TYPE FILE VALUE "../myfile.prj" END :: # Use an OGC WKT definition (escaping may be required) PROJECTION 'GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.01745329251994328, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]]' END :: # Use an ESRI WKT definition (escaping may be required) PROJECTION TYPE ESRIWKT 'GEOGCS["GCS_WGS_1984", DATUM["D_WGS_1984", SPHEROID["WGS_1984",6378137,298.257223563]], PRIMEM["Greenwich",0], UNIT["Degree",0.017453292519943295]]' END Implementation Details ============================================================================== It is important that MapServer's previous spatial reference definition behavior be preserved. First, drastically changing the PROJECTION definitions would mean a lot of unnecessary mapfile churn. Second, continuing to define spatial references in proj4 format as before will be the most performant. Implementation of this RFC will encompass four items: 1) Additional spatial reference type enumerations will be added. 2) Addition of a method to the LAYER virtual table so layers can support returning the spatial reference in a variety of formats (OGCWKT, ESRIWKT, proj4, EPSG). 3) Additional methods will be added to operate with the MapScript projectionObj to support setting the projectionObj of a TYPE with a definition. TYPE Enumerations ----------------- The following TYPE enumerations will be added to support SRS definition types: :: enum MS_SRS_TYPE {MS_SRS_AUTO, MS_SRS_PROJ4, MS_SRS_EPSG, MS_SRS_FILE, MS_SRS_OGCWKT, MS_SRS_ESRIWKT} projectionObj ------------- Two methods will be added to set the projectionObj using various definition types and to return definitions in various flavors. :: int msSetProjectionByType(projectionObj *p, int type, const char *value) :: char* msGetProjectionByType(projectionObj *p, int type) Virtual Table Method -------------------- To support AUTO projection definitions, drivers need to have the ability to return spatial reference information. MapServer's layer plugin architecture provides mechanisms for interacting with MapServer layer providers, but there is currently no regularized method for returning the spatial reference information from providers. The following virtual table member is proposed: :: int (*LayerGetAutoProjection)(layerObj *layer) Driver-specific implementations ------------------------------- The following drivers will have implementations provided to support TYPE AUTO spatial reference definitions: * Shapefile * OGR * GDAL Raster * ArcSDE * PostGIS MapScript --------- msSetProjectionByType and msGetProjectionByType will be exposed to MapScript via the projectionObj: :: setByType(char* definition, int type) getByType(int type) Files Affected ============================================================================== :: mapserver.h mapfile.c mapscript/swiginc/projection.i maplayer.c mapproject.h mapproject.c mapsde.c mapogr.cpp mapraster.c mappostgis.c . . . Backward Compatibility Issues ============================================================================== All work described in this RFC will provide optional capabilities to MapServer and no backward compatibility issues are expected. Documentation ============================================================================== This RFC will stand as primary documentation for the feature until such time as the methods and practices described in this document are integrated into the regular MapServer documentation framework.