Changes between Initial Version and Version 1 of rfc41_multiple_geometry_fields


Ignore:
Timestamp:
Jul 24, 2013, 5:43:50 AM (11 years ago)
Author:
Even Rouault
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • rfc41_multiple_geometry_fields

    v1 v1  
     1= RFC 41 : Support for multiple geometry fields in OGR =
     2
     3== Summary ==
     4
     5Add read/write support in the OGR data model for features with multiple geometry
     6fields.
     7
     8== Motivation ==
     9
     10The OGR data model is currently tied to a single geometry field per feature,
     11feature definition and layer. But a number of data formats support multiple
     12geometry fields. The OGC Simple Feature Specifications also do not limit to
     13one geometry field per layer (e.g. §7.1.4 of [http://portal.opengeospatial.org/files/?artifact_id=25354 OGC 06-104r4 "OpenGIS® Implementation Standard for Geographic information - Simple feature access -Part 2: SQL option]).
     14
     15There are workarounds : using geometries of type GEOMETRYCOLLECTION, or
     16advertizing as many layers as there are geometry columns in the layer (like
     17currently done in the PostGIS or SQLite drivers). All those approach are at best
     18workarounds that suffer from limitations :
     19  * GEOMETRYCOLLECTION approach : no way to know the name/semantics of each
     20    sub-geometry. All sub-geometries must be expressed in the same SRS. No way
     21    of guaranteeing that the GEOMETRYCOLLECTION has always the same number of
     22    sub-geometries or that there are of a consistent geometry type.
     23  * one layer per geometry column approach : only appropriate for read-only
     24    scenarios. Cannot work in write scenarios.
     25
     26The purpose of this RFC is to make support for multiple geometry fields per
     27feature to be properly taken into account in the OGR data model.
     28
     29== Proposed solution ==
     30
     31(Note: alternative solutions have also been studied. They are explained in a
     32following section of this RFC.)
     33
     34To sum it up, geometry fields will be treated similarly as attribute fields are
     35handled at the OGRFeatureDefn and OGRFeature levels, but they will be kept
     36separate. Attribute fields and geometry fields will have their own separate
     37indexing in the feature definition.
     38
     39This choice has been mainly made to maximize backward compatibility, while
     40offering new capabilities.
     41
     42Its involves creating a OGRGeomFieldDefn class, and changes in OGRFieldDefn,
     43OGRFeatureDefn, OGRFeature and OGRLayer classes.
     44
     45=== OGRGeomFieldDefn class ===
     46
     47The OGRGeomFieldDefn is a new class. Its structure is directly inspired from the
     48OGRFieldDefn class.
     49
     50{{{
     51class CPL_DLL OGRGeomFieldDefn
     52{
     53protected:
     54        char                *pszName;
     55        OGRGeometryType      eGeomType; /* all values possible except wkbNone */
     56        OGRSpatialReference* poSRS;
     57
     58        int                 bIgnore;
     59
     60public:
     61                            OGRGeomFieldDefn(char *pszName,
     62                                             OGRGeometryType eGeomType);
     63        virtual            ~OGRGeomFieldDefn();
     64
     65        void                SetName( const char * );
     66        const char         *GetNameRef();
     67
     68        OGRGeometryType     GetType();
     69        void                SetType( OGRGeometryType eTypeIn );
     70
     71        virtual OGRSpatialReference* GetSpatialRef();
     72        void                 SetSpatialRef(OGRSpatialReference* poSRS);
     73
     74        int                 IsIgnored();
     75        void                SetIgnored( int bIgnoreIn );
     76};
     77}}}
     78
     79One can notice that the member variables were to be found at OGRLayer level
     80previously.
     81
     82The SRS object is ref-counted. The reference count is increased in the
     83constructor and in SetSpatialRef(), and decreased in the destructor.
     84
     85GetSpatialRef() is deliberately set virtual, so that lazy evaluation can
     86be implemented (getting SRS can have a noticeable cost in some driver
     87implementations, like reading an extra file, or issuing a SQL request).
     88
     89=== OGRFeatureDefn class ===
     90
     91The OGRFeatureDefn class will be extended as the following :
     92
     93{{{
     94class CPL_DLL OGRFeatureDefn
     95{
     96  protected:
     97        // Remove OGRwkbGeometryType eGeomType and bIgnoreGeometry and
     98        // add instead the following :
     99
     100        int nGeomFieldCount;
     101        OGRGeomFieldDefn* papoGeomFieldDefn;
     102  public:
     103        virtual int         GetGeomFieldCount();
     104        virtual OGRGeomFieldDefn *GetGeomFieldDefn( int i );
     105        virtual int         GetGeomFieldIndex( const char * );
     106
     107        virtual void        AddGeomFieldDefn( OGRGeomFieldDefn * );
     108        virtual OGRErr      DeleteGeomFieldDefn( int iGeomField );
     109
     110        // Route OGRwkbGeometryType GetGeomType() and void SetGeomType()
     111        // on the first geometry field definition.
     112
     113        // Same for IsGeometryIgnored() and SetGeometryIgnored()
     114}
     115}}}
     116
     117At instanciation, OGRFeatureDefn would create a default geometry field
     118definition of name "" and type wkbUnknown. If SetGeomType() is called,
     119this will be routed on papoGeomFieldDefn[0]. If only one geometry
     120field definition exists, SetGeomType(wkbNone) will remove it.
     121
     122GetGeomType() will be routed on papoGeomFieldDefn[0] if it exists.
     123Otherwise it will return wkbNone.
     124
     125It is strongly advised that there is name uniqueness among the combined
     126set of regular field names and the geometry field names. Failing to do so will
     127result in unspecified behaviour in SQL queries. This advice will not be
     128checked by the code (it is currently not done for regular fields).
     129
     130Another change is to make all the existing methods of OGRFeatureDefn
     131virtual (and change private visibility to protected), so this class can be
     132subclassed if needed. This will enable lazy creation of the object.
     133Justification: establishing the full feature definition can be costly.
     134But applications may want to list all the layers of a datasource, and only
     135present some information that is important, but cheap to establish. In the
     136past, OGRLayer::GetName() and  OGRLayer::GetGeomType() have been introduced
     137in order to workaround for that.
     138
     139Note also that ReorderGeomFieldDefns() is not foreseen for the moment. It
     140could be added in a later step, should the need arises. DeleteGeomFieldDefn()
     141is mostly there for the own benefit of OGRFeatureDefn itself when calling
     142SetGeomType(wkbNone).
     143
     144=== OGRFeature class ===
     145
     146The OGRFeature class will be extended as following :
     147
     148{{{
     149class CPL_DLL OGRFeature
     150{
     151  private:
     152        // Remove poGeometry field and add instead
     153        OGRGeometry** papoGeometries; /* size is given by poFDefn->GetGeomFieldCount() */
     154
     155  public:
     156
     157        int                 GetGeomFieldCount();
     158        OGRGeomFieldDefn   *GetGeomFieldDefnRef( int iField );
     159        int                 GetGeomFieldIndex( const char * pszName);
     160
     161        OGRGeometry*        GetGeomFieldRef(int iField);
     162        OGRErr              SetGeomFieldDirectly( int iField, OGRGeometry * );
     163        OGRErr              SetGeomField( int iField, OGRGeometry * );
     164
     165        // Route SetGeometryDirectly(), SetGeometry(), GetGeometryRef(),
     166        // StealGeometry() on the first geometry field in the array
     167
     168        // Modify implementation of SetFrom() to replicate all geometries
     169}
     170}}}
     171
     172=== OGRLayer class ===
     173
     174Impact on OGRLayer class :
     175
     176  * Spatial filter: the option considered is to only allow one spatial
     177    filter at the time.
     178      - the need for spatial filters applied simultaneously on several
     179        geometry fields is not obvious.
     180      - the m_poFilterGeom protected member is used more than 250 times in the
     181        OGR code base, so turning it into an array would be a tedious task...
     182
     183    Additions:
     184{{{
     185        protected:
     186            int m_iGeomFieldFilter // specify the index on which the spatial
     187                                   // filter is active.
     188
     189        public:
     190            virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
     191            virtual void        SetSpatialFilterRect( int iGeomField,
     192                                                    double dfMinX, double dfMinY,
     193                                                    double dfMaxX, double dfMaxY );
     194}}}
     195
     196    GetNextFeature() implementation must check the m_iGeomFieldFilter index
     197    in order to select the appropriate geometry field.
     198
     199  * GetGeomType() : unchanged. For other fields, use
     200    GetLayerDefn()->GetGeomField(i)->GetType()
     201
     202  * GetSpatialRef(): Currently the default implementation returns NULL. It will
     203    be changed to return GetLayerDefn()->GetGeomField(0)->GetSpatialRef() (if
     204    there is at least one geometry field). New drivers are encouraged not to
     205    specialize GetSpatialRef() anymore, but to appropriately set the SRS of
     206    their first geometry field.
     207    For other fields, use GetLayerDefn()->GetGeomField(i)->GetSpatialRef().
     208
     209    Caveat: as SRS wasn't previously stored at the OGRFeatureDefn level, all
     210    existing drivers, if not updated, will have GetGeomField(0)->GetSpatialRef()
     211    returning NULL. The test_ogrsf utility will check and warn about this. Update
     212    of existing drivers will be made progressively. In the mean time,
     213    using OGRLayer::GetSpatialRef() will be advized to get the SRS of the first
     214    geometry field in a reliable way.
     215
     216  * add :
     217
     218{{{
     219        virtual OGRErr GetExtentEx(int iGeomField, OGREnvelope *psExtent,
     220                                   int bForce = TRUE);
     221}}}
     222    Default implementation would call GetExtent() if iGeomField == 0
     223
     224  * add :
     225
     226{{{
     227        virtual OGRErr CreateGeomField(OGRGeomFieldDefn *poField);
     228}}}
     229
     230  * no DeleteGeomField(), ReorderGeomFields() or AlterGeomFieldDefn()
     231    for now. Could be added later if the need arises.
     232
     233  * GetGeometryColumn() : unchanged. Routed onto the first geometry field.
     234    For other fields, use GetLayerDefn()->GetGeomField(i)->GetNameRef()
     235
     236  * SetIgnoredFields() : iterate over the geometry fields in addition to
     237    regular fields. The special "OGR_GEOMETRY" value will only apply to the
     238    first geometry field.
     239
     240  * Intersection(), Union(), etc... : unchanged. Later improvements could
     241    use the papszOptions parameter to specify an alternate geometry field
     242
     243  * TestCapability(): add a OLCCreateGeomField capability to inform if
     244    CreateGeomField() is implemented.
     245
     246=== OGRDataSource class ===
     247
     248Impact on OGRDataSource class :
     249
     250  * CreateLayer() : signature will be unchanged. If more than one
     251    geometry fields are needed, OGRLayer::CreateGeomField() must be used.
     252    If the name of the first geometry field must be specified, for drivers
     253    supporting OLCCreateGeomField, using code should call CreateLayer() with
     254    eGType = wkbNone and then add all geometry fields with
     255    OGRLayer::CreateGeomField().
     256
     257  * CopyLayer() : adapted to replicate all geometry fields (if supported by
     258    target layer)
     259
     260  * ExecuteSQL() : takes a spatial filter. In the case of the generic OGR SQL
     261    implementation, this filter is a facility. It could also as well be applied
     262    on the returned layer object. So there is no real need for adding a way
     263    of specifying the geometry field at the ExecuteSQL() API level.
     264
     265== Explored alternative solutions ==
     266
     267( This paragraph can be skipped if you are totally convinced by the proposed
     268approach detailed above :-) )
     269
     270A possible alternative solution would have been to extend the existing
     271OGRFieldDefn object with information related to the geometry. That would have
     272involved adding a OFTGeometry value in the OGRFieldType enumeration, and
     273adding the  OGRGeometryType eGeomType and OGRSpatialReference* poSRS members
     274to OGRFieldDefn. At OGRFeature class level, the OGRField union could have
     275been extended with a OGRGeometry* field. Similarly at OGRLayer level,
     276CreateField() could have been used to create new geometry fields.
     277
     278The main drawback of this approach, which seems the most natural way, is
     279backward compatibility. This would have affected all places in OGR own code or
     280external code where fields are retrieved and geometry is not expected. For
     281example, in code like the following (very common in the
     282CreateFeature() of most drivers, or in user code consuming features returned
     283by GetNextFeature()) :
     284
     285{{{
     286switch( poFieldDefn->GetType() )
     287{
     288        case OFTInteger: something1(poField->GetFieldAsInteger()); break;
     289        case OFTReal: something2(poField->GetFieldAsDouble()): break;
     290        default: something3(poField->GetFieldAsString()); break;
     291}
     292}}}
     293
     294This would lead, for legacy code, to geometry being handled as regular field.
     295We could imagine that GetFieldAsString() converts the geometry as WKT, but it
     296is doubtfull that this would really be desired. Fundamentally, the handling
     297of attribute and geometry fields is different in most use cases.
     298
     299(On the other side, if we introduce 64bit integer as a OGR type (this is an
     300RFC that is waiting for implementation...), the above code would still produce
     301a meaningful result. The string reprentation of a 64bit integer is not that
     302bad as a default behaviour.)
     303
     304GetFieldCount() would also take into account geometry fields, but in most
     305cases, you would need to substract them.
     306
     307A possible way of avoiding the above compatibility issue would be to have
     3082 sets of API at OGRFeatureDefn and OGRFeature level. The current one, that
     309would ignore the geometry fields, and an "extended" one that would take them
     310into account. For example, OGRFeatureDefn::GetFieldCountEx(),
     311OGRFeatureDefn::GetFieldIndexEx(), OGRFeatureDefn::GetFieldDefnEx(),
     312OGRFeature::GetFieldEx(), OGRFeature::SetFieldAsXXXEx() would take into account
     313both attribute and geometry fields. The annoying thing with that approach is
     314the duplication of the ~ 20 methods GetField() and SetFieldXXX() in OGRFeature.
     315
     316== C API ==
     317
     318The following functions are added to the C API :
     319
     320{{{
     321/* OGRGeomFieldDefnH */
     322
     323typedef struct OGRGeomFieldDefnHS *OGRGeomFieldDefnH;
     324
     325OGRGeomFieldDefnH    CPL_DLL OGR_GFld_Create( const char *, OGRwkbGeometryType ) CPL_WARN_UNUSED_RESULT;
     326void                 CPL_DLL OGR_GFld_Destroy( OGRGeomFieldDefnH );
     327
     328void                 CPL_DLL OGR_GFld_SetName( OGRGeomFieldDefnH, const char * );
     329const char           CPL_DLL *OGR_GFld_GetNameRef( OGRGeomFieldDefnH );
     330
     331OGRwkbGeometryType   CPL_DLL OGR_GFld_GetType( OGRGeomFieldDefnH );
     332void                 CPL_DLL OGR_GFld_SetType( OGRGeomFieldDefnH, OGRwkbGeometryType );
     333
     334OGRSpatialReferenceH CPL_DLL OGR_GFld_GetSpatialRef( OGRGeomFieldDefnH );
     335void                 CPL_DLL OGR_GFld_SetSpatialRef( OGRSpatialReferenceH hSRS, OGRGeomFieldDefnH );
     336
     337int                  CPL_DLL OGR_GFld_IsIgnored( OGRGeomFieldDefnH hDefn );
     338void                 CPL_DLL OGR_GFld_SetIgnored( OGRGeomFieldDefnH hDefn, int );
     339
     340/* OGRFeatureDefnH */
     341
     342int               CPL_DLL OGR_FD_GetGeomFieldCount( OGRFeatureDefnH hFDefn );
     343OGRGeomFieldDefnH CPL_DLL OGR_FD_GetGeomFieldDefn( OGRFeatureDefnH hFDefn, int i );
     344int               CPL_DLL OGR_FD_GetGeomFieldIndex( OGRFeatureDefnH hFDefn, const char * );
     345
     346void              CPL_DLL OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hFDefn, OGRGeomFieldDefnH );
     347OGRErr            CPL_DLL OGR_FD_DeleteGeomFieldDefn( OGRFeatureDefnH hFDefn, int iGeomField );
     348
     349/* OGRFeatureH */
     350
     351int               CPL_DLL OGR_L_GetGeomFieldCount( OGRFeatureH hFeat );
     352OGRGeomFieldDefnH CPL_DLL OGR_L_GetGeomFieldDefnRef( OGRFeatureH hFeat, int iField );
     353int               CPL_DLL OGR_L_GetGeomFieldIndex( OGRFeatureH hFeat, const char * pszName);
     354
     355OGRGeometryH      CPL_DLL OGR_F_GetGeomFieldRef( OGRFeatureH hFeat, int iField );
     356OGRErr            CPL_DLL OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField, OGRGeometryH );
     357OGRErr            CPL_DLL OGR_F_SetGeomField( OGRFeatureH hFeat, int iField, OGRGeometryH );
     358
     359/* OGRLayerH */
     360
     361void     CPL_DLL OGR_L_SetSpatialFilterEx( OGRLayerH, int iGeomField, OGRGeometryH );
     362void     CPL_DLL OGR_L_SetSpatialFilterRectEx( OGRLayerH, int iGeomField,
     363                                               double dfMinX, double dfMinY,
     364                                               double dfMaxX, double dfMaxY );
     365OGRErr   CPL_DLL OGR_L_GetExtentEx( OGRLayerH, int iGeomField,
     366                                    OGREnvelope *psExtent, int bForce );
     367OGRErr   CPL_DLL OGR_L_CreateGeomField( OGRLayerH, OGRGeomFieldDefnH hFieldDefn );
     368
     369}}}
     370
     371== OGR SQL engine ==
     372
     373Currently, "SELECT fieldname1[, ...fieldnameN] FROM layername" returns the
     374specified fields, as well as the associated geometry. This behaviour is clearly
     375not following the behaviour of spatial RDBMS where the geometry field must be
     376explicitely specified.
     377
     378The following compromise between backward compatibility and the new capabilities
     379of this RFC is adopted :
     380  * if no geometry field is explicitely specified in the SELECT clause, and
     381    there is only one geometry fields associated with the layer, then return it
     382    implicitely
     383  * otherwise, only return the explicitely mentionned geometry fields (or all
     384    geometry fields if "*" is used).
     385
     386=== Limitations ===
     387
     388  * Geometries from joined layers will not be fetched, as currently.
     389  * UNION ALL will only handle the default geometry, as currently. (could be
     390    extended in later work.)
     391  * The special fields OGR_GEOMETRY, OGR_GEOM_WKT and OGR_GEOM_AREA will operate
     392    on the first geometry field. It does not seem wise to extend this ad-hoc
     393    syntax. A better alternative will be the OGR SQLite dialect (with Spatialite
     394    support), once it is updated to support multi-geometry (not in the scope of
     395    this RFC)
     396
     397== Drivers ==
     398
     399=== Updated drivers in the context of this RFC  ===
     400
     401  * PostGIS:
     402      - a ad-hoc form of support already exists. Tables with multiple
     403        geometries are reported currently as layers called
     404        "table_name(geometry_col_name)" (as many layers as geometry columns).
     405        This behaviour will be changed so that the table is reported
     406        only once as a OGR layer.
     407  * PGDump:
     408      - add write support for multi-geometry tables.
     409  * Memory:
     410      - updated as a simple illustration of the new capabilities.
     411  * Interlis:
     412      - updated to support multiple geometry fields (as well as other
     413        changes unrelated to this RFC)
     414
     415=== Other candidate drivers (upgrade not covered by this RFC) ===
     416
     417  * GML driver :
     418    currently, only one geometry per feature reported. Possibility of
     419    changing this by hand-editing of the .gfs file
     420  * SQLite driver :
     421      - currently, same behaviour as current PostGIS driver.
     422      - both the driver and the SQLite dialect could be updated to support
     423        multi-geometry layers.
     424  * Google Fusion Tables driver :
     425    currently, only the first found geometry column used. Possibility of
     426    specifying "table_name(geometry_column_name)" as the layer name
     427    passed to GetLayerByName().
     428  * VRT : some thoughts needed to find the syntax to support multiple geometries.
     429      Impacted XML syntax :
     430       . at OGRVRTLayer element level :
     431         GeometryType, LayerSRS, GeomField, SrcRegion,
     432         ExtentXMin/YMin/XMax/YMax,
     433       . at OGRVRTWarpedLayer element level :
     434         add new element to select the geometry field
     435       . at OGRVRTUnionLayer element level :
     436         GeometryType, LayerSRS, ExtentXMin/YMin/XMax/YMax
     437  * CSV : currently, take geometries from column named "WKT". To be extended
     438    to support multiple geometry columns. Not sure worth the effort. Could
     439    be done with the extended VRT driver.
     440  * WFS : currently, only single-geometry layers supported. The standard allows
     441    multi-geometry. Would require GML driver support first.
     442  * Other RDBMS based drivers: MySQL ?, MSSQLSpatial ? Oracle Spatial ?
     443
     444== Utilities ==
     445
     446=== ogrinfo ===
     447
     448ogrinfo will be updated to report information related to multi-geometry support.
     449Output is expected to be unchanged w.r.t current output in the case of
     450single-geometry datasource.
     451
     452Expected output for multi-geometry datasource:
     453
     454{{{
     455$ ogrinfo PG:dbname=mydb
     456INFO: Open of `PG:dbname=mydb'
     457      using driver `PostgreSQL' successful.
     4581: test_multi_geom (Polygon, Point)
     459}}}
     460
     461{{{
     462$ ogrinfo PG:dbname=mydb -al
     463INFO: Open of `PG:dbname=mydb'
     464      using driver `PostgreSQL' successful.
     465
     466Layer name: test_multi_geom
     467Geometry (polygon_geometry): Polygon
     468Geometry (centroid_geometry): Point
     469Feature Count: 10
     470Extent (polygon_geometry): (400000,4500000) - (500000, 5000000)
     471Extent (centroid_geometry): (2,48) - (3,49)
     472Layer SRS WKT (polygon_geometry):
     473PROJCS["WGS 84 / UTM zone 31N",
     474    GEOGCS["WGS 84",
     475        DATUM["WGS_1984",
     476            SPHEROID["WGS 84",6378137,298.257223563,
     477                AUTHORITY["EPSG","7030"]],
     478            AUTHORITY["EPSG","6326"]],
     479        PRIMEM["Greenwich",0,
     480            AUTHORITY["EPSG","8901"]],
     481        UNIT["degree",0.0174532925199433,
     482            AUTHORITY["EPSG","9122"]],
     483        AUTHORITY["EPSG","4326"]],
     484    PROJECTION["Transverse_Mercator"],
     485    PARAMETER["latitude_of_origin",0],
     486    PARAMETER["central_meridian",3],
     487    PARAMETER["scale_factor",0.9996],
     488    PARAMETER["false_easting",500000],
     489    PARAMETER["false_northing",0],
     490    UNIT["metre",1,
     491        AUTHORITY["EPSG","9001"]],
     492    AXIS["Easting",EAST],
     493    AXIS["Northing",NORTH],
     494    AUTHORITY["EPSG","32631"]]
     495Layer SRS WKT (centroid_geometry):
     496GEOGCS["WGS 84",
     497    DATUM["WGS_1984",
     498        SPHEROID["WGS 84",6378137,298.257223563,
     499            AUTHORITY["EPSG","7030"]],
     500        AUTHORITY["EPSG","6326"]],
     501    PRIMEM["Greenwich",0,
     502        AUTHORITY["EPSG","8901"]],
     503    UNIT["degree",0.0174532925199433,
     504        AUTHORITY["EPSG","9122"]],
     505    AUTHORITY["EPSG","4326"]]
     506FID Column = ogc_fid
     507Geometry Column 1 = polygon_geometry
     508Geometry Column 2 = centroid_geometry
     509area: Real
     510OGRFeature(test_multi_geom):1
     511  area (Real) = 500
     512  polygon_geometry = POLYGON ((400000 4500000,400000 5000000,500000 5000000,500000 4500000,400000 4500000))
     513  centroid_geometry = POINT(2.5 48.5)
     514}}}
     515
     516A "-geomfield" option will be added to specify on which field the -spat
     517option applies.
     518
     519=== ogr2ogr ===
     520
     521Enhacements :
     522   * will translate multi-geometry layers into multi-geometry layers
     523     if supported by output layer (OLCCreateGeomField capability). In case
     524     it is not supported, only translates the first geometry.
     525   * "-select" option. If only attribute field names are specified,
     526     all input geometries will be implicitely selected (backward
     527     compatible behaviour). If one or several geometry field names are
     528     specified, only those ones will be selected.
     529   * add a "-geomfield" option to specify on which field the -spat
     530     option applies
     531   * the various geometry transformations (reprojection, clipping, etc.)
     532     will be applied on all geometry fields.
     533
     534=== test_ogrsf ===
     535
     536Will be enhanced with a few consistency checks :
     537  * OGRLayer::GetSpatialRef() == OGRFeatureDefn::GetGeomField(0)->GetSpatialRef()
     538  * OGRLayer::GetGeomType() == OGRFeatureDefn::GetGeomField(0)->GetGeomType()
     539  * OGRLayer::GetGeometryColumn() == OGRFeatureDefn::GetGeomField(0)->GetNameRef()
     540
     541Spatial filtering tests will loop over all geometry fields.
     542
     543== Documentation ==
     544
     545In addition to function level documentation, the new capability will be
     546documented in the [http://gdal.org/ogr/ogr_arch.html OGR Architecture] and
     547[http://gdal.org/ogr/ogr_apitut.html OGR API tutorial] documents.
     548
     549== Python and other language bindings ==
     550
     551The new C API will be mapped to SWIG bindings. It will be only tested
     552with the Python bindings. No new typemaps are expected, so this should work
     553with other languages in a straightforward way.
     554
     555== Compatibility ==
     556
     557 * Changes are only additions to the existing API, and existing behaviour should
     558   be preserved, so this will be backwards compatible.
     559
     560 * C++ ABI changes
     561
     562 * Change of behaviour in PostGIS driver w.r.t GDAL 1.10 for tables with
     563   multiple geometries.
     564
     565
     566== Implementation ==
     567
     568Even Rouault will implement the above described changes for GDAL 1.11 / 2.0 release
     569(whatever version number it might end up :-)), except the upgrade of the Interlis
     570driver that will be done by Pirmin Kalberer.
     571
     572== Funding ==
     573
     574This work is funded by the
     575[http://www.swisstopo.admin.ch/internet/swisstopo/en/home/swisstopo/org/kogis.html Federal Office of Topography (swisstopo), COGIS]
     576
     577== Voting history ==
     578
     579TBD