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