26 | | Additionally, the SFCGAL library has been interfaced through OGR methods for implementing some methods from the API. For that, |
27 | | SFCGAL methods are introduced in OGRGeometry to convert SFCGAL geometries <-> OGR geometries. |
| 36 | |
| 37 | Additionally, the [http://www.sfcgal.org/ SFCGAL] library is a new optional dependency of GDAL (build support only done for Unix for now). |
| 38 | The minimum version tested to build is 1.2.2 (as found in Ubuntu 16.04). |
| 39 | As mentionned in its home page, "SFCGAL is a C++ wrapper library around CGAL with the aim of supporting ISO 19107:2013 and OGC Simple Features Access 1.2 for 3D operations." |
| 40 | It is mostly used as a potential geometry backend by PostGIS. It has a C API, that is the one we use. |
| 41 | |
| 42 | SFCGAL functions may be used by methods of OGRGeometry (currently IsValid(), Distance(), ConvexHull(), Intersection(), Union(), Difference(), SymDifference(), Crosses()), as soon as one of the geometry operands is a Triangle, PolyhedralSurface or TIN. |
| 43 | |
| 44 | Two new OGRGeometry methods are used to convert SFCGAL geometries <-> OGR geometries. |
49 | | virtual int WkbSize() const; |
50 | | virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc ); |
51 | | virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const; |
52 | | virtual OGRErr importFromWkt( char ** ); |
53 | | virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const; |
54 | | |
55 | | // New methods interfaced through SFCGAL or rewritten from OGRPolygon/OGRCurvePolygon/OGRGeometry |
56 | | virtual OGRGeometry *Boundary() const CPL_WARN_UNUSED_RESULT; |
57 | | virtual double Distance3D(const OGRGeometry *poOtherGeom) const; |
58 | | virtual OGRErr Centroid( OGRPoint * poPoint ) const; |
59 | | virtual OGRBoolean IsSimple() const; |
60 | | virtual OGRBoolean IsRing() const; |
61 | | virtual OGRErr addRing (OGRCurve *poNewRing); |
62 | | virtual OGRErr PointOnSurface( OGRPoint * poPoint ) const; |
63 | | virtual OGRGeometry *Polygonize() const CPL_WARN_UNUSED_RESULT; |
64 | | virtual OGRGeometry *SymDifference( const OGRGeometry *poOtherGeom) const CPL_WARN_UNUSED_RESULT; |
65 | | virtual OGRBoolean Touches( const OGRGeometry * ) const; |
66 | | virtual double get_Area() const; |
| 81 | virtual OGRErr importFromWkb( unsigned char *, int = -1, |
| 82 | OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE; |
| 83 | virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE; |
| 84 | |
| 85 | // New methods rewritten from OGRPolygon/OGRCurvePolygon/OGRGeometry |
| 86 | virtual OGRErr addRingDirectly( OGRCurve * poNewRing ) CPL_OVERRIDE; |
| 87 | |
| 88 | //! @cond Doxygen_Suppress |
| 89 | static OGRGeometry* CastToPolygon(OGRGeometry* poGeom); |
| 90 | //! @endcond |
86 | | virtual int WkbSize() const; |
87 | | virtual const char *getGeometryName() const; |
88 | | virtual OGRwkbGeometryType getGeometryType() const; |
89 | | virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc ); |
90 | | virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const; |
91 | | virtual OGRErr importFromWkt( char ** ); |
92 | | virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const; |
| 119 | virtual int WkbSize() const CPL_OVERRIDE; |
| 120 | virtual const char *getGeometryName() const CPL_OVERRIDE; |
| 121 | virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE; |
| 122 | virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE; |
| 123 | virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const CPL_OVERRIDE; |
| 124 | virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE; |
| 125 | virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const CPL_OVERRIDE; |
95 | | virtual int getDimension() const; |
96 | | |
97 | | virtual void empty(); |
98 | | |
99 | | virtual OGRGeometry *clone() const; |
100 | | virtual void getEnvelope(OGREnvelope * psEnvelope) const; |
101 | | virtual void getEnvelope(OGREnvelope3D * psEnvelope) const; |
102 | | |
103 | | virtual void flattenTo2D(); |
104 | | virtual OGRErr transform(OGRCoordinateTransformation*); |
105 | | virtual OGRBoolean Equals(OGRGeometry*) const; |
106 | | virtual double get_Area() const; |
107 | | virtual OGRErr PointOnSurface(OGRPoint*) const; |
108 | | |
109 | | OGRMultiPolygon* CastToMultiPolygon(); |
110 | | virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const; |
| 128 | virtual int getDimension() const CPL_OVERRIDE; |
| 129 | |
| 130 | virtual void empty() CPL_OVERRIDE; |
| 131 | |
| 132 | virtual OGRGeometry *clone() const CPL_OVERRIDE; |
| 133 | virtual void getEnvelope(OGREnvelope * psEnvelope) const CPL_OVERRIDE; |
| 134 | virtual void getEnvelope(OGREnvelope3D * psEnvelope) const CPL_OVERRIDE; |
| 135 | |
| 136 | virtual void flattenTo2D() CPL_OVERRIDE; |
| 137 | virtual OGRErr transform(OGRCoordinateTransformation*) CPL_OVERRIDE; |
| 138 | virtual OGRBoolean Equals(OGRGeometry*) const CPL_OVERRIDE; |
| 139 | virtual double get_Area() const CPL_OVERRIDE; |
| 140 | virtual OGRErr PointOnSurface(OGRPoint*) const CPL_OVERRIDE; |
| 141 | |
| 142 | static OGRMultiPolygon* CastToMultiPolygon(OGRPolyhedralSurface* poPS); |
| 143 | virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const CPL_OVERRIDE; |
112 | | virtual OGRErr addGeometryDirectly(OGRGeometry *poNewGeom); |
113 | | virtual int getNumGeometries(); |
114 | | virtual OGRGeometry* getGeometry(int i); |
115 | | |
116 | | virtual OGRBoolean IsEmpty() const; |
117 | | virtual void setCoordinateDimension( int nDimension ); |
118 | | virtual void set3D( OGRBoolean bIs3D ); |
119 | | virtual void setMeasured( OGRBoolean bIsMeasured ); |
120 | | virtual void swapXY(); |
121 | | virtual double Distance3D(const OGRGeometry *poOtherGeom) const; |
122 | | virtual OGRErr removeGeometry( int iIndex, int bDelete = TRUE ); |
| 145 | OGRErr addGeometryDirectly(OGRGeometry *poNewGeom); |
| 146 | int getNumGeometries() const; |
| 147 | OGRGeometry* getGeometryRef(int i); |
| 148 | const OGRGeometry* getGeometryRef(int i) const; |
| 149 | |
| 150 | virtual OGRBoolean IsEmpty() const CPL_OVERRIDE; |
| 151 | virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE; |
| 152 | virtual void set3D( OGRBoolean bIs3D ) CPL_OVERRIDE; |
| 153 | virtual void setMeasured( OGRBoolean bIsMeasured ) CPL_OVERRIDE; |
| 154 | virtual void swapXY() CPL_OVERRIDE; |
| 155 | OGRErr removeGeometry( int iIndex, int bDelete = TRUE ); |
176 | | virtual int WkbSize() const; |
177 | | virtual OGRErr importFromWkb(unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc); |
178 | | virtual OGRErr exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc) const; |
179 | | virtual OGRErr importFromWkt(char **); |
180 | | virtual OGRErr exportToWkt(char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc) const; |
181 | | |
182 | | virtual OGRGeometry *clone() const; |
183 | | virtual OGRErr addGeometry( const OGRGeometry * ); |
184 | | virtual OGRErr addGeometryDirectly(OGRGeometry *poNewGeom); |
185 | | OGRMultiPolygon* CastToMultiPolygon(); |
| 220 | virtual OGRErr addGeometry( const OGRGeometry * ) CPL_OVERRIDE; |
| 221 | |
| 222 | static OGRPolyhedralSurface* CastToPolyhedralSurface(OGRTriangulatedSurface* poTS); |
| 234 | |
| 235 | == Geometry conversions == |
| 236 | |
| 237 | The OGRGeometryFactory::forceTo() and forceToMultiPolygon() methods have been enhanced |
| 238 | to support conversions between the new geometry types, and towards multipolygon. Note that |
| 239 | converting a TIN or a PolyhedralSurface into a MultiPolygon is semantically incorrect since |
| 240 | a MultiPolygon is suppose to contain geometries in the same plane, but it might help when |
| 241 | converting those new geometry types into a format that doesn't support them (and such |
| 242 | conversion was for example implicitly done in the reading side of the shapefile driver |
| 243 | previously) |
| 244 | |
201 | 250 | {{{ |
202 | 251 | wkt_list = ['POLYHEDRALSURFACE (((0 0 0,0 0 1,0 1 1,0 1 0,0 0 0)),((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((1 1 0,1 1 1,1 0 1,1 0 0,1 1 0)),((0 1 0,0 1 1,1 1 1,1 1 0,0 1 0)),((0 0 1,1 0 1,1 1 1,0 1 1,0 0 1)))', |
213 | | * Two different OGRTriangulatedSurface are maintained for each TriStrip and TriFan. If both are present in the file read, then an OGRGeometryCollection object is the result which consists of both OGRTriangulatedSurface which correspond to TriStrip and TriFan. (This is not strictly legal, since a TriangulatedSurface should not be a subgeometry of GeometryCollection) |
214 | | * GML - GML has been modified for both input and output -> Triangle, PolyhedralSurface and TriangulatedSurface are capable of being read/written from/to a GML document. Sample examples include - |
| 264 | * Rings (outer ring, inner ring, first ring, "non-typed" ring) |
| 265 | Up to now multipatch were read as MultiPolygon. Now, in general, a GeometryCollection will be returned, with zero or several TIN corresponding to the TriangleStrip/TriangleFan and zero or one MultiPolygon with all the rings. If there's only one TIN or one MultiPolygon, it will be returned as a top-level geometry. The layer type will be Unknown |
| 266 | On writing, the SHPT layer creation option is extended to recognize the MULTIPATCH value, and the current logic to guess the shape type from the layer geometry type or the geometry type of the first feature is extended to support MULTIPATCH. On a MULTIPATCH layer, geometries of type TIN, POLYHEDRALSURFACE, MULTIPOLYGON or GEOMETRYCOLLECTION (whose subgeometries are on of the 3 previous types) are accepted and converted to a MultiPatch object, trying to use TriangleStrip and TriangleFan if the triangles are in the expected order. |
| 267 | |
| 268 | === FileGDB, OpenFileGDB === |
| 269 | |
| 270 | The FileGDB format support the MultiPatch object as well, with one extension. There is a new type of part, which is made of several triangles whose organization is not TriangleStrip or TriangleFan. Both drivers have been upgraded to work like the ShapeFile driver on the reading side. On the wirting side, the FileGDB driver will automatically write a MultiPatch if the layer geometry type is TIN or PolyhedralSurface. The layer option that existed before CREATE_MULTIPATCH=YES can still be used to force writing as MultiPatch |
| 271 | |
| 272 | === GML === |
| 273 | |
| 274 | The GML driver has been modified for both input and output -> Triangle, PolyhedralSurface and TriangulatedSurface are capable of being read/written from/to a GML document. Sample examples include - |
259 | | * DXF changes include converting a PolyFaceMesh (a subtype of PolyLine) to PolyhedralSurface. This is illustrated by a bug on the GDAL trac - https://trac.osgeo.org/gdal/ticket/6246. A PolyFace Mesh consists of points defined initially using specific codes, then these points are described as part of a polygon (a polygon can have four points at the maximum). Reading the PolyFace Mesh is supported in OGR as of now, but write support for it as well (though not implemented by me in this changeset) should be possible as well now. |
| 319 | |
| 320 | Note that on the writing side those geometries are only generated for a GML 3 output. |
| 321 | |
| 322 | === DXF === |
| 323 | |
| 324 | The changes in the DXF driver include converting a PolyFaceMesh (a subtype of PolyLine) to PolyhedralSurface. This is illustrated by a bug on the GDAL trac - https://trac.osgeo.org/gdal/ticket/6246. A PolyFace Mesh consists of points defined initially using specific codes, then these points are described as part of a polygon (a polygon can have four points at the maximum). Reading the PolyFace Mesh is supported in OGR as of now, but write support for it as well (though not implemented by me in this changeset) should be possible as well now. |
| 325 | |
| 326 | === GeoPackage === |
| 327 | |
| 328 | The GeoPackage specification supports [Multi]Point, [Multi]LineString, [Multi]Polygon and GeometryCollection in its core. Curve geometry types are mentionned as a registered extension. But Triangle, PolyhedralSurface or TIN are not mentionned at all. However the GeoPackage geometry blob format being based on ISO WKB, support for the new geometry types did not really require new code. Hence we have kepts this possibility of reading/writing the 3 new geometry types, but with a warning emitted that a non-standard extension will be used on the writing side. |
| 329 | |
| 330 | === Other drivers === |
| 331 | |
| 332 | The CSV, VRT, PGDump, SQLite (but not Spatialite) drivers support the new geometry types. A couple of drivers have been modified, so as not to crash on the writing side when being provided with the new geometry types. Besides the previously mentionned drivers, the following drivers have been verified to not crash (but potentially error out, or skip unrecognized geometries): MySQL, OCI, KML, LIBKML, GeoJSON, MapInfo |