Changes between Version 3 and Version 4 of rfc64_triangle_polyhedralsurface_tin


Ignore:
Timestamp:
Dec 6, 2016, 7:55:15 AM (7 years ago)
Author:
Even Rouault
Comment:

Updates

Legend:

Unmodified
Added
Removed
Modified
  • rfc64_triangle_polyhedralsurface_tin

    v3 v4  
    1 Author: Avyav Kumar Singh [[BR]]
    2 Contact: avyavkumar at gmail dot com [[BR]]
     1= RFC 64: Triangle, Polyhedral surface and TIN =
     2
     3Authors: Avyav Kumar Singh, Even Rouault [[BR]]
     4Contact: avyavkumar at gmail dot com, even.rouault at spatialys.com [[BR]]
    35Status: Development [[BR]]
    46
     
    810This RFC addresses the addition of the following new geometries in OGRGeometry - [[BR]]
    911[[BR]]
    10 Triangle - A subset of polygons, the fundamental difference is that of 3 nodes only and ONLY ONE exterior boundary and NO interior polygons. [[BR]]
     12Triangle - A subset of polygons, the fundamental difference is that it is made of 3 nodes only (actually 4, with the last one being the repetition of the first one) and ONLY ONE exterior boundary and NO interior polygons. [[BR]]
    1113[[BR]]
    1214PolyhedralSurface - A 3D figure made exclusively of Polygons.[[BR]]
     
    1719[[BR]]
    1820The following was consulted for the geometries - [[BR]]
    19 * [http://portal.opengeospatial.org/files/?artifact_id=25355]
    20 * [https://github.com/postgis/postgis/blob/svn-trunk/doc/bnf-wkt.txt]
    21 * [https://github.com/postgis/postgis/blob/svn-trunk/doc/bnf-wkb.txt]
     21
     22  * [http://portal.opengeospatial.org/files/?artifact_id=25355 OpenGIS Simple Feature Access Part 1 : Common Architecture,v 1.2.1], a.k.a. SFA 1.2.1
     23
     24  * [https://github.com/postgis/postgis/blob/svn-trunk/doc/bnf-wkt.txt BNF of WKT encoding]: extracted from SQL/MM Part 3
     25
     26  * [https://github.com/postgis/postgis/blob/svn-trunk/doc/bnf-wkb.txt BNF of WKB encoding]: extracted from SQL/MM Part 3
    2227[[BR]]
    2328== Core changes ==
     29
     30The new class hierarchy is the following and is mostly consistant with SQL/MM Part 3
     31
     32[[Image(classOGRGeometry_RFC64.png)]]
     33
    2434[[BR]]
    2535Some prelimenary work had already been done prior to this proposal, such as including the necessary WKB codes in <ogr_core.h>.
    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
     37Additionally, the [http://www.sfcgal.org/ SFCGAL] library is a new optional dependency of GDAL (build support only done for Unix for now).
     38The minimum version tested to build is 1.2.2 (as found in Ubuntu 16.04).
     39As 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."
     40It is mostly used as a potential geometry backend by PostGIS. It has a C API, that is the one we use.
     41
     42SFCGAL 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
     44Two new OGRGeometry methods are used to convert SFCGAL geometries <-> OGR geometries.
    2845{{{
    2946static sfcgal_geometry_t* OGRexportToSFCGAL(OGRGeometry *poGeom);
    3047static OGRGeometry* SFCGALexportToOGR(sfcgal_geometry_t* _geometry);
    3148}}}
     49
    3250Besides SFCGAL, GEOS methods are still used in some cases, but with the following limitations - a Triangle is converted to a Polygon with one exterior ring; Polyhedral Surfaces and Triangulated Surfaces are converted to MultiPolygons. (each Triangle in a Triangulated Surface is converted to a Polygon as described previously) [[BR]]
    33 [[BR]]
     51
     52[[BR]]
     53
    3454The API for the new geometries introduced includes - [[BR]]
    3555* Overwriting existing methods for Polygon in the case of Triangle API. A complete API is provided below - [[BR]]
     
    3757class CPL_DLL OGRTriangle : public OGRPolygon
    3858{
     59  private:
     60    bool quickValidityCheck() const;
     61
     62  protected:
     63//! @cond Doxygen_Suppress
     64    virtual OGRSurfaceCasterToPolygon   GetCasterToPolygon() const CPL_OVERRIDE;
     65    virtual OGRErr importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM,
     66                                       OGRRawPoint*& paoPoints, int& nMaxPoints,
     67                                       double*& padfZ ) CPL_OVERRIDE;
     68//! @endcond
     69
    3970  public:
    4071    OGRTriangle();
    4172    OGRTriangle(const OGRPoint &p, const OGRPoint &q, const OGRPoint &r);
    4273    OGRTriangle(const OGRTriangle &other);
     74    OGRTriangle(const OGRPolygon &other, OGRErr &eErr);
    4375    OGRTriangle& operator=(const OGRTriangle& other);
    4476    virtual ~OGRTriangle();
    45     const char *getGeometryName() const;
    46     virtual OGRwkbGeometryType getGeometryType() const;
     77    virtual const char *getGeometryName() const CPL_OVERRIDE;
     78    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
    4779
    4880    // IWks Interface
    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
    6791};
    6892}}}
     
    7296{
    7397  protected:
     98//! @cond Doxygen_Suppress
     99    friend class OGRTriangulatedSurface;
    74100    OGRMultiPolygon oMP;
    75     virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon() const;
    76     virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon() const;
     101    virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon() const CPL_OVERRIDE;
     102    virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon() const CPL_OVERRIDE;
     103    virtual OGRBoolean         isCompatibleSubType( OGRwkbGeometryType ) const;
     104    virtual const char*        getSubGeometryName() const;
     105    virtual OGRwkbGeometryType getSubGeometryType() const;
    77106    OGRErr exportToWktInternal (char ** ppszDstText, OGRwkbVariant eWkbVariant, const char* pszSkipPrefix ) const;
     107
     108    virtual OGRPolyhedralSurfaceCastToMultiPolygon GetCasterToMultiPolygon() const;
     109    static OGRMultiPolygon* CastToMultiPolygonImpl(OGRPolyhedralSurface* poPS);
     110//! @endcond
    78111
    79112  public:
     
    84117
    85118    // IWks Interface
    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;
    93126
    94127    // IGeometry methods
    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;
    111144    virtual OGRErr addGeometry( const OGRGeometry * );
    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 );
    123156};
     157
    124158}}}
    125159* The Triangulated Surface API is similar to Polyhedral Surface, and the MultiPolygon class was tweaked slightly to include methods to run which consisted of subgeometries of the form Triangle. (A MultiPolygon is strictly a collection of Polygons). These methods are internal to OGRMultiPolygon and cannot be accessed by a public user. For instance, the `OGRMultiPolygon::addGeomtryDirectly` method has a check that the subgeometry added to it should be of the type POLYGON. Rather than mess around with the existing function, a new function has been written which does not implement this check -
     
    164198class CPL_DLL OGRTriangulatedSurface : public OGRPolyhedralSurface
    165199{
     200  protected:
     201//! @cond Doxygen_Suppress
     202    virtual OGRBoolean         isCompatibleSubType( OGRwkbGeometryType ) const CPL_OVERRIDE;
     203    virtual const char*        getSubGeometryName() const CPL_OVERRIDE;
     204    virtual OGRwkbGeometryType getSubGeometryType() const CPL_OVERRIDE;
     205
     206    virtual OGRPolyhedralSurfaceCastToMultiPolygon GetCasterToMultiPolygon() const CPL_OVERRIDE;
     207    static OGRMultiPolygon* CastToMultiPolygonImpl(OGRPolyhedralSurface* poPS);
     208//! @endcond
     209
    166210  public:
    167211    OGRTriangulatedSurface();
     
    170214
    171215    OGRTriangulatedSurface& operator=(const OGRTriangulatedSurface& other);
    172     virtual const char *getGeometryName() const;
    173     virtual OGRwkbGeometryType getGeometryType() const;
     216    virtual const char *getGeometryName() const CPL_OVERRIDE;
     217    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
    174218
    175219    // IWks Interface
    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);
    186223};
    187224}}}
     
    195232|| Triangle             || 0017 || 1017 || 2017 || 3017 ||
    196233[[BR]]
     234
     235== Geometry conversions ==
     236
     237The OGRGeometryFactory::forceTo() and forceToMultiPolygon() methods have been enhanced
     238to support conversions between the new geometry types, and towards multipolygon. Note that
     239converting a TIN or a PolyhedralSurface into a MultiPolygon is semantically incorrect since
     240a MultiPolygon is suppose to contain geometries in the same plane, but it might help when
     241converting those new geometry types into a format that doesn't support them (and such
     242conversion was for example implicitly done in the reading side of the shapefile driver
     243previously)
     244
    197245== Changes in drivers ==
    198 Some drivers were modified to be compatible with the new geometries. These include -> [[BR]]
    199 
    200 * PostGIS - No changes done to the driver explicitly, but it has been ensured that PG <-> OGR compatibility has been maintained. PostGIS 3D functions work on OGR, simple scripts work, for example from `autotest/ogr/ogr_pg.py`, we have -
     246
     247=== PostGIS ===
     248
     249No changes done to the driver explicitly, but it has been ensured that PG <-> OGR compatibility has been maintained. PostGIS 3D functions work on OGR, simple scripts work, for example from `autotest/ogr/ogr_pg.py`, we have -
    201250{{{
    202251wkt_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)))',
     
    208257}}}
    209258
    210 * ShapeFile - TriangleStrip and TriangleFan objects in ShapeFile are parsed to OGRTriangulatedSurface. According to ESRI specs,
     259=== ShapeFile ===
     260
     261Shapefiles have the concept of a "MultiPatch" object. The MultiPatch can be made of several parts, which are
    211262 * A TriangleStrip is a linked strip of triangles, where every vertex (after the first two) completes a new triangle. A new triangle is always formed by connecting the new vertex with its two immediate predecessors.
    212263 * A TriangleFan is a linked fan of triangles, where every vertex (after the first two) completes a new triangle. A new triangle is always formed by connecting the new vertex with its immediate predecessor and the first vertex of the part.
    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)
     265Up 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
     266On 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
     270The 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
     274The 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 -
    215275{{{
    216276'TRIANGLE ((0 0,0 1,0 1,0 0))' is parsed to -
     
    257317</gml:PolyhedralSurface>'
    258318}}}
    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
     320Note that on the writing side those geometries are only generated for a GML 3 output.
     321
     322=== DXF ===
     323
     324The 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
     328The 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
     332The 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
    260333
    261334== Documentation ==
     335
    262336Using standard Doxygen documentation procedure.
    263337
     338== Compatibility ==
     339
     340Many applications will not be able to properly deal with the new geometry
     341types that may now be returned by some drivers. In GDAL 2.1, the new types
     342were introduced mentionning that they might be returned by GDAL in the future.
     343Code should either skip the new geometries, deal with them properly or use
     344the OGR_G_ForceTo() function to convert to a geometry type it supports.
     345
    264346== Testing ==
    265 Rigorous testing of all the use cases I can think of. Please feel free to add your own test to the autotest suite to check the stability of the code.
     347
     348Very few changes have been made so that the existing autotest suite still
     349passes.
     350New geometry classes and conversion methods has
     351been added to ogr_geom.py and ogr_gml_geom.py. Updated drivers have received
     352new tests also.
    266353
    267354== Implementation ==
    268 Done by Avyav Kumar Singh, under the Google Summer of Code 2016 program.
     355
     356Done by Avyav Kumar Singh, under the Google Summer of Code 2016 program, and fine tuned / extended / integrated by Even Rouault.
     357
     358The proposed implementation lies in the "gsoc-triangle-ps-tin-rebased" branch of the
     359https://github.com/rouault/gdal2/tree/gsoc-triangle-ps-tin-rebased repository.
     360
     361== Voting history ==
     362
     363TBD