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