1.. _rfc-49: 2 3======================================================================================= 4RFC 49: Curve geometries 5======================================================================================= 6 7Author: Even Rouault 8 9Contact: even dot rouault at spatialys dot com 10 11Status: Adopted, implemented in GDAL 2.0 12 13Summary 14------- 15 16The current geometry model in GDAL 1.X makes use of points, lines, 17polygons and aggregations of them (multipoints, multilines, 18multipolygons and geometry collections). It was modeled from the 19geometry class hierarchy of the "OpenGIS Simple Feature Access Part 1 : 20Common Architecture" (in its 1.1.0 version). 21 22This RFC covers the addition of new geometry types that have been added 23in ISO/IEC 13249 Part 3 Spatial (abbreviated as ISO SQL/MM Part 3): 24 25- circular string: a circular arc, or a sequence of connected circular 26 arcs, each of them describe by 3 points: the first point of the arc, 27 an intermediate point and the final point 28- compound curve: a sequence of connected curves, either line strings 29 or circular strings 30- curve polygon: polygon consisting of one outer ring, and zero or more 31 inner ring. Each ring can be one of the curve implementations: line 32 strings, circular strings, compound curves. 33- multicurve: a collection of curves (line strings, circular strings, 34 compound curves) 35- multisurface: a collection of surfaces (polygons, curve polygons) 36 37The scope of this RFC consists in : 38 39- adding the new geometry classes to the existing geometry class 40 hierarchy, with the corresponding importer and exporter of WKT (Well 41 Known Text) and WKB (Well Known Binary) encodings 42- adding methods to convert those curve geometries into their 43 approximated linear version, and to do the reverse operation 44- upgrading some of the drivers that can support such geometries : GML 45 (and indirectly NAS, WFS), PostGIS/PGDump, GeoPackage, SQLite, CSV, 46 VRT. 47 48Reference documents 49------------------- 50 51The following documents have been used for the implementation : 52 53- `Old draft version of ISO/IEC 13249 Part 3 Spatial, dating from 54 2004-05-09 <http://jtc1sc32.org/doc/N1101-1150/32N1107-WD13249-3--spatial.pdf>`__, 55 a.k.a SQL/MM Part 3 : Caution the WKB codes given at page 137 and 56 following are not the latest ones used. Refer to SFA 1.2.1 57 58- `OpenGIS Simple Feature Access Part 1 : Common Architecture,v 59 1.2.1 <http://portal.opengeospatial.org/files/?artifact_id=25355>`__, 60 a.k.a. SFA 1.2.1 61 62- `BNF of WKT 63 encoding <https://github.com/postgis/postgis/blob/svn-trunk/doc/bnf-wkt.txt>`__: 64 extracted from SQL/MM Part 3 65 66- `BNF of WKB 67 encoding <https://github.com/postgis/postgis/blob/svn-trunk/doc/bnf-wkb.txt>`__: 68 extracted from SQL/MM Part 3 69 70Core changes 71------------ 72 73New cass hierarchy 74~~~~~~~~~~~~~~~~~~ 75 76The new class hierarchy is the following and is mostly consistent with 77SQL/MM Part 3 78 79.. image:: ../../../images/rfc49/classOGRGeometry.png 80 81The only exceptions are : 82 83- OGRLinearRing: this class present in GDAL 1.X is kept for backward 84 compatibility and also because it is still present in SFA 1.2.1, even 85 if absent from SQL/MM Part 3 86- OGRSimpleCurve: this abstract class is an implementation detail in 87 OGR that simplifies the implementation of OGRCircularString, by 88 sharing code with what was in OGRLineString only. 89 90Geometry types 91~~~~~~~~~~~~~~ 92 93The OGRwkbGeometryType enumeration has been extended with the following 94values : 95 96:: 97 98 wkbCircularString = 8, /**< one or more circular arc segments connected end to end, 99 * ISO SQL/MM Part 3. GDAL >= 2.0 */ 100 wkbCompoundCurve = 9, /**< sequence of contiguous curves, ISO SQL/MM Part 3. GDAL >= 2.0 */ 101 wkbCurvePolygon = 10, /**< planar surface, defined by 1 exterior boundary 102 * and zero or more interior boundaries, that are curves. 103 * ISO SQL/MM Part 3. GDAL >= 2.0 */ 104 wkbMultiCurve = 11, /**< GeometryCollection of Curves, ISO SQL/MM Part 3. GDAL >= 2.0 */ 105 wkbMultiSurface = 12, /**< GeometryCollection of Surfaces, ISO SQL/MM Part 3. GDAL >= 2.0 */ 106 107 wkbCircularStringZ = 1008, /**< wkbCircularString with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */ 108 wkbCompoundCurveZ = 1009, /**< wkbCompoundCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */ 109 wkbCurvePolygonZ = 1010, /**< wkbCurvePolygon with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */ 110 wkbMultiCurveZ = 1011, /**< wkbMultiCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */ 111 wkbMultiSurfaceZ = 1012, /**< wkbMultiSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */ 112 113The codes have been taken from SFA 1.2.1, and are consistent with the 114PostGIS 2 implementation. Note that ISO SQL/MM Part 3 allows alternates 115values for wkbCircularString (8 or 1000001) : see Table 15 in the above 116mentioned draft. The values in the range 10000XX probably date back 117from an earlier draft version. OGR will import them, but will use the 118values from SFA 1.2.1 when exporting WKB. 119 120It has been considered if it would worth to modify the enumeration 121values of the existing 2.5D geometries (wkbPoint25D, etc...) to conform 122with the WKB codes of ISO SQL/MM Part 3 / SFA 1.2.1, but there was not a 123clear advantage in doing so, with respect to the impact on existing 124users of OGR API. 125 126Note: the mix of different ways of expression the Z dimension (wkb25DBit 127bit for "old" geometry types, and +1000 for "new" geometry types) has no 128direct impact on the export of geometries as WKB. There is no direct 129coupling between the values of OGRwkbGeometryType and what goes to WKB 130geometries. The exportToWkb() method of OGRGeometry takes a wkbVariant 131parameter to select the variant of WKB that is wished. 132 133The use of the wkb25DBit value (0x8000000) that was sometimes used to 134test if a geometry type was 3D is now clearly deprecated since it will 135not work for the new geometry type. The wkbHasZ() and wkbSetZ() have 136been added to respectively test if a geometry type is 3D, or modify a 137geometry type to be 3D. The wkb25DBit constant is now disabled for all 138code in GDAL (but still accessible by user code) and all drivers have 139been converted to use the new macros. 140 141A new family of functions have been used to operate on geometry types : 142 143:: 144 145 OGRwkbGeometryType CPL_DLL OGR_GT_Flatten( OGRwkbGeometryType eType ); 146 --> Returns the 2D geometry type corresponding to the passed geometry type. 147 148 OGRwkbGeometryType CPL_DLL OGR_GT_SetZ( OGRwkbGeometryType eType ); 149 --> Returns the 3D geometry type corresponding to the passed geometry type. 150 151 OGRwkbGeometryType CPL_DLL OGR_GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSetM ); 152 --> Returns a 2D or 3D geometry type depending on parameter. 153 154 int CPL_DLL OGR_GT_HasZ( OGRwkbGeometryType eType ); 155 --> Return if the geometry type is a 3D geometry type. 156 157 int CPL_DLL OGR_GT_IsSubClassOf( OGRwkbGeometryType eType, 158 OGRwkbGeometryType eSuperType ); 159 --> Returns if a type is a subclass of another one 160 161 int CPL_DLL OGR_GT_IsCurve( OGRwkbGeometryType ); 162 --> Return if a geometry type is an instance of Curve 163 (i.e. wkbLineString, wkbCircularString or wkbCompoundCurve) 164 165 int CPL_DLL OGR_GT_IsSurface( OGRwkbGeometryType ); 166 --> Return if a geometry type is an instance of Surface 167 (i.e. wkbPolygon or wkbCurvePolygon) 168 169 int CPL_DLL OGR_GT_IsNonLinear( OGRwkbGeometryType ); 170 --> Return if a geometry type is a non-linear geometry type. 171 Such geometry type are wkbCircularString, wkbCompoundCurve, wkbCurvePolygon, 172 wkbMultiCurve, wkbMultiSurface and their 3D variant. 173 174 OGRwkbGeometryType CPL_DLL OGR_GT_GetCollection( OGRwkbGeometryType eType ); 175 --> Returns the collection type that can contain the passed geometry type 176 177 OGRwkbGeometryType CPL_DLL OGR_GT_GetCurve( OGRwkbGeometryType eType ); 178 --> Returns the curve geometry type that can contain the passed geometry type. 179 Handled conversions are : wkbPolygon -> wkbCurvePolygon, 180 wkbLineString->wkbCompoundCurve, wkbMultiPolygon->wkbMultiSurface 181 and wkbMultiLineString->wkbMultiCurve. 182 183 OGRwkbGeometryType CPL_DLL OGR_GT_GetLinear( OGRwkbGeometryType eType ); 184 --> Returns the non-curve geometry type that can contain the passed geometry type 185 Handled conversions are : wkbCurvePolygon -> wkbPolygon, 186 wkbCircularString->wkbLineString, wkbCompoundCurve->wkbLineString, 187 wkbMultiSurface->wkbMultiPolygon and wkbMultiCurve->wkbMultiLineString. 188 189The existing wkbFlatten() is an alias of OGR_GT_Flatten(), the new 190wkbHasZ() an alias of OGR_GT_HasZ() and wkbSetZ() an alias of 191OGR_GT_SetZ(). 192 193New methods 194~~~~~~~~~~~ 195 196- In OGRGeometry class : 197 198:: 199 200 201 virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const; 202 203 /** 204 * \brief Returns if this geometry is or has curve geometry. 205 * 206 * Returns if a geometry is, contains or may contain a CIRCULARSTRING, COMPOUNDCURVE, 207 * CURVEPOLYGON, MULTICURVE or MULTISURFACE. 208 * 209 * If bLookForNonLinear is set to TRUE, it will be actually looked if the 210 * geometry or its subgeometries are or contain a non-linear geometry in them. In which 211 * case, if the method returns TRUE, it means that getLinearGeometry() would 212 * return an approximate version of the geometry. Otherwise, getLinearGeometry() 213 * would do a conversion, but with just converting container type, like 214 * COMPOUNDCURVE -> LINESTRING, MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON, 215 * resulting in a "loss-less" conversion. 216 */ 217 218 virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const; 219 220 /** 221 * \brief Return curve version of this geometry. 222 * 223 * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, 224 * MULTICURVE or MULTISURFACE in it, by de-approximating curve geometries. 225 * 226 * If the geometry has no curve portion, the returned geometry will be a clone 227 * of it. 228 * 229 * The ownership of the returned geometry belongs to the caller. 230 * 231 * The reverse method is OGRGeometry::getLinearGeometry(). 232 * 233 * This function is the same as C function OGR_G_GetCurveGeometry(). 234 * 235 * @param papszOptions options as a null-terminated list of strings. 236 * Unused for now. Must be set to NULL. 237 */ 238 239 virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0, 240 const char* const* papszOptions = NULL) const; 241 242 243 /** 244 * \brief Return, possibly approximate, non-curve version of this geometry. 245 * 246 * Returns a geometry that has no CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, 247 * MULTICURVE or MULTISURFACE in it, by approximating curve geometries. 248 * 249 * The ownership of the returned geometry belongs to the caller. 250 * 251 * The reverse method is OGRGeometry::getCurveGeometry(). 252 * 253 * This method is the same as the C function OGR_G_GetLinearGeometry(). 254 * 255 * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the 256 * arc, zero to use the default setting. 257 * @param papszOptions options as a null-terminated list of strings. 258 * See OGRGeometryFactory::curveToLineString() for valid options. 259 */ 260 261- In OGRGeometryFactory class : 262 263:: 264 265 266 static OGRLineString* curveToLineString( 267 double x0, double y0, double z0, 268 double x1, double y1, double z1, 269 double x2, double y2, double z2, 270 int bHasZ, 271 double dfMaxAngleStepSizeDegrees, 272 const char*const* papszOptions ) 273 /** 274 * \brief Converts an arc circle into an approximate line string 275 * 276 * The arc circle is defined by a first point, an intermediate point and a 277 * final point. 278 * 279 * The provided dfMaxAngleStepSizeDegrees is a hint. The discretization 280 * algorithm may pick a slightly different value. 281 * 282 * So as to avoid gaps when rendering curve polygons that share common arcs, 283 * this method is guaranteed to return a line with reversed vertex if called 284 * with inverted first and final point, and identical intermediate point. 285 * 286 * @param x0 x of first point 287 * @param y0 y of first point 288 * @param z0 z of first point 289 * @param x1 x of intermediate point 290 * @param y1 y of intermediate point 291 * @param z1 z of intermediate point 292 * @param x2 x of final point 293 * @param y2 y of final point 294 * @param z2 z of final point 295 * @param bHasZ TRUE if z must be taken into account 296 * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the 297 * arc, zero to use the default setting. 298 * @param papszOptions options as a null-terminated list of strings or NULL. 299 * Recognized options: 300 * <ul> 301 * <li>ADD_INTERMEDIATE_POINT=STEALTH/YES/NO (Default to STEALTH). 302 * Determine if and how the intermediate point must be output in the linestring. 303 * If set to STEALTH, no explicit intermediate point is added but its 304 * properties are encoded in low significant bits of intermediate points 305 * and OGRGeometryFactory::curveFromLineString() can decode them. 306 * This is the best compromise for round-tripping in OGR and better results 307 * with PostGIS <a href="http://postgis.org/docs/ST_LineToCurve.html">ST_LineToCurve()</a> 308 * If set to YES, the intermediate point is explicitly added to the linestring. 309 * If set to NO, the intermediate point is not explicitly added. 310 * </li> 311 * </ul> 312 */ 313 314 --> This method is used by OGRCircularString::getLinearGeometry() 315 316 OGRCurve* OGRGeometryFactory::curveFromLineString(const OGRLineString* poLS, 317 CPL_UNUSED const char*const* papszOptions) 318 319 /** 320 * \brief Try to convert a linestring approximating curves into a curve. 321 * 322 * This method can return a COMPOUNDCURVE, a CIRCULARSTRING or a LINESTRING. 323 * 324 * This method is the reverse of curveFromLineString(). 325 * 326 * @param poLS handle to the geometry to convert. 327 * @param papszOptions options as a null-terminated list of strings. 328 * Unused for now. Must be set to NULL. 329 */ 330 331 --> This method is used by OGRLineString::getCurveGeometry() 332 333 334 OGRGeometry* OGRGeometryFactory::forceTo( OGRGeometry* poGeom, 335 OGRwkbGeometryType eTargetType, 336 const char*const* papszOptions ) 337 * 338 * Tries to force the provided geometry to the specified geometry type. 339 * 340 * It can promote 'single' geometry type to their corresponding collection type 341 * (see OGR_GT_GetCollection()) or the reverse. non-linear geometry type to 342 * their corresponding linear geometry type (see OGR_GT_GetLinear()), by 343 * possibly approximating circular arcs they may contain. 344 * Regarding conversion from linear geometry types to curve geometry types, only 345 * "wrapping" will be done. No attempt to retrieve potential circular arcs by 346 * de-approximating stroking will be done. For that, OGRGeometry::getCurveGeometry() 347 * can be used. 348 * 349 * The passed in geometry is consumed and a new one returned (or potentially the same one). 350 * 351 * @param poGeom the input geometry - ownership is passed to the method. 352 * @param eTargetType target output geometry type. 353 * @param papszOptions options as a null-terminated list of strings or NULL. 354 * @return new geometry. 355 */ 356 357 --> This method generalizes the existing forceToPolygon(), forceToLineString(), 358 forceToMultiPolygon(), forceToMultiLineString(), that have been extended to 359 deal with the new geometry types. forceTo() and actually calls them if they 360 can be used for the requested conversion, and also deal with conversion between 361 linear and non-linear geometry types. 362 363Implementation of existing OGRGeometry methods 364~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 365 366As GEOS does not support curve geometries for now, all GEOS related 367operations, the ones returning a boolean value such as Intersects(), or 368the ones returning a new geometry such as Intersection(), have been 369adapted so that non-linear geometries are first converted to their 370linear approximation (this might be revisited if GEOS supports curve 371geometries in the future) When GEOS returns a geometry, and that one of 372the input parameters was a non-linear geometry, the reverse operation is 373done to attempt retrieving as much as possible of the curve geometry. Of 374course, the result will not generally perfect, but it is better than 375nothing. 376 377Simple example doing the union of 2 half-circles that are contiguous: 378 379:: 380 381 g1 = ogr.CreateGeometryFromWkt('CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING (0 0,1 1,2 0),(2 0,0 0)))') 382 g2 = ogr.CreateGeometryFromWkt('CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING (0 0,1 -1,2 0),(2 0,0 0)))') 383 g3 = g1.Union(g2) 384 assert g3.ExportToWkt() == 'CURVEPOLYGON (CIRCULARSTRING (0 0,1 1,2 0,1 -1,0 0))' 385 386Or using GetCurveGeometry() explicitly on the result of a buffer 387operation: 388 389:: 390 391 g1 = ogr.CreateGeometryFromWkt('POINT(1 2)') 392 g2 = g1.Buffer(0.5) 393 g3 = g2.GetCurveGeometry() 394 assert g3.ExportToWkt() != 'CURVEPOLYGON (CIRCULARSTRING (1.5 2.0,0.5 2.0,1.5 2.0))' 395 396The Length() operation on OGRCircularString (and thus OGRCompoundCurve) 397uses circle geometry to compute the exact length, without falling back 398to linear approximation. The Area() operation on OGRCurvePolygon will 399generally need to go to linear approximation. When operating on a full 400circle, or a curve polygon that is convex, an optimization is done to 401avoid this (by computing the area of the polygon formed with all the 402vertex including in the circular parts of the description, and adding 403the area of the `circular 404segments <http://en.wikipedia.org/wiki/Circular_segment>`__) 405 406C API changes 407~~~~~~~~~~~~~ 408 409Deprecation: 410 411- wkb25DBit still present, but deprecated since incompatible with the 412 new geometry type. Use the wkbFlatten(), wkbHasZ(), wkbSetZ() macros 413 instead 414 415Additions: 416 417- OGR_GT_xxxx (for Geometry Type): described above 418- OGRErr OGR_G_ExportToIsoWkb( OGRGeometryH, OGRwkbByteOrder, unsigned 419 char*) : Export geometry as WKB conforming to ISO SQL/MM Part 3. 420- OGRErr OGR_G_ExportToIsoWkt( OGRGeometryH, char \*\* ) : Export 421 geometry as WKT conforming to ISO SQL/MM Part 3, i.e. 2.5D geometries 422 names are suffixed by " Z", e.g. "POINT Z (1 2 3)". 423- OGRGeometryH OGR_G_Value( OGRGeometryH, double dfDistance ) : mapping 424 of existing OGRGeometry::Value() 425- int OGR_G_HasCurveGeometry( OGRGeometryH, int bLookForNonLinear ) : 426 mapping of OGRGeometry::hasCurveGeometry() 427- OGRGeometryH OGR_G_GetLinearGeometry( OGRGeometryH hGeom, double 428 dfMaxAngleStepSizeDegrees, char*\* papszOptions) : mapping of 429 OGRGeometry::hasCurveGeometry() 430- OGRGeometryH OGR_G_GetCurveGeometry( OGRGeometryH hGeom, char*\* 431 papszOptions ) : mapping of OGRGeometry::hasCurveGeometry() 432- void OGRSetNonLinearGeometriesEnabledFlag(int bFlag) : discussed in 433 Backward compatibility section 434- int OGRGetNonLinearGeometriesEnabledFlag() : discussed in Backward 435 compatibility section 436 437Changes in drivers 438------------------ 439 440- GML geometry importer: Arc, ArcString, ArcByBulge, ArcByCenterPoint, 441 Circle and CircleByCenterPoints GML elements will be returned as 442 circular string OGR geometries. If they are included in other GML 443 elements such as CurveComposite, MultiCurve, Surface, corresponding 444 non-linear OGR geometries will be returned as well. When reading 445 geometries that are made of or consist of Surface, MultiSurface, 446 Curve, MultiCurve, an effort is made to return the OGR geometry class 447 of a linear type as much as possible, i.e. OGRCurvePolygon, 448 OGRCompoundCurve, etc... will only be returned if there's a circular 449 string in the geometry. 450 451- GML geometry exporter: can generate ArcString and Circle GML elements 452 when passed a geometry with circular string in it. 453 454- GML driver: Can read/write all the new geometry types. When reading 455 GML3 application schemas, declarations of geometry fields such as 456 CurvePropertyType, SurfacePropertyType, MultiCurvePropertyType or 457 MultiSurfacePropertyType will be also interpreted as being potential 458 non-linear geometries, and corresponding OGR geometry type will be 459 used for the layer geometry type, and the geometries of the feature 460 will also follow that layer geometry type. This can affect the WFS 461 drivers. 462 463- NAS driver: Can return the new geometry types. NAS layers will use 464 the new geometry types only if the NAS file contains arcs. 465 466- PG/PostGIS: Can read/write all the new geometry types for both 467 PostGIS 2.X and PostGIS 1.X. For PostGIS 1.X compatibility, special 468 processing must be done in the importFromWkb()/exportToWkb() to deal 469 with the non standard codes used by PostGIS 1.X for curvepolygon, 470 multicurve and multisurface. This is done with a wkbVariantPostGIS1 471 value added to OGRwkbVariant enumeration used by those methods. 472 473- PGDump: Can write all new geometry types. Above remark related to the 474 differences among version make it important to specify correctly the 475 POSTGIS_VERSION dataset creation option. 476 477- GeoPackage: Can read/write all the new geometry types. Note: this 478 isn't in the core of the GeoPackage specification, but it is still a 479 registered extension. 480 481- SQLite: Can read/write all the new geometry types for databases that 482 are NOT Spatialite databases, since Spatialite does no support curve 483 geometry types. However an attempt (well a hack) is done so that the 484 SQLite SQL dialect can still be used. Basically when converting a OGR 485 geometry to Spatialite, if it is of one of the curve geometry type, 486 the resulting blob will first contain the spatialite compatible blob 487 of the linear geometry, and afterwards the WKB of the curve geometry. 488 Spatialite functions, if called with a ST\_ function for example, 489 will ignore the later one. When reading a blob from sqlite, if the 490 added WKB of the curve geometry is still there, it will be used. 491 Otherwise the spatialite geometry blob will be used. So SELECT 492 statement just selecting the geometry column without doing any 493 operation on it should preserve curve geometries. 494 495- MEM: Can read/write all the new geometry types. 496 497- CSV: Can read/write all the new geometry types. 498 499- VRT: Declared as compatible with all the new geometry types. Actual 500 capability will depend on the underlying layers wrapped by the VRT. 501 502Changes in utilities 503-------------------- 504 505- ogr2ogr: the new geometry names (CIRCULARSTRING, etc...) are 506 supported in the -nlt option. "-nlt CONVERT_TO_LINEAR" can also be 507 used to ask curve geometries to be converted into their linear 508 approximation ( what is used to do that is forceTo(xxx, 509 OGR_GT_GetLinear()) ). Note: this isn't strictly necessary as all 510 drivers should be able to deal with the non-linear geometry types 511 with the compatibility mechanism described in Backward compatibility. 512 But this might be useful to produce a PostGIS table or GeoPackage 513 database with linear geometry types even if the source contains 514 non-linear geometries. "-nlt CONVERT_TO_LINEAR" can be combined with 515 "-nlt PROMOTE_TO_MULTI". 516 517Changes in SWIG bindings 518------------------------ 519 520Addition of : 521 522- the new geometry types as ogr.wkbXXXXX 523- ogr.ForceTo() 524- Geometry.ExportToIsoWkt() 525- Geometry.ExportToIsoWkb() 526- Geometry.HasCurveGeometry(int bLookForCircular = FALSE) 527- Geometry.GetLinearGeometry(double dfMaxAngleStepSizeDegrees = 528 0.0,char*\* options = NULL) 529- Geometry.GetCurveGeometry(char*\* options = NULL) 530- ogr.SetNonLinearGeometriesEnabledFlag(int bFlag) 531- ogr.GetNonLinearGeometriesEnabledFlag() 532- ogr.GT_xxxxx functions 533 534Using ogr.wkb25DBit will issue a deprecation warning 535 536Related changes that are *NOT* included in this RFC 537--------------------------------------------------- 538 539- Support for other ISO SQL/MM geometries such as Polyhedral Surface, 540 Triangulated Irregular Network (TIN), Triangle. 541- Support for the M (Measure) dimension of geometries. 542- Upgrade of other drivers that could make use of curve geometries : 543 MSSQL Spatial, Oracle Spatial, DXF, DWG, ... 544- Support for arbitrary new geometry types: Conceptually one could hope 545 that a new class extending OGRCurve (Bezier or Spline curve) for 546 example could be added without touching OGR core. This isn't 547 currently possible: changes in OGRGeometryFactory and the OGR_GT\_ 548 functions would be needed to remove a few hardcoded assumptions. 549 550Backward compatibility 551---------------------- 552 553Regarding code using GDAL 554~~~~~~~~~~~~~~~~~~~~~~~~~ 555 556Many applications will not be able to properly deal with the new 557geometry types that may now be returned by some drivers. If they don't 558want to test the geometry type and explicitly calling the conversion 559function, they can call OGRSetNonLinearGeometriesEnabledFlag(FALSE) (the 560default value is TRUE, i.e. non-linear geometries can be returned). In 561which case, they will be transformed into their closest linear geometry, 562by doing linear approximation, with OGR_G_ForceTo(). 563 564This flag has only an effect on the OGR_F_GetGeometryRef(), 565OGR_F_GetGeomFieldRef(), OGR_L_GetGeomType(), OGR_GFld_GetType() and 566OGR_FD_GetGeomType() C API, and corresponding methods in the SWIG 567bindings. 568 569Libraries should generally *not* use that method, since that could 570interfere with other libraries or applications. 571 572Note that it does *not* affect the behavior of the C++ API. It has been 573deemed dangerous/complicated to try doing that at the C++ level as it 574could confuse drivers since they might call GetGeomType() for example. 575 576Regarding OGR drivers 577~~~~~~~~~~~~~~~~~~~~~ 578 579Drivers that can deal with the new geometry types SHOULD declare the new 580dataset level ODsCCurveGeometries AND layer level OLCCurveGeometries 581capabilities. The virtual methods CreateFeature() and SetFeature() 582implemented by drivers have been renamed ICreateFeature() and 583ISetFeature(). OGRLayer has now a non-virtual CreateFeature() and 584SetFeature() that checks if the layer has curve geometry capability. If 585it has not, and that the passed feature has non-linear geometries, they 586will be transparently converted to their linear approximation before 587calling the driver ICreateFeature()/ISetFeature() method. Similarly the 588CreateLayer() method at datasource level will convert the passed 589geometry type to a non-linear corresponding type if necessary. 590 591All in-tree drivers have been converted to switch from CreateFeature() 592to ICreateFeature() and SetFeature() to ISetFeature(). Out-of-tree 593drivers will have to be adapted similarly otherwise those methods will 594fails (the now non-virtual methods in OGRLayer class will try to create 595the default implementation of the same class, which will fail). 596 597Documentation 598------------- 599 600All new methods and OGR geometry classes are documented. Driver 601documentation is updated when necessary. MIGRATION_GUIDE.TXT is updated 602with a summary of the text of this RFC. 603 604Testing 605------- 606 607Very few changes have been made so that the existing autotest suite 608still passes. Very comprehensive testing of new geometry classes and 609conversion methods has been added to ogr_geom.py and ogr_gml_geom.py. 610Updated drivers have received new tests also. 611 612Implementation 613-------------- 614 615Implementation will be done by Even Rouault. Coordinated with Sourcepole 616(see `QGIS Enhancement 8: Geometry 617redesign <https://github.com/mhugent/QGIS-Enhancement-Proposals/blob/master/QEP-8-geometry_redesign.rst>`__), 618sponsored by Swiss QGIS User Group. 619 620The proposed implementation lies in the "curve_geometries" branch of the 621`https://github.com/rouault/gdal2/tree/curve_geometries <https://github.com/rouault/gdal2/tree/curve_geometries>`__ 622repository. 623 624The list of changes : 625`https://github.com/rouault/gdal2/compare/curve_geometries <https://github.com/rouault/gdal2/compare/curve_geometries>`__ 626 627Voting history 628-------------- 629 630+1 from TamasS, JukkaR and EvenR 631 632