Version 5 (modified by 8 years ago) ( diff ) | ,
---|
RFC 61 : Support for measured geometries
Author: Ari Jolma
Contact: ari.jolma at gmail.com
Status: Draft
Implementation version: 2.1 or 2.2
Summary
This RFC defines how to implement measured geometries (geometries, where the points have M coordinate, i.e., they are XYM or XYZM).
Rationale
M coordinate is in the OGC simple feature model and it is used in many vector data formats.
Changes
Changes are required into the C++ API and the C API needs to be enhanced. Several drivers need to be changed to take advantage of this enhancement but also due to the changes in the C++ API.
Common API
New OGRwkbGeometryType values are needed - that is a rather complex system due to history. SFSQL 1.2 and ISO SQL/MM Part 3 will be used, i.e., 2D type + 2000 for M and 2D type + 3000 for ZM. (Also types such as Tin and PolyhedralSurface types can be added for completeness, even if unimplemented currently)
C++ API
The property int nCoordinateDimension in class OGRGeometry will be replaced by int flags. It may have the following flags:
#define OGR_G_NOT_EMPTY 0x1 #define OGR_G_3D 0x2 #define OGR_G_MEASURED 0x4
Currently hacks such as nCoordDimension == -2 are used to denote empty geometries. This implies many changes to drivers etc. which get or set nCoordinateDimension.
IsEmpty = !(flags & OGR_G_NOT_EMPTY), Is3D = flags & OGR_G_3D, IsMeasured = flags & OGR_G_MEASURED.
Keep (with original semantics, i.e., coordinate dimension is 2 or 3), but deprecate
getCoordinateDimension(); setCoordinateDimension();
class OGRGeometry:
//Possibly add methods (SF Common Architecture): int Dimension(); // -1 for empty geometries, 0 for points, 1 for curves, 2 for surfaces, max of components for collections int CoordinateDimension(); // 2 if not 3D and not measured, 3 if 3D or measured, 4 if 3D and measured int SpatialDimension(); // ?? char *GeometryType(); // calls OGRToOGCGeomType (which needs to be enhanced) //Add methods (SF Common Architecture): OGRBoolean Is3D(); OGRBoolean IsMeasured(); //Add methods (non-standard, may cause internal changes, e.g., allocate memory for Z or M values): virtual void set3D(OGRBoolean bIs3D); virtual void setMeasured(OGRBoolean bIsMeasured); //Add now or later methods: virtual OGRGeometry *LocateAlong(double mValue); virtual OGRGeometry *LocateBetween(double mStart, double mEnd);
int CoordinateDimension() should have the new semantics. The method name in simple features documents actually is without prefix get. Similarly,
Add property double m to class OGRPoint. Add constructor, getters, and setters for it.
Add property double *padfM to class OGRSimpleCurce. Add constructor, getters, and setters for it. The getters and setters can take advantage of the flags to determine whether Z or M is to be set in some of them. For backwards compatibility Z is preferred.
Override methods set3D and setMeasured in those classes where setCoordinateDimension is overridden.
C API
ogr_core.h:
OGRwkbGeometryType CPL_DLL OGR_GT_SetM( OGRwkbGeometryType eType ); int CPL_DLL OGR_GT_HasM( OGRwkbGeometryType eType );
ogr_api.h: (new versions of some functions are needed, use postfix M)
void CPL_DLL OGR_G_Is3D( OGRGeometryH ); void CPL_DLL OGR_G_IsMeasured( OGRGeometryH ); void CPL_DLL OGR_G_Set3D( OGRGeometryH, int ); void CPL_DLL OGR_G_SetMeasured( OGRGeometryH, int ); int CPL_DLL OGR_G_GetPointsM( OGRGeometryH hGeom, void* pabyX, int nXStride, void* pabyY, int nYStride, void* pabyZ, int nZStride, void* pabyM, int nMStride); double CPL_DLL OGR_G_GetM( OGRGeometryH, int ); void CPL_DLL OGR_G_GetPointM( OGRGeometryH, int iPoint, double *, double *, double *, double * ); void CPL_DLL OGR_G_SetPointM( OGRGeometryH, int iPoint, double, double, double, double ); void CPL_DLL OGR_G_AddPointM( OGRGeometryH, double, double, double, double ); void CPL_DLL OGR_G_SetPointsM( OGRGeometryH hGeom, int nPointsIn, void* pabyX, int nXStride, void* pabyY, int nYStride, void* pabyZ, int nZStride, void* pabyM, int nMStride );
ogr_p.g
const char CPL_DLL * OGRWktReadPointsM( const char * pszInput, OGRRawPoint **ppaoPoints, double **ppadfZ, double **ppadfM, int * pnMaxPoints, int * pnReadPoints ); void CPL_DLL OGRMakeWktCoordinateM( char *, double, double, double, double, int );
pggeometry.h is internal, so we can change the function prototype
void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP, OGRPolygon*& poLastPoly, int nPartType, int nPartPoints, double* padfX, double* padfY, double* padfZ, double* padfM);
SWIG bindings (Python / Java / C# / Perl) changes
The new C API functions need to be exposed through swig. Further changes depend on whether the language bindings are aware of coordinates. At least Python and Perl are.
Drivers
Drivers that are probably affected by the C++ changes are at least (these use the CoordinateDimension API) pg, mssqlspatial, sqlite, db2, mysql, gml, pgdump, geojson, libkml, gpkg, wasp, gpx, filegdb, vfk, bna, dxf.
Utilities
to do
Documentation
All new methods/functions are documented.
Test Suite
to do
Compatibility Issues
Many drivers (actually datasets and layers) which support measures need to have the support added. Support should be advertised using
#define ODsCMeasuredGeometries "MeasuredGeometries" #define OLCMeasuredGeometries "MeasuredGeometries"
ICreateLayer, which all drivers that have create layer capability implement, have geometry type as an argument. The method should call CPLError() with CPLE_NotSupported and return NULL if the driver does not support measures. Similarly for ICreateFeature and ISetFeature.
There is a question whether the user-oriented API functions (CreateLayer, CreateFeature, and SetFeature) should (silently) strip out the measures before continuing to the I* methods. This (side effect) may not be what is wanted in some usage scenarios but it would follow the pattern of what is already done with non linear geometries.
Related tickets
https://trac.osgeo.org/gdal/ticket/6063 https://trac.osgeo.org/gdal/ticket/6331
Implementation
The implementation will be done by Ari Jolma.
The proposed implementation will be in https://github.com/ajolma/GDAL-XYZM