LCOV - code coverage report
Current view: top level - ogr - ogr_geometry.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 559 563 99.3 %
Date: 2026-05-17 16:12:46 Functions: 304 311 97.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Classes for manipulating simple features that is not specific
       5             :  *           to a particular interface technology.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 1999, Frank Warmerdam
      10             :  * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #ifndef OGR_GEOMETRY_H_INCLUDED
      16             : #define OGR_GEOMETRY_H_INCLUDED
      17             : 
      18             : #include "cpl_conv.h"
      19             : #include "cpl_json.h"
      20             : #include "gdal_fwd.h"
      21             : #include "ogr_core.h"
      22             : #include "ogr_geomcoordinateprecision.h"
      23             : #include "ogr_spatialref.h"
      24             : 
      25             : #include <climits>
      26             : #include <cmath>
      27             : #include <memory>
      28             : #include <utility>
      29             : 
      30             : /**
      31             :  * \file ogr_geometry.h
      32             :  *
      33             :  * Simple feature geometry classes.
      34             :  */
      35             : 
      36             : /// WKT Output formatting options.
      37             : enum class OGRWktFormat
      38             : {
      39             :     F,       ///< F-type formatting.
      40             :     G,       ///< G-type formatting.
      41             :     Default  ///< Format as F when abs(value) < 1, otherwise as G.
      42             : };
      43             : 
      44             : /// Options for formatting WKT output
      45             : class CPL_DLL OGRWktOptions
      46             : {
      47             :   public:
      48             :     /// Type of WKT output to produce.
      49             :     OGRwkbVariant variant = wkbVariantOldOgc;
      50             :     /// Precision of output for X,Y coordinates.  Interpretation depends on \c format.
      51             :     int xyPrecision;
      52             :     /// Precision of output for Z coordinates.  Interpretation depends on \c format.
      53             :     int zPrecision;
      54             :     /// Precision of output for M coordinates.  Interpretation depends on \c format.
      55             :     int mPrecision;
      56             :     /// Whether GDAL-special rounding should be applied.
      57             :     bool round;
      58             :     /// Formatting type.
      59             :     OGRWktFormat format = OGRWktFormat::Default;
      60             : 
      61             :     /// Constructor.
      62       11220 :     OGRWktOptions()
      63       22440 :         : xyPrecision(getDefaultPrecision()), zPrecision(xyPrecision),
      64       11220 :           mPrecision(zPrecision), round(getDefaultRound())
      65             :     {
      66       11220 :     }
      67             : 
      68             :     /// Constructor.
      69       34038 :     OGRWktOptions(int xyPrecisionIn, bool roundIn)
      70       34038 :         : xyPrecision(xyPrecisionIn), zPrecision(xyPrecision),
      71       34038 :           mPrecision(zPrecision), round(roundIn)
      72             :     {
      73       34038 :     }
      74             : 
      75             :     /// Copy constructor
      76             :     OGRWktOptions(const OGRWktOptions &) = default;
      77             : 
      78             :     /// Return default precision
      79             :     static int getDefaultPrecision();
      80             : 
      81             :     /// Return default rounding mode.
      82             :     static bool getDefaultRound();
      83             : };
      84             : 
      85             : /**
      86             :  * Simple container for a position.
      87             :  */
      88             : class OGRRawPoint
      89             : {
      90             :   public:
      91             :     /** Constructor */
      92         573 :     OGRRawPoint() : x(0.0), y(0.0)
      93             :     {
      94         573 :     }
      95             : 
      96             :     /** Constructor */
      97         117 :     OGRRawPoint(double xIn, double yIn) : x(xIn), y(yIn)
      98             :     {
      99         117 :     }
     100             : 
     101             :     /** x */
     102             :     double x;
     103             :     /** y */
     104             :     double y;
     105             : };
     106             : 
     107             : /** GEOS geometry type */
     108             : typedef struct GEOSGeom_t *GEOSGeom;
     109             : /** GEOS context handle type */
     110             : typedef struct GEOSContextHandle_HS *GEOSContextHandle_t;
     111             : /** SFCGAL geometry type */
     112             : typedef void sfcgal_geometry_t;
     113             : 
     114             : class OGRPoint;
     115             : class OGRCurve;
     116             : class OGRCompoundCurve;
     117             : class OGRSimpleCurve;
     118             : class OGRLinearRing;
     119             : class OGRLineString;
     120             : class OGRCircularString;
     121             : class OGRSurface;
     122             : class OGRCurvePolygon;
     123             : class OGRPolygon;
     124             : class OGRMultiPoint;
     125             : class OGRMultiSurface;
     126             : class OGRMultiPolygon;
     127             : class OGRMultiCurve;
     128             : class OGRMultiLineString;
     129             : class OGRGeometryCollection;
     130             : class OGRTriangle;
     131             : class OGRPolyhedralSurface;
     132             : class OGRTriangulatedSurface;
     133             : 
     134             : //! @cond Doxygen_Suppress
     135             : typedef OGRLineString *(*OGRCurveCasterToLineString)(OGRCurve *);
     136             : typedef OGRLinearRing *(*OGRCurveCasterToLinearRing)(OGRCurve *);
     137             : 
     138             : typedef OGRPolygon *(*OGRSurfaceCasterToPolygon)(OGRSurface *);
     139             : typedef OGRCurvePolygon *(*OGRSurfaceCasterToCurvePolygon)(OGRSurface *);
     140             : typedef OGRMultiPolygon *(*OGRPolyhedralSurfaceCastToMultiPolygon)(
     141             :     OGRPolyhedralSurface *);
     142             : 
     143             : //! @endcond
     144             : 
     145             : /** OGRGeometry visitor interface.
     146             :  */
     147          86 : class CPL_DLL IOGRGeometryVisitor
     148             : {
     149             :   public:
     150             :     /** Destructor/ */
     151             :     virtual ~IOGRGeometryVisitor();
     152             : 
     153             :     /** Visit OGRPoint. */
     154             :     virtual void visit(OGRPoint *) = 0;
     155             :     /** Visit OGRLineString. */
     156             :     virtual void visit(OGRLineString *) = 0;
     157             :     /** Visit OGRLinearRing. */
     158             :     virtual void visit(OGRLinearRing *) = 0;
     159             :     /** Visit OGRPolygon. */
     160             :     virtual void visit(OGRPolygon *) = 0;
     161             :     /** Visit OGRMultiPoint. */
     162             :     virtual void visit(OGRMultiPoint *) = 0;
     163             :     /** Visit OGRMultiLineString. */
     164             :     virtual void visit(OGRMultiLineString *) = 0;
     165             :     /** Visit OGRMultiPolygon. */
     166             :     virtual void visit(OGRMultiPolygon *) = 0;
     167             :     /** Visit OGRGeometryCollection. */
     168             :     virtual void visit(OGRGeometryCollection *) = 0;
     169             :     /** Visit OGRCircularString. */
     170             :     virtual void visit(OGRCircularString *) = 0;
     171             :     /** Visit OGRCompoundCurve. */
     172             :     virtual void visit(OGRCompoundCurve *) = 0;
     173             :     /** Visit OGRCurvePolygon. */
     174             :     virtual void visit(OGRCurvePolygon *) = 0;
     175             :     /** Visit OGRMultiCurve. */
     176             :     virtual void visit(OGRMultiCurve *) = 0;
     177             :     /** Visit OGRMultiSurface. */
     178             :     virtual void visit(OGRMultiSurface *) = 0;
     179             :     /** Visit OGRTriangle. */
     180             :     virtual void visit(OGRTriangle *) = 0;
     181             :     /** Visit OGRPolyhedralSurface. */
     182             :     virtual void visit(OGRPolyhedralSurface *) = 0;
     183             :     /** Visit OGRTriangulatedSurface. */
     184             :     virtual void visit(OGRTriangulatedSurface *) = 0;
     185             : };
     186             : 
     187             : /** OGRGeometry visitor default implementation.
     188             :  *
     189             :  * This default implementation will recurse down to calling
     190             :  * visit(OGRPoint*) on each point.
     191             :  *
     192             :  */
     193             : class CPL_DLL OGRDefaultGeometryVisitor : public IOGRGeometryVisitor
     194             : {
     195             :     void _visit(OGRSimpleCurve *poGeom);
     196             : 
     197             :   public:
     198           0 :     void visit(OGRPoint *) override
     199             :     {
     200           0 :     }
     201             : 
     202             :     void visit(OGRLineString *) override;
     203             :     void visit(OGRLinearRing *) override;
     204             :     void visit(OGRPolygon *) override;
     205             :     void visit(OGRMultiPoint *) override;
     206             :     void visit(OGRMultiLineString *) override;
     207             :     void visit(OGRMultiPolygon *) override;
     208             :     void visit(OGRGeometryCollection *) override;
     209             :     void visit(OGRCircularString *) override;
     210             :     void visit(OGRCompoundCurve *) override;
     211             :     void visit(OGRCurvePolygon *) override;
     212             :     void visit(OGRMultiCurve *) override;
     213             :     void visit(OGRMultiSurface *) override;
     214             :     void visit(OGRTriangle *) override;
     215             :     void visit(OGRPolyhedralSurface *) override;
     216             :     void visit(OGRTriangulatedSurface *) override;
     217             : };
     218             : 
     219             : /** OGRGeometry visitor interface.
     220             :  */
     221         327 : class CPL_DLL IOGRConstGeometryVisitor
     222             : {
     223             :   public:
     224             :     /** Destructor/ */
     225             :     virtual ~IOGRConstGeometryVisitor();
     226             : 
     227             :     /** Visit OGRPoint. */
     228             :     virtual void visit(const OGRPoint *) = 0;
     229             :     /** Visit OGRLineString. */
     230             :     virtual void visit(const OGRLineString *) = 0;
     231             :     /** Visit OGRLinearRing. */
     232             :     virtual void visit(const OGRLinearRing *) = 0;
     233             :     /** Visit OGRPolygon. */
     234             :     virtual void visit(const OGRPolygon *) = 0;
     235             :     /** Visit OGRMultiPoint. */
     236             :     virtual void visit(const OGRMultiPoint *) = 0;
     237             :     /** Visit OGRMultiLineString. */
     238             :     virtual void visit(const OGRMultiLineString *) = 0;
     239             :     /** Visit OGRMultiPolygon. */
     240             :     virtual void visit(const OGRMultiPolygon *) = 0;
     241             :     /** Visit OGRGeometryCollection. */
     242             :     virtual void visit(const OGRGeometryCollection *) = 0;
     243             :     /** Visit OGRCircularString. */
     244             :     virtual void visit(const OGRCircularString *) = 0;
     245             :     /** Visit OGRCompoundCurve. */
     246             :     virtual void visit(const OGRCompoundCurve *) = 0;
     247             :     /** Visit OGRCurvePolygon. */
     248             :     virtual void visit(const OGRCurvePolygon *) = 0;
     249             :     /** Visit OGRMultiCurve. */
     250             :     virtual void visit(const OGRMultiCurve *) = 0;
     251             :     /** Visit OGRMultiSurface. */
     252             :     virtual void visit(const OGRMultiSurface *) = 0;
     253             :     /** Visit OGRTriangle. */
     254             :     virtual void visit(const OGRTriangle *) = 0;
     255             :     /** Visit OGRPolyhedralSurface. */
     256             :     virtual void visit(const OGRPolyhedralSurface *) = 0;
     257             :     /** Visit OGRTriangulatedSurface. */
     258             :     virtual void visit(const OGRTriangulatedSurface *) = 0;
     259             : };
     260             : 
     261             : /** OGRGeometry visitor default implementation.
     262             :  *
     263             :  * This default implementation will recurse down to calling
     264             :  * visit(const OGRPoint*) on each point.
     265             :  *
     266             :  */
     267             : class CPL_DLL OGRDefaultConstGeometryVisitor : public IOGRConstGeometryVisitor
     268             : {
     269             :     void _visit(const OGRSimpleCurve *poGeom);
     270             : 
     271             :   public:
     272           0 :     void visit(const OGRPoint *) override
     273             :     {
     274           0 :     }
     275             : 
     276             :     void visit(const OGRLineString *) override;
     277             :     void visit(const OGRLinearRing *) override;
     278             :     void visit(const OGRPolygon *) override;
     279             :     void visit(const OGRMultiPoint *) override;
     280             :     void visit(const OGRMultiLineString *) override;
     281             :     void visit(const OGRMultiPolygon *) override;
     282             :     void visit(const OGRGeometryCollection *) override;
     283             :     void visit(const OGRCircularString *) override;
     284             :     void visit(const OGRCompoundCurve *) override;
     285             :     void visit(const OGRCurvePolygon *) override;
     286             :     void visit(const OGRMultiCurve *) override;
     287             :     void visit(const OGRMultiSurface *) override;
     288             :     void visit(const OGRTriangle *) override;
     289             :     void visit(const OGRPolyhedralSurface *) override;
     290             :     void visit(const OGRTriangulatedSurface *) override;
     291             : };
     292             : 
     293             : /************************************************************************/
     294             : /*                   OGRGeomCoordinateBinaryPrecision                   */
     295             : /************************************************************************/
     296             : 
     297             : /** Geometry coordinate precision for a binary representation.
     298             :  *
     299             :  * @since GDAL 3.9
     300             :  */
     301             : class CPL_DLL OGRGeomCoordinateBinaryPrecision
     302             : {
     303             :   public:
     304             :     int nXYBitPrecision =
     305             :         INT_MIN; /**< Number of bits needed to achieved XY precision. Typically
     306             :                     computed with SetFromResolution() */
     307             :     int nZBitPrecision =
     308             :         INT_MIN; /**< Number of bits needed to achieved Z precision. Typically
     309             :                     computed with SetFromResolution() */
     310             :     int nMBitPrecision =
     311             :         INT_MIN; /**< Number of bits needed to achieved M precision. Typically
     312             :                     computed with SetFromResolution() */
     313             : 
     314             :     void SetFrom(const OGRGeomCoordinatePrecision &);
     315             : };
     316             : 
     317             : /************************************************************************/
     318             : /*                         OGRwkbExportOptions                          */
     319             : /************************************************************************/
     320             : 
     321             : /** WKB export options.
     322             :  *
     323             :  * @since GDAL 3.9
     324             :  */
     325             : struct CPL_DLL OGRwkbExportOptions
     326             : {
     327             :     OGRwkbByteOrder eByteOrder = wkbNDR;           /**< Byte order */
     328             :     OGRwkbVariant eWkbVariant = wkbVariantOldOgc;  /**< WKB variant. */
     329             :     OGRGeomCoordinateBinaryPrecision sPrecision{}; /**< Binary precision. */
     330             : };
     331             : 
     332             : /************************************************************************/
     333             : /*                             OGRGeometry                              */
     334             : /************************************************************************/
     335             : 
     336             : /**
     337             :  * Abstract base class for all geometry classes.
     338             :  *
     339             :  * Some spatial analysis methods require that OGR is built on the GEOS library
     340             :  * to work properly. The precise meaning of methods that describe spatial
     341             :  * relationships between geometries is described in the SFCOM, or other simple
     342             :  * features interface specifications, like "OpenGISĀ® Implementation
     343             :  * Specification for Geographic information - Simple feature access - Part 1:
     344             :  * Common architecture":
     345             :  * <a href="http://www.opengeospatial.org/standards/sfa">OGC 06-103r4</a>
     346             :  *
     347             :  * The hierarchy of classes has been extended with
     348             :  * <a href="https://portal.opengeospatial.org/files/?artifact_id=32024">
     349             :  * (working draft) ISO SQL/MM Part 3 (ISO/IEC 13249-3)</a> curve geometries :
     350             :  * CIRCULARSTRING (OGRCircularString), COMPOUNDCURVE (OGRCompoundCurve),
     351             :  * CURVEPOLYGON (OGRCurvePolygon), MULTICURVE (OGRMultiCurve) and
     352             :  * MULTISURFACE (OGRMultiSurface).
     353             :  *
     354             :  */
     355             : 
     356    10848100 : class CPL_DLL OGRGeometry
     357             : {
     358             :   private:
     359             :     const OGRSpatialReference *poSRS = nullptr;  // may be NULL
     360             : 
     361             :   protected:
     362             :     //! @cond Doxygen_Suppress
     363             :     friend class OGRCurveCollection;
     364             : 
     365             :     unsigned int flags = 0;
     366             : 
     367             :     OGRErr importPreambleFromWkt(const char **ppszInput, int *pbHasZ,
     368             :                                  int *pbHasM, bool *pbIsEmpty);
     369             :     OGRErr importCurveCollectionFromWkt(
     370             :         const char **ppszInput, int bAllowEmptyComponent, int bAllowLineString,
     371             :         int bAllowCurve, int bAllowCompoundCurve,
     372             :         OGRErr (*pfnAddCurveDirectly)(OGRGeometry *poSelf, OGRCurve *poCurve));
     373             :     OGRErr importPreambleFromWkb(const unsigned char *pabyData, size_t nSize,
     374             :                                  OGRwkbByteOrder &eByteOrder,
     375             :                                  OGRwkbVariant eWkbVariant);
     376             :     OGRErr importPreambleOfCollectionFromWkb(const unsigned char *pabyData,
     377             :                                              size_t &nSize, size_t &nDataOffset,
     378             :                                              OGRwkbByteOrder &eByteOrder,
     379             :                                              size_t nMinSubGeomSize,
     380             :                                              int &nGeomCount,
     381             :                                              OGRwkbVariant eWkbVariant);
     382             :     OGRErr PointOnSurfaceInternal(OGRPoint *poPoint) const;
     383             :     bool IsSFCGALCompatible() const;
     384             : 
     385             :     void HomogenizeDimensionalityWith(OGRGeometry *poOtherGeom);
     386             :     std::string wktTypeString(OGRwkbVariant variant) const;
     387             : 
     388             :     //! @endcond
     389             : 
     390             :   public:
     391             :     /************************************************************************/
     392             :     /*                   Bit flags for OGRGeometry                          */
     393             :     /*          The OGR_G_NOT_EMPTY_POINT is used *only* for points.        */
     394             :     /*          Do not use these outside of the core.                       */
     395             :     /*          Use Is3D, IsMeasured, set3D, and setMeasured instead        */
     396             :     /************************************************************************/
     397             : 
     398             :     //! @cond Doxygen_Suppress
     399             :     static const unsigned int OGR_G_NOT_EMPTY_POINT = 0x1;
     400             :     static const unsigned int OGR_G_3D = 0x2;
     401             :     static const unsigned int OGR_G_MEASURED = 0x4;
     402             :     //! @endcond
     403             : 
     404             :     OGRGeometry();
     405             :     OGRGeometry(const OGRGeometry &other);
     406             :     OGRGeometry(OGRGeometry &&other);
     407             :     virtual ~OGRGeometry();
     408             : 
     409             :     OGRGeometry &operator=(const OGRGeometry &other);
     410             :     OGRGeometry &operator=(OGRGeometry &&other);
     411             : 
     412             :     /** Returns if two geometries are equal. */
     413             :     bool operator==(const OGRGeometry &other) const
     414             :     {
     415             :         return Equals(&other);
     416             :     }
     417             : 
     418             :     /** Returns if two geometries are different. */
     419        1149 :     bool operator!=(const OGRGeometry &other) const
     420             :     {
     421        1149 :         return !Equals(&other);
     422             :     }
     423             : 
     424             :     // Standard IGeometry.
     425             :     virtual int getDimension() const = 0;
     426             :     virtual int getCoordinateDimension() const;
     427             :     int CoordinateDimension() const;
     428             :     virtual bool IsEmpty() const = 0;
     429             :     virtual bool IsValid(std::string *posReason = nullptr) const;
     430             :     virtual OGRGeometry *MakeValid(CSLConstList papszOptions = nullptr) const;
     431             :     virtual OGRGeometry *Normalize() const;
     432             :     virtual bool IsSimple() const;
     433             : 
     434             :     /*! Returns whether the geometry has a Z component. */
     435    21399445 :     bool Is3D() const
     436             :     {
     437    21399445 :         return (flags & OGR_G_3D) != 0;
     438             :     }
     439             : 
     440             :     /*! Returns whether the geometry has a M component. */
     441    15526890 :     bool IsMeasured() const
     442             :     {
     443    15526890 :         return (flags & OGR_G_MEASURED) != 0;
     444             :     }
     445             : 
     446             :     virtual bool IsRing() const;
     447             :     virtual void empty() = 0;
     448             :     virtual OGRGeometry *clone() const CPL_WARN_UNUSED_RESULT = 0;
     449             :     virtual void getEnvelope(OGREnvelope *psEnvelope) const = 0;
     450             :     virtual void getEnvelope(OGREnvelope3D *psEnvelope) const = 0;
     451             : 
     452             :     // IWks Interface.
     453             :     virtual size_t WkbSize() const = 0;
     454             :     OGRErr importFromWkb(const GByte *, size_t = static_cast<size_t>(-1),
     455             :                          OGRwkbVariant = wkbVariantOldOgc);
     456             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
     457             :                                  size_t &nBytesConsumedOut) = 0;
     458             :     OGRErr exportToWkb(OGRwkbByteOrder, unsigned char *,
     459             :                        OGRwkbVariant = wkbVariantOldOgc) const;
     460             :     virtual OGRErr exportToWkb(unsigned char *,
     461             :                                const OGRwkbExportOptions * = nullptr) const = 0;
     462             :     virtual OGRErr importFromWkt(const char **ppszInput) = 0;
     463             : 
     464             : #ifndef DOXYGEN_XML
     465             :     /** Deprecated.
     466             :      * @deprecated
     467             :      */
     468             :     OGRErr importFromWkt(char **ppszInput)
     469             :         /*! @cond Doxygen_Suppress */
     470             :         CPL_WARN_DEPRECATED("Use importFromWkt(const char**) instead")
     471             :     /*! @endcond */
     472             :     {
     473             :         return importFromWkt(const_cast<const char **>(ppszInput));
     474             :     }
     475             : #endif
     476             : 
     477             :     OGRErr exportToWkt(char **ppszDstText,
     478             :                        OGRwkbVariant = wkbVariantOldOgc) const;
     479             : 
     480             :     /// Export a WKT geometry.
     481             :     /// \param opts  Output options.
     482             :     /// \param err   Pointer to error code, if desired.
     483             :     /// \return  WKT string representing this geometry.
     484             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
     485             :                                     OGRErr *err = nullptr) const = 0;
     486             : 
     487             :     // Non-standard.
     488             :     virtual OGRwkbGeometryType getGeometryType() const = 0;
     489             :     OGRwkbGeometryType getIsoGeometryType() const;
     490             :     virtual const char *getGeometryName() const = 0;
     491             :     void dumpReadable(FILE *, const char * = nullptr,
     492             :                       CSLConstList papszOptions = nullptr) const;
     493             :     std::string dumpReadable(const char * = nullptr,
     494             :                              CSLConstList papszOptions = nullptr) const;
     495             :     virtual void flattenTo2D() = 0;
     496             :     virtual char *exportToGML(const char *const *papszOptions = nullptr) const;
     497             :     virtual char *exportToKML() const;
     498             :     virtual char *exportToJson(CSLConstList papszOptions = nullptr) const;
     499             : 
     500             :     /** Accept a visitor. */
     501             :     virtual void accept(IOGRGeometryVisitor *visitor) = 0;
     502             : 
     503             :     /** Accept a visitor. */
     504             :     virtual void accept(IOGRConstGeometryVisitor *visitor) const = 0;
     505             : 
     506             :     static GEOSContextHandle_t createGEOSContext();
     507             :     static void freeGEOSContext(GEOSContextHandle_t hGEOSCtxt);
     508             :     GEOSGeom
     509             :     exportToGEOS(GEOSContextHandle_t hGEOSCtxt, bool bRemoveEmptyParts = false,
     510             :                  bool bAddPointsIfNeeded = false) const CPL_WARN_UNUSED_RESULT;
     511             :     virtual bool hasCurveGeometry(int bLookForNonLinear = FALSE) const;
     512             :     virtual OGRGeometry *getCurveGeometry(
     513             :         const char *const *papszOptions = nullptr) const CPL_WARN_UNUSED_RESULT;
     514             :     virtual OGRGeometry *getLinearGeometry(
     515             :         double dfMaxAngleStepSizeDegrees = 0,
     516             :         const char *const *papszOptions = nullptr) const CPL_WARN_UNUSED_RESULT;
     517             : 
     518             :     void roundCoordinates(const OGRGeomCoordinatePrecision &sPrecision);
     519             :     void
     520             :     roundCoordinatesIEEE754(const OGRGeomCoordinateBinaryPrecision &options);
     521             : 
     522             :     // SFCGAL interfacing methods.
     523             :     //! @cond Doxygen_Suppress
     524             :     static sfcgal_geometry_t *OGRexportToSFCGAL(const OGRGeometry *poGeom);
     525             :     static OGRGeometry *SFCGALexportToOGR(const sfcgal_geometry_t *_geometry);
     526             :     //! @endcond
     527             :     virtual void closeRings();
     528             : 
     529             :     virtual bool setCoordinateDimension(int nDimension);
     530             :     virtual bool set3D(bool bIs3D);
     531             :     virtual bool setMeasured(bool bIsMeasured);
     532             : 
     533             :     virtual void assignSpatialReference(const OGRSpatialReference *poSR);
     534             : 
     535     1905256 :     const OGRSpatialReference *getSpatialReference(void) const
     536             :     {
     537     1905256 :         return poSRS;
     538             :     }
     539             : 
     540             :     virtual OGRErr transform(OGRCoordinateTransformation *poCT) = 0;
     541             :     OGRErr transformTo(const OGRSpatialReference *poSR);
     542             : 
     543             :     virtual bool segmentize(double dfMaxLength);
     544             : 
     545             :     // ISpatialRelation
     546             :     virtual bool Intersects(const OGRGeometry *) const;
     547             :     virtual bool Equals(const OGRGeometry *) const = 0;
     548             :     bool Disjoint(const OGRGeometry *) const;
     549             :     bool Touches(const OGRGeometry *) const;
     550             :     bool Crosses(const OGRGeometry *) const;
     551             :     virtual bool Within(const OGRGeometry *) const;
     552             :     virtual bool Contains(const OGRGeometry *) const;
     553             :     bool Overlaps(const OGRGeometry *) const;
     554             : 
     555             :     OGRGeometry *Boundary() const CPL_WARN_UNUSED_RESULT;
     556             : 
     557             :     double Distance(const OGRGeometry *) const;
     558             : 
     559             :     OGRGeometry *ConvexHull() const CPL_WARN_UNUSED_RESULT;
     560             : 
     561             :     OGRGeometry *ConcaveHull(double dfRatio,
     562             :                              bool bAllowHoles) const CPL_WARN_UNUSED_RESULT;
     563             : 
     564             :     OGRGeometry *
     565             :     ConcaveHullOfPolygons(double dfLengthRatio, bool bIsTight,
     566             :                           bool bAllowHoles) const CPL_WARN_UNUSED_RESULT;
     567             : 
     568             :     OGRGeometry *Buffer(double dfDist,
     569             :                         int nQuadSegs = 30) const CPL_WARN_UNUSED_RESULT;
     570             : 
     571             :     OGRGeometry *
     572             :     BufferEx(double dfDist,
     573             :              CSLConstList papszOptions) const CPL_WARN_UNUSED_RESULT;
     574             : 
     575             :     OGRGeometry *Intersection(const OGRGeometry *) const CPL_WARN_UNUSED_RESULT;
     576             : 
     577             :     OGRGeometry *Union(const OGRGeometry *) const CPL_WARN_UNUSED_RESULT;
     578             : 
     579             :     OGRGeometry *UnionCascaded() const CPL_WARN_UNUSED_RESULT;
     580             : 
     581             :     OGRGeometry *UnaryUnion() const CPL_WARN_UNUSED_RESULT;
     582             : 
     583             :     OGRGeometry *Difference(const OGRGeometry *) const CPL_WARN_UNUSED_RESULT;
     584             : 
     585             :     OGRGeometry *
     586             :     SymDifference(const OGRGeometry *) const CPL_WARN_UNUSED_RESULT;
     587             : 
     588             :     OGRErr Centroid(OGRPoint *poPoint) const;
     589             : 
     590             :     OGRGeometry *Simplify(double dTolerance) const CPL_WARN_UNUSED_RESULT;
     591             : 
     592             :     OGRGeometry *
     593             :     SimplifyPreserveTopology(double dTolerance) const CPL_WARN_UNUSED_RESULT;
     594             : 
     595             :     OGRGeometry *
     596             :     DelaunayTriangulation(double dfTolerance,
     597             :                           int bOnlyEdges) const CPL_WARN_UNUSED_RESULT;
     598             : 
     599             :     OGRGeometry *
     600             :     ConstrainedDelaunayTriangulation() const CPL_WARN_UNUSED_RESULT;
     601             : 
     602             :     OGRGeometry *Polygonize() const CPL_WARN_UNUSED_RESULT;
     603             : 
     604             :     OGRGeometry *BuildArea() const CPL_WARN_UNUSED_RESULT;
     605             : 
     606             :     double Distance3D(const OGRGeometry *poOtherGeom) const;
     607             : 
     608             :     OGRGeometry *SetPrecision(double dfGridSize, int nFlags) const;
     609             : 
     610             :     virtual bool hasEmptyParts() const;
     611             :     virtual void removeEmptyParts();
     612             : 
     613             :     //! @cond Doxygen_Suppress
     614             :     // backward compatibility to non-standard method names.
     615             :     bool Intersect(OGRGeometry *) const
     616             :         CPL_WARN_DEPRECATED("Non standard method. "
     617             :                             "Use Intersects() instead");
     618             :     bool Equal(OGRGeometry *) const CPL_WARN_DEPRECATED("Non standard method. "
     619             :                                                         "Use Equals() instead");
     620             :     OGRGeometry *SymmetricDifference(const OGRGeometry *) const
     621             :         CPL_WARN_DEPRECATED("Non standard method. "
     622             :                             "Use SymDifference() instead");
     623             :     OGRGeometry *getBoundary() const
     624             :         CPL_WARN_DEPRECATED("Non standard method. "
     625             :                             "Use Boundary() instead");
     626             :     //! @endcond
     627             : 
     628             :     //! @cond Doxygen_Suppress
     629             :     // Special HACK for DB2 7.2 support
     630             :     static int bGenerate_DB2_V72_BYTE_ORDER;
     631             :     //! @endcond
     632             : 
     633             :     virtual void swapXY();
     634             : 
     635             :     bool IsRectangle() const;
     636             : 
     637             :     //! @cond Doxygen_Suppress
     638             :     static OGRGeometry *CastToIdentity(OGRGeometry *poGeom)
     639             :     {
     640             :         return poGeom;
     641             :     }
     642             : 
     643             :     static OGRGeometry *CastToError(OGRGeometry *poGeom);
     644             : 
     645             :     //! @endcond
     646             : 
     647             :     /** Convert a OGRGeometry* to a OGRGeometryH.
     648             :      */
     649      477200 :     static inline OGRGeometryH ToHandle(OGRGeometry *poGeom)
     650             :     {
     651      477200 :         return reinterpret_cast<OGRGeometryH>(poGeom);
     652             :     }
     653             : 
     654             :     /** Convert a OGRGeometryH to a OGRGeometry*.
     655             :      */
     656     1828303 :     static inline OGRGeometry *FromHandle(OGRGeometryH hGeom)
     657             :     {
     658     1828303 :         return reinterpret_cast<OGRGeometry *>(hGeom);
     659             :     }
     660             : 
     661             :     /** Down-cast to OGRPoint*.
     662             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbPoint.
     663             :      */
     664      188924 :     inline OGRPoint *toPoint()
     665             :     {
     666      188924 :         return cpl::down_cast<OGRPoint *>(this);
     667             :     }
     668             : 
     669             :     /** Down-cast to OGRPoint*.
     670             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbPoint.
     671             :      */
     672       59428 :     inline const OGRPoint *toPoint() const
     673             :     {
     674       59428 :         return cpl::down_cast<const OGRPoint *>(this);
     675             :     }
     676             : 
     677             :     /** Down-cast to OGRCurve*.
     678             :      * Implies prior checking that OGR_GT_IsSubClass(getGeometryType(),
     679             :      * wkbCurve).
     680             :      */
     681       12327 :     inline OGRCurve *toCurve()
     682             :     {
     683       12327 :         return cpl::down_cast<OGRCurve *>(this);
     684             :     }
     685             : 
     686             :     /** Down-cast to OGRCurve*.
     687             :      * Implies prior checking that OGR_GT_IsSubClass(getGeometryType(),
     688             :      * wkbCurve).
     689             :      */
     690          59 :     inline const OGRCurve *toCurve() const
     691             :     {
     692          59 :         return cpl::down_cast<const OGRCurve *>(this);
     693             :     }
     694             : 
     695             :     /** Down-cast to OGRSimpleCurve*.
     696             :      * Implies prior checking that getGeometryType() is wkbLineString,
     697             :      * wkbCircularString or a derived type.
     698             :      */
     699      412550 :     inline OGRSimpleCurve *toSimpleCurve()
     700             :     {
     701      412550 :         return cpl::down_cast<OGRSimpleCurve *>(this);
     702             :     }
     703             : 
     704             :     /** Down-cast to OGRSimpleCurve*.
     705             :      * Implies prior checking that getGeometryType() is wkbLineString,
     706             :      * wkbCircularString or a derived type.
     707             :      */
     708       61762 :     inline const OGRSimpleCurve *toSimpleCurve() const
     709             :     {
     710       61762 :         return cpl::down_cast<const OGRSimpleCurve *>(this);
     711             :     }
     712             : 
     713             :     /** Down-cast to OGRLineString*.
     714             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     715             :      * wkbLineString.
     716             :      */
     717       33162 :     inline OGRLineString *toLineString()
     718             :     {
     719       33162 :         return cpl::down_cast<OGRLineString *>(this);
     720             :     }
     721             : 
     722             :     /** Down-cast to OGRLineString*.
     723             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     724             :      * wkbLineString.
     725             :      */
     726       41636 :     inline const OGRLineString *toLineString() const
     727             :     {
     728       41636 :         return cpl::down_cast<const OGRLineString *>(this);
     729             :     }
     730             : 
     731             :     /** Down-cast to OGRLinearRing*.
     732             :      * Implies prior checking that EQUAL(getGeometryName(), "LINEARRING").
     733             :      */
     734      203491 :     inline OGRLinearRing *toLinearRing()
     735             :     {
     736      203491 :         return cpl::down_cast<OGRLinearRing *>(this);
     737             :     }
     738             : 
     739             :     /** Down-cast to OGRLinearRing*.
     740             :      * Implies prior checking that EQUAL(getGeometryName(), "LINEARRING").
     741             :      */
     742        5136 :     inline const OGRLinearRing *toLinearRing() const
     743             :     {
     744        5136 :         return cpl::down_cast<const OGRLinearRing *>(this);
     745             :     }
     746             : 
     747             :     /** Down-cast to OGRCircularString*.
     748             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     749             :      * wkbCircularString.
     750             :      */
     751           3 :     inline OGRCircularString *toCircularString()
     752             :     {
     753           3 :         return cpl::down_cast<OGRCircularString *>(this);
     754             :     }
     755             : 
     756             :     /** Down-cast to OGRCircularString*.
     757             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     758             :      * wkbCircularString.
     759             :      */
     760          69 :     inline const OGRCircularString *toCircularString() const
     761             :     {
     762          69 :         return cpl::down_cast<const OGRCircularString *>(this);
     763             :     }
     764             : 
     765             :     /** Down-cast to OGRCompoundCurve*.
     766             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     767             :      * wkbCompoundCurve.
     768             :      */
     769        2756 :     inline OGRCompoundCurve *toCompoundCurve()
     770             :     {
     771        2756 :         return cpl::down_cast<OGRCompoundCurve *>(this);
     772             :     }
     773             : 
     774             :     /** Down-cast to OGRCompoundCurve*.
     775             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     776             :      * wkbCompoundCurve.
     777             :      */
     778         906 :     inline const OGRCompoundCurve *toCompoundCurve() const
     779             :     {
     780         906 :         return cpl::down_cast<const OGRCompoundCurve *>(this);
     781             :     }
     782             : 
     783             :     /** Down-cast to OGRSurface*.
     784             :      * Implies prior checking that OGR_GT_IsSubClass(getGeometryType(),
     785             :      * wkbSurface).
     786             :      */
     787        1625 :     inline OGRSurface *toSurface()
     788             :     {
     789        1625 :         return cpl::down_cast<OGRSurface *>(this);
     790             :     }
     791             : 
     792             :     /** Down-cast to OGRSurface*.
     793             :      * Implies prior checking that OGR_GT_IsSubClass(getGeometryType(),
     794             :      * wkbSurface).
     795             :      */
     796         110 :     inline const OGRSurface *toSurface() const
     797             :     {
     798         110 :         return cpl::down_cast<const OGRSurface *>(this);
     799             :     }
     800             : 
     801             :     /** Down-cast to OGRPolygon*.
     802             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbPolygon
     803             :      * or wkbTriangle.
     804             :      */
     805       57362 :     inline OGRPolygon *toPolygon()
     806             :     {
     807       57362 :         return cpl::down_cast<OGRPolygon *>(this);
     808             :     }
     809             : 
     810             :     /** Down-cast to OGRPolygon*.
     811             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbPolygon
     812             :      * or wkbTriangle.
     813             :      */
     814      241966 :     inline const OGRPolygon *toPolygon() const
     815             :     {
     816      241966 :         return cpl::down_cast<const OGRPolygon *>(this);
     817             :     }
     818             : 
     819             :     /** Down-cast to OGRTriangle*.
     820             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbTriangle.
     821             :      */
     822       52101 :     inline OGRTriangle *toTriangle()
     823             :     {
     824       52101 :         return cpl::down_cast<OGRTriangle *>(this);
     825             :     }
     826             : 
     827             :     /** Down-cast to OGRTriangle*.
     828             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbTriangle.
     829             :      */
     830           2 :     inline const OGRTriangle *toTriangle() const
     831             :     {
     832           2 :         return cpl::down_cast<const OGRTriangle *>(this);
     833             :     }
     834             : 
     835             :     /** Down-cast to OGRCurvePolygon*.
     836             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     837             :      * wkbCurvePolygon or wkbPolygon or wkbTriangle.
     838             :      */
     839       77008 :     inline OGRCurvePolygon *toCurvePolygon()
     840             :     {
     841       77008 :         return cpl::down_cast<OGRCurvePolygon *>(this);
     842             :     }
     843             : 
     844             :     /** Down-cast to OGRCurvePolygon*.
     845             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     846             :      * wkbCurvePolygon or wkbPolygon or wkbTriangle.
     847             :      */
     848       42876 :     inline const OGRCurvePolygon *toCurvePolygon() const
     849             :     {
     850       42876 :         return cpl::down_cast<const OGRCurvePolygon *>(this);
     851             :     }
     852             : 
     853             :     /** Down-cast to OGRGeometryCollection*.
     854             :      * Implies prior checking that OGR_GT_IsSubClass(getGeometryType(),
     855             :      * wkbGeometryCollection).
     856             :      */
     857       17266 :     inline OGRGeometryCollection *toGeometryCollection()
     858             :     {
     859       17266 :         return cpl::down_cast<OGRGeometryCollection *>(this);
     860             :     }
     861             : 
     862             :     /** Down-cast to OGRGeometryCollection*.
     863             :      * Implies prior checking that OGR_GT_IsSubClass(getGeometryType(),
     864             :      * wkbGeometryCollection).
     865             :      */
     866        6661 :     inline const OGRGeometryCollection *toGeometryCollection() const
     867             :     {
     868        6661 :         return cpl::down_cast<const OGRGeometryCollection *>(this);
     869             :     }
     870             : 
     871             :     /** Down-cast to OGRMultiPoint*.
     872             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     873             :      * wkbMultiPoint.
     874             :      */
     875         201 :     inline OGRMultiPoint *toMultiPoint()
     876             :     {
     877         201 :         return cpl::down_cast<OGRMultiPoint *>(this);
     878             :     }
     879             : 
     880             :     /** Down-cast to OGRMultiPoint*.
     881             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     882             :      * wkbMultiPoint.
     883             :      */
     884         220 :     inline const OGRMultiPoint *toMultiPoint() const
     885             :     {
     886         220 :         return cpl::down_cast<const OGRMultiPoint *>(this);
     887             :     }
     888             : 
     889             :     /** Down-cast to OGRMultiLineString*.
     890             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     891             :      * wkbMultiLineString.
     892             :      */
     893         220 :     inline OGRMultiLineString *toMultiLineString()
     894             :     {
     895         220 :         return cpl::down_cast<OGRMultiLineString *>(this);
     896             :     }
     897             : 
     898             :     /** Down-cast to OGRMultiLineString*.
     899             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     900             :      * wkbMultiLineString.
     901             :      */
     902         127 :     inline const OGRMultiLineString *toMultiLineString() const
     903             :     {
     904         127 :         return cpl::down_cast<const OGRMultiLineString *>(this);
     905             :     }
     906             : 
     907             :     /** Down-cast to OGRMultiPolygon*.
     908             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     909             :      * wkbMultiPolygon.
     910             :      */
     911         662 :     inline OGRMultiPolygon *toMultiPolygon()
     912             :     {
     913         662 :         return cpl::down_cast<OGRMultiPolygon *>(this);
     914             :     }
     915             : 
     916             :     /** Down-cast to OGRMultiPolygon*.
     917             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     918             :      * wkbMultiPolygon.
     919             :      */
     920       66558 :     inline const OGRMultiPolygon *toMultiPolygon() const
     921             :     {
     922       66558 :         return cpl::down_cast<const OGRMultiPolygon *>(this);
     923             :     }
     924             : 
     925             :     /** Down-cast to OGRMultiCurve*.
     926             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     927             :      * wkbMultiCurve and derived types.
     928             :      */
     929        1081 :     inline OGRMultiCurve *toMultiCurve()
     930             :     {
     931        1081 :         return cpl::down_cast<OGRMultiCurve *>(this);
     932             :     }
     933             : 
     934             :     /** Down-cast to OGRMultiCurve*.
     935             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     936             :      * wkbMultiCurve and derived types.
     937             :      */
     938          41 :     inline const OGRMultiCurve *toMultiCurve() const
     939             :     {
     940          41 :         return cpl::down_cast<const OGRMultiCurve *>(this);
     941             :     }
     942             : 
     943             :     /** Down-cast to OGRMultiSurface*.
     944             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     945             :      * wkbMultiSurface and derived types.
     946             :      */
     947          17 :     inline OGRMultiSurface *toMultiSurface()
     948             :     {
     949          17 :         return cpl::down_cast<OGRMultiSurface *>(this);
     950             :     }
     951             : 
     952             :     /** Down-cast to OGRMultiSurface*.
     953             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     954             :      * wkbMultiSurface and derived types.
     955             :      */
     956         100 :     inline const OGRMultiSurface *toMultiSurface() const
     957             :     {
     958         100 :         return cpl::down_cast<const OGRMultiSurface *>(this);
     959             :     }
     960             : 
     961             :     /** Down-cast to OGRPolyhedralSurface*.
     962             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     963             :      * wkbPolyhedralSurface or wkbTIN.
     964             :      */
     965        1226 :     inline OGRPolyhedralSurface *toPolyhedralSurface()
     966             :     {
     967        1226 :         return cpl::down_cast<OGRPolyhedralSurface *>(this);
     968             :     }
     969             : 
     970             :     /** Down-cast to OGRPolyhedralSurface*.
     971             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
     972             :      * wkbPolyhedralSurface or wkbTIN.
     973             :      */
     974        5767 :     inline const OGRPolyhedralSurface *toPolyhedralSurface() const
     975             :     {
     976        5767 :         return cpl::down_cast<const OGRPolyhedralSurface *>(this);
     977             :     }
     978             : 
     979             :     /** Down-cast to OGRTriangulatedSurface*.
     980             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbTIN.
     981             :      */
     982           4 :     inline OGRTriangulatedSurface *toTriangulatedSurface()
     983             :     {
     984           4 :         return cpl::down_cast<OGRTriangulatedSurface *>(this);
     985             :     }
     986             : 
     987             :     /** Down-cast to OGRTriangulatedSurface*.
     988             :      * Implies prior checking that wkbFlatten(getGeometryType()) == wkbTIN.
     989             :      */
     990           2 :     inline const OGRTriangulatedSurface *toTriangulatedSurface() const
     991             :     {
     992           2 :         return cpl::down_cast<const OGRTriangulatedSurface *>(this);
     993             :     }
     994             : };
     995             : 
     996             : //! @cond Doxygen_Suppress
     997             : struct CPL_DLL OGRGeometryUniquePtrDeleter
     998             : {
     999             :     void operator()(OGRGeometry *) const;
    1000             : };
    1001             : 
    1002             : //! @endcond
    1003             : 
    1004             : /** Unique pointer type for OGRGeometry.
    1005             :  */
    1006             : typedef std::unique_ptr<OGRGeometry, OGRGeometryUniquePtrDeleter>
    1007             :     OGRGeometryUniquePtr;
    1008             : 
    1009             : //! @cond Doxygen_Suppress
    1010             : #define OGR_FORBID_DOWNCAST_TO(name)                                           \
    1011             :     inline OGR##name *to##name() = delete;                                     \
    1012             :     inline const OGR##name *to##name() const = delete;
    1013             : 
    1014             : #define OGR_FORBID_DOWNCAST_TO_POINT OGR_FORBID_DOWNCAST_TO(Point)
    1015             : #define OGR_FORBID_DOWNCAST_TO_CURVE OGR_FORBID_DOWNCAST_TO(Curve)
    1016             : #define OGR_FORBID_DOWNCAST_TO_SIMPLE_CURVE OGR_FORBID_DOWNCAST_TO(SimpleCurve)
    1017             : #define OGR_FORBID_DOWNCAST_TO_LINESTRING OGR_FORBID_DOWNCAST_TO(LineString)
    1018             : #define OGR_FORBID_DOWNCAST_TO_LINEARRING OGR_FORBID_DOWNCAST_TO(LinearRing)
    1019             : #define OGR_FORBID_DOWNCAST_TO_CIRCULARSTRING                                  \
    1020             :     OGR_FORBID_DOWNCAST_TO(CircularString)
    1021             : #define OGR_FORBID_DOWNCAST_TO_COMPOUNDCURVE                                   \
    1022             :     OGR_FORBID_DOWNCAST_TO(CompoundCurve)
    1023             : #define OGR_FORBID_DOWNCAST_TO_SURFACE OGR_FORBID_DOWNCAST_TO(Surface)
    1024             : #define OGR_FORBID_DOWNCAST_TO_CURVEPOLYGON OGR_FORBID_DOWNCAST_TO(CurvePolygon)
    1025             : #define OGR_FORBID_DOWNCAST_TO_POLYGON OGR_FORBID_DOWNCAST_TO(Polygon)
    1026             : #define OGR_FORBID_DOWNCAST_TO_TRIANGLE OGR_FORBID_DOWNCAST_TO(Triangle)
    1027             : #define OGR_FORBID_DOWNCAST_TO_MULTIPOINT OGR_FORBID_DOWNCAST_TO(MultiPoint)
    1028             : #define OGR_FORBID_DOWNCAST_TO_MULTICURVE OGR_FORBID_DOWNCAST_TO(MultiCurve)
    1029             : #define OGR_FORBID_DOWNCAST_TO_MULTILINESTRING                                 \
    1030             :     OGR_FORBID_DOWNCAST_TO(MultiLineString)
    1031             : #define OGR_FORBID_DOWNCAST_TO_MULTISURFACE OGR_FORBID_DOWNCAST_TO(MultiSurface)
    1032             : #define OGR_FORBID_DOWNCAST_TO_MULTIPOLYGON OGR_FORBID_DOWNCAST_TO(MultiPolygon)
    1033             : #define OGR_FORBID_DOWNCAST_TO_GEOMETRYCOLLECTION                              \
    1034             :     OGR_FORBID_DOWNCAST_TO(GeometryCollection)
    1035             : #define OGR_FORBID_DOWNCAST_TO_POLYHEDRALSURFACE                               \
    1036             :     OGR_FORBID_DOWNCAST_TO(PolyhedralSurface)
    1037             : #define OGR_FORBID_DOWNCAST_TO_TIN OGR_FORBID_DOWNCAST_TO(TriangulatedSurface)
    1038             : 
    1039             : #define OGR_ALLOW_UPCAST_TO(name)                                              \
    1040             :     inline OGR##name *to##name()                                               \
    1041             :     {                                                                          \
    1042             :         return this;                                                           \
    1043             :     }                                                                          \
    1044             :     inline const OGR##name *to##name() const                                   \
    1045             :     {                                                                          \
    1046             :         return this;                                                           \
    1047             :     }
    1048             : 
    1049             : #ifndef SUPPRESS_OGR_ALLOW_CAST_TO_THIS_WARNING
    1050             : #define CAST_TO_THIS_WARNING CPL_WARN_DEPRECATED("Casting to this is useless")
    1051             : #else
    1052             : #define CAST_TO_THIS_WARNING
    1053             : #endif
    1054             : 
    1055             : #define OGR_ALLOW_CAST_TO_THIS(name)                                           \
    1056             :     inline OGR##name *to##name() CAST_TO_THIS_WARNING                          \
    1057             :     {                                                                          \
    1058             :         return this;                                                           \
    1059             :     }                                                                          \
    1060             :     inline const OGR##name *to##name() const CAST_TO_THIS_WARNING              \
    1061             :     {                                                                          \
    1062             :         return this;                                                           \
    1063             :     }
    1064             : 
    1065             : #define OGR_FORBID_DOWNCAST_TO_ALL_CURVES                                      \
    1066             :     OGR_FORBID_DOWNCAST_TO_CURVE                                               \
    1067             :     OGR_FORBID_DOWNCAST_TO_SIMPLE_CURVE                                        \
    1068             :     OGR_FORBID_DOWNCAST_TO_LINESTRING                                          \
    1069             :     OGR_FORBID_DOWNCAST_TO_LINEARRING                                          \
    1070             :     OGR_FORBID_DOWNCAST_TO_CIRCULARSTRING                                      \
    1071             :     OGR_FORBID_DOWNCAST_TO_COMPOUNDCURVE
    1072             : 
    1073             : #define OGR_FORBID_DOWNCAST_TO_ALL_SURFACES                                    \
    1074             :     OGR_FORBID_DOWNCAST_TO_SURFACE                                             \
    1075             :     OGR_FORBID_DOWNCAST_TO_CURVEPOLYGON                                        \
    1076             :     OGR_FORBID_DOWNCAST_TO_POLYGON                                             \
    1077             :     OGR_FORBID_DOWNCAST_TO_TRIANGLE                                            \
    1078             :     OGR_FORBID_DOWNCAST_TO_POLYHEDRALSURFACE                                   \
    1079             :     OGR_FORBID_DOWNCAST_TO_TIN
    1080             : 
    1081             : #define OGR_FORBID_DOWNCAST_TO_ALL_SINGLES                                     \
    1082             :     OGR_FORBID_DOWNCAST_TO_POINT                                               \
    1083             :     OGR_FORBID_DOWNCAST_TO_ALL_CURVES                                          \
    1084             :     OGR_FORBID_DOWNCAST_TO_ALL_SURFACES
    1085             : 
    1086             : #define OGR_FORBID_DOWNCAST_TO_ALL_MULTI                                       \
    1087             :     OGR_FORBID_DOWNCAST_TO_GEOMETRYCOLLECTION                                  \
    1088             :     OGR_FORBID_DOWNCAST_TO_MULTIPOINT                                          \
    1089             :     OGR_FORBID_DOWNCAST_TO_MULTICURVE                                          \
    1090             :     OGR_FORBID_DOWNCAST_TO_MULTILINESTRING                                     \
    1091             :     OGR_FORBID_DOWNCAST_TO_MULTISURFACE                                        \
    1092             :     OGR_FORBID_DOWNCAST_TO_MULTIPOLYGON
    1093             : 
    1094             : //! @endcond
    1095             : 
    1096             : /************************************************************************/
    1097             : /*                               OGRPoint                               */
    1098             : /************************************************************************/
    1099             : 
    1100             : /**
    1101             :  * Point class.
    1102             :  *
    1103             :  * Implements SFCOM IPoint methods.
    1104             :  */
    1105             : 
    1106      374532 : class CPL_DLL OGRPoint : public OGRGeometry
    1107             : {
    1108             :     double x;
    1109             :     double y;
    1110             :     double z;
    1111             :     double m;
    1112             : 
    1113             :   public:
    1114             :     OGRPoint();
    1115             :     OGRPoint(double x, double y);
    1116             :     OGRPoint(double x, double y, double z);
    1117             :     OGRPoint(double x, double y, double z, double m);
    1118             :     OGRPoint(const OGRPoint &other);
    1119             :     /** Move constructor */
    1120      156261 :     OGRPoint(OGRPoint &&other) = default;
    1121             :     static OGRPoint *createXYM(double x, double y, double m);
    1122             : 
    1123             :     OGRPoint &operator=(const OGRPoint &other);
    1124             :     /** Move assignment operator */
    1125             :     OGRPoint &operator=(OGRPoint &&other) = default;
    1126             : 
    1127             :     /** Corresponding 2D OGRwkbGeometryType constant. */
    1128             :     static constexpr OGRwkbGeometryType EnumType2D = wkbPoint;
    1129             : 
    1130             :     /** C++ type for corresponding collection. */
    1131             :     using MultiType = OGRMultiPoint;
    1132             : 
    1133             :     // IWks Interface
    1134             :     size_t WkbSize() const override;
    1135             :     OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    1136             :                          size_t &nBytesConsumedOut) override;
    1137             :     OGRErr exportToWkb(unsigned char *,
    1138             :                        const OGRwkbExportOptions * = nullptr) const override;
    1139             : 
    1140             : #ifndef DOXYGEN_XML
    1141             :     using OGRGeometry::importFromWkt; /** deprecated */
    1142             : #endif
    1143             : 
    1144             :     OGRErr importFromWkt(const char **) override;
    1145             : 
    1146             : #ifndef DOXYGEN_XML
    1147             :     using OGRGeometry::exportToWkt;
    1148             : #endif
    1149             : 
    1150             :     /// Export a point to WKT
    1151             :     /// \param opts  Output options.
    1152             :     /// \param err   Pointer to error code, if desired.
    1153             :     /// \return  WKT string representing this point.
    1154             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    1155             :                                     OGRErr *err = nullptr) const override;
    1156             : 
    1157             :     // IGeometry
    1158             :     int getDimension() const override;
    1159             :     OGRPoint *clone() const override;
    1160             :     void empty() override;
    1161             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    1162             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    1163             : 
    1164     4409564 :     bool IsEmpty() const override
    1165             :     {
    1166     4409564 :         return !(flags & OGR_G_NOT_EMPTY_POINT);
    1167             :     }
    1168             : 
    1169             :     // IPoint
    1170             :     /** Return x */
    1171    13920433 :     double getX() const
    1172             :     {
    1173    13920433 :         return x;
    1174             :     }
    1175             : 
    1176             :     /** Return y */
    1177    13669474 :     double getY() const
    1178             :     {
    1179    13669474 :         return y;
    1180             :     }
    1181             : 
    1182             :     /** Return z */
    1183     5368465 :     double getZ() const
    1184             :     {
    1185     5368465 :         return z;
    1186             :     }
    1187             : 
    1188             :     /** Return m */
    1189        1187 :     double getM() const
    1190             :     {
    1191        1187 :         return m;
    1192             :     }
    1193             : 
    1194             :     // Non standard
    1195             :     bool setCoordinateDimension(int nDimension) override;
    1196             : 
    1197             :     /** Set x
    1198             :      * @param xIn x
    1199             :      */
    1200     2074041 :     void setX(double xIn)
    1201             :     {
    1202     2074041 :         x = xIn;
    1203     2074041 :         if (std::isnan(x) || std::isnan(y))
    1204           5 :             flags &= ~OGR_G_NOT_EMPTY_POINT;
    1205             :         else
    1206     2074040 :             flags |= OGR_G_NOT_EMPTY_POINT;
    1207     2074041 :     }
    1208             : 
    1209             :     /** Set y
    1210             :      * @param yIn y
    1211             :      */
    1212     2073939 :     void setY(double yIn)
    1213             :     {
    1214     2073939 :         y = yIn;
    1215     2073939 :         if (std::isnan(x) || std::isnan(y))
    1216           7 :             flags &= ~OGR_G_NOT_EMPTY_POINT;
    1217             :         else
    1218     2073936 :             flags |= OGR_G_NOT_EMPTY_POINT;
    1219     2073939 :     }
    1220             : 
    1221             :     /** Set z
    1222             :      * @param zIn z
    1223             :      */
    1224       50250 :     void setZ(double zIn)
    1225             :     {
    1226       50250 :         z = zIn;
    1227       50250 :         flags |= OGR_G_3D;
    1228       50250 :     }
    1229             : 
    1230             :     /** Set m
    1231             :      * @param mIn m
    1232             :      */
    1233       29053 :     void setM(double mIn)
    1234             :     {
    1235       29053 :         m = mIn;
    1236       29053 :         flags |= OGR_G_MEASURED;
    1237       29053 :     }
    1238             : 
    1239             :     // ISpatialRelation
    1240             :     bool Equals(const OGRGeometry *) const override;
    1241             :     bool Intersects(const OGRGeometry *) const override;
    1242             :     bool Within(const OGRGeometry *) const override;
    1243             : 
    1244             :     // Non standard from OGRGeometry
    1245             :     const char *getGeometryName() const override;
    1246             :     OGRwkbGeometryType getGeometryType() const override;
    1247             :     OGRErr transform(OGRCoordinateTransformation *poCT) override;
    1248             :     void flattenTo2D() override;
    1249             : 
    1250        1150 :     void accept(IOGRGeometryVisitor *visitor) override
    1251             :     {
    1252        1150 :         visitor->visit(this);
    1253        1150 :     }
    1254             : 
    1255       68229 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    1256             :     {
    1257       68229 :         visitor->visit(this);
    1258       68229 :     }
    1259             : 
    1260             :     void swapXY() override;
    1261             : 
    1262             :     OGR_ALLOW_CAST_TO_THIS(Point)
    1263             :     OGR_FORBID_DOWNCAST_TO_ALL_CURVES
    1264             :     OGR_FORBID_DOWNCAST_TO_ALL_SURFACES
    1265             :     OGR_FORBID_DOWNCAST_TO_ALL_MULTI
    1266             : };
    1267             : 
    1268             : /************************************************************************/
    1269             : /*                           OGRPointIterator                           */
    1270             : /************************************************************************/
    1271             : 
    1272             : /**
    1273             :  * Interface for a point iterator.
    1274             :  *
    1275             :  */
    1276             : 
    1277         341 : class CPL_DLL OGRPointIterator
    1278             : {
    1279             :   public:
    1280             :     virtual ~OGRPointIterator();
    1281             :     virtual bool getNextPoint(OGRPoint *p) = 0;
    1282             : 
    1283             :     static void destroy(OGRPointIterator *);
    1284             : };
    1285             : 
    1286             : /************************************************************************/
    1287             : /*                               OGRCurve                               */
    1288             : /************************************************************************/
    1289             : 
    1290             : /**
    1291             :  * Abstract curve base class for OGRLineString, OGRCircularString and
    1292             :  * OGRCompoundCurve
    1293             :  */
    1294             : 
    1295           8 : class CPL_DLL OGRCurve : public OGRGeometry
    1296             : {
    1297             :   protected:
    1298             :     //! @cond Doxygen_Suppress
    1299     3483412 :     OGRCurve() = default;
    1300       10245 :     OGRCurve(const OGRCurve &other) = default;
    1301           4 :     OGRCurve(OGRCurve &&other) = default;
    1302             : 
    1303             :     virtual OGRCurveCasterToLineString GetCasterToLineString() const = 0;
    1304             :     virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const = 0;
    1305             : 
    1306             :     friend class OGRCurvePolygon;
    1307             :     friend class OGRCompoundCurve;
    1308             :     //! @endcond
    1309             :     virtual int ContainsPoint(const OGRPoint *p) const;
    1310             :     virtual int IntersectsPoint(const OGRPoint *p) const;
    1311             :     virtual double get_AreaOfCurveSegments() const = 0;
    1312             : 
    1313             :   private:
    1314          61 :     class CPL_DLL ConstIterator
    1315             :     {
    1316             :         struct Private;
    1317             :         std::unique_ptr<Private> m_poPrivate;
    1318             : 
    1319             :       public:
    1320             :         ConstIterator(const OGRCurve *poSelf, bool bStart);
    1321             :         ConstIterator(ConstIterator &&oOther) noexcept;
    1322             :         ConstIterator &operator=(ConstIterator &&oOther);
    1323             :         ~ConstIterator();
    1324             :         const OGRPoint &operator*() const;
    1325             :         ConstIterator &operator++();
    1326             :         bool operator!=(const ConstIterator &it) const;
    1327             :     };
    1328             : 
    1329             :     friend inline ConstIterator begin(const OGRCurve *);
    1330             :     friend inline ConstIterator end(const OGRCurve *);
    1331             : 
    1332             :   public:
    1333             :     //! @cond Doxygen_Suppress
    1334             :     OGRCurve &operator=(const OGRCurve &other);
    1335             :     OGRCurve &operator=(OGRCurve &&other) = default;
    1336             :     //! @endcond
    1337             : 
    1338             :     /** C++ type of child elements. */
    1339             :     using ChildType = OGRPoint;
    1340             : 
    1341             :     /** 2D OGRwkbGeometryType constant. */
    1342             :     static constexpr OGRwkbGeometryType EnumType2D = wkbCurve;
    1343             : 
    1344             :     /**  C++ type for corresponding collection. */
    1345             :     using MultiType = OGRMultiCurve;
    1346             : 
    1347             :     /** Return begin of a point iterator.
    1348             :      *
    1349             :      * Using this iterator for standard range-based loops is safe, but
    1350             :      * due to implementation limitations, you shouldn't try to access
    1351             :      * (dereference) more than one iterator step at a time, since you will get
    1352             :      * a reference to the same OGRPoint& object.
    1353             :      */
    1354             :     ConstIterator begin() const;
    1355             :     /** Return end of a point iterator. */
    1356             :     ConstIterator end() const;
    1357             : 
    1358             :     // IGeometry
    1359             :     OGRCurve *clone() const override = 0;
    1360             : 
    1361             :     // ICurve methods
    1362             :     virtual double get_Length() const = 0;
    1363             :     virtual void StartPoint(OGRPoint *) const = 0;
    1364             :     virtual void EndPoint(OGRPoint *) const = 0;
    1365             :     virtual bool get_IsClosed() const;
    1366             :     virtual void Value(double, OGRPoint *) const = 0;
    1367             :     virtual OGRLineString *
    1368             :     CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
    1369             :                 const char *const *papszOptions = nullptr) const = 0;
    1370             :     int getDimension() const override;
    1371             : 
    1372             :     // non standard
    1373             :     virtual int getNumPoints() const = 0;
    1374             :     virtual OGRPointIterator *getPointIterator() const = 0;
    1375             :     virtual bool IsConvex() const;
    1376             :     virtual double get_Area() const = 0;
    1377             :     virtual double get_GeodesicArea(
    1378             :         const OGRSpatialReference *poSRSOverride = nullptr) const = 0;
    1379             :     virtual double get_GeodesicLength(
    1380             :         const OGRSpatialReference *poSRSOverride = nullptr) const = 0;
    1381             :     virtual bool isClockwise() const;
    1382             :     virtual void reversePoints() = 0;
    1383             : 
    1384             :     /** Down-cast to OGRSimpleCurve*.
    1385             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
    1386             :      * wkbLineString or wkbCircularString. */
    1387         536 :     inline OGRSimpleCurve *toSimpleCurve()
    1388             :     {
    1389         536 :         return cpl::down_cast<OGRSimpleCurve *>(this);
    1390             :     }
    1391             : 
    1392             :     /** Down-cast to OGRSimpleCurve*.
    1393             :      * Implies prior checking that wkbFlatten(getGeometryType()) ==
    1394             :      * wkbLineString or wkbCircularString. */
    1395             :     inline const OGRSimpleCurve *toSimpleCurve() const
    1396             :     {
    1397             :         return cpl::down_cast<const OGRSimpleCurve *>(this);
    1398             :     }
    1399             : 
    1400             :     static OGRCompoundCurve *CastToCompoundCurve(OGRCurve *puCurve);
    1401             :     static OGRLineString *CastToLineString(OGRCurve *poCurve);
    1402             :     static OGRLinearRing *CastToLinearRing(OGRCurve *poCurve);
    1403             : 
    1404             :     OGR_FORBID_DOWNCAST_TO_POINT
    1405             :     OGR_ALLOW_CAST_TO_THIS(Curve)
    1406             :     OGR_FORBID_DOWNCAST_TO_ALL_SURFACES
    1407             :     OGR_FORBID_DOWNCAST_TO_ALL_MULTI
    1408             : };
    1409             : 
    1410             : //! @cond Doxygen_Suppress
    1411             : /** @see OGRCurve::begin() const */
    1412           8 : inline OGRCurve::ConstIterator begin(const OGRCurve *poCurve)
    1413             : {
    1414           8 :     return poCurve->begin();
    1415             : }
    1416             : 
    1417             : /** @see OGRCurve::end() const */
    1418           8 : inline OGRCurve::ConstIterator end(const OGRCurve *poCurve)
    1419             : {
    1420           8 :     return poCurve->end();
    1421             : }
    1422             : 
    1423             : //! @endcond
    1424             : 
    1425             : /************************************************************************/
    1426             : /*                           OGRIteratedPoint                           */
    1427             : /************************************************************************/
    1428             : 
    1429             : /*!
    1430             :  Implementation detail of OGRSimpleCurve::Iterator.
    1431             : 
    1432             :  This class is a simple wrapper over OGRPoint, which shouldn't be directly
    1433             :  referenced by the user other than through auto&& in an iterator
    1434             :  over a OGRSimpleCurve.
    1435             : 
    1436             :  Typical usage pattern is:
    1437             :  \verbatim
    1438             :  for (auto&& p: line)
    1439             :  {
    1440             :     p.setZ(100);
    1441             :  }
    1442             :  \endverbatim
    1443             : 
    1444             :  The lifetime of this object is coupled to the one of the curve on which it
    1445             :  was returned. It is thus also illegal to modify it once the curve has been
    1446             :  deleted.
    1447             : 
    1448             :  @since GDAL 3.6
    1449             :  */
    1450         500 : class CPL_DLL OGRIteratedPoint : public OGRPoint
    1451             : {
    1452             :   private:
    1453             :     friend class OGRSimpleCurve;
    1454             : 
    1455             :     OGRSimpleCurve *m_poCurve = nullptr;
    1456             :     int m_nPos = 0;
    1457             : 
    1458         500 :     OGRIteratedPoint() = default;
    1459             : 
    1460             :     CPL_DISALLOW_COPY_ASSIGN(OGRIteratedPoint)
    1461             : 
    1462             :   public:
    1463             :     /** Set x
    1464             :      * @param xIn x
    1465             :      */
    1466             :     void setX(double xIn);
    1467             :     /** Set y
    1468             :      * @param yIn y
    1469             :      */
    1470             :     void setY(double yIn);
    1471             :     /** Set z
    1472             :      * @param zIn z
    1473             :      */
    1474             :     void setZ(double zIn);
    1475             :     /** Set m
    1476             :      * @param mIn m
    1477             :      */
    1478             :     void setM(double mIn);
    1479             : 
    1480             :     /** Destructor */
    1481             :     ~OGRIteratedPoint() override;
    1482             : };
    1483             : 
    1484             : /************************************************************************/
    1485             : /*                            OGRSimpleCurve                            */
    1486             : /************************************************************************/
    1487             : 
    1488             : /**
    1489             :  * Abstract curve base class for OGRLineString and OGRCircularString
    1490             :  *
    1491             :  * Note: this class does not exist in SQL/MM standard and exists for
    1492             :  * implementation convenience.
    1493             :  *
    1494             :  */
    1495             : 
    1496             : class CPL_DLL OGRSimpleCurve : public OGRCurve
    1497             : {
    1498             :   protected:
    1499             :     //! @cond Doxygen_Suppress
    1500             :     friend class OGRGeometry;
    1501             : 
    1502             :     int nPointCount = 0;
    1503             :     int m_nPointCapacity = 0;
    1504             :     OGRRawPoint *paoPoints = nullptr;
    1505             :     double *padfZ = nullptr;
    1506             :     double *padfM = nullptr;
    1507             : 
    1508             :     bool Make3D();
    1509             :     void Make2D();
    1510             :     void RemoveM();
    1511             :     bool AddM();
    1512             : 
    1513             :     OGRErr importFromWKTListOnly(const char **ppszInput, int bHasZ, int bHasM,
    1514             :                                  OGRRawPoint *&paoPointsIn, int &nMaxPoints,
    1515             :                                  double *&padfZIn);
    1516             :     //! @endcond
    1517             : 
    1518             :     virtual double get_LinearArea() const;
    1519             : 
    1520             :     /** Constructor */
    1521     3480700 :     OGRSimpleCurve() = default;
    1522             : 
    1523             :     OGRSimpleCurve(const OGRSimpleCurve &other);
    1524             : 
    1525             :     OGRSimpleCurve(OGRSimpleCurve &&other);
    1526             : 
    1527             :   private:
    1528             :     class CPL_DLL Iterator
    1529             :     {
    1530             :         struct Private;
    1531             :         std::unique_ptr<Private> m_poPrivate;
    1532             :         void update();
    1533             : 
    1534             :       public:
    1535             :         Iterator(OGRSimpleCurve *poSelf, int nPos);
    1536             :         Iterator(Iterator &&oOther) noexcept;  // declared but not defined.
    1537             :                                                // Needed for gcc 5.4 at least
    1538             :         ~Iterator();
    1539             :         OGRIteratedPoint &operator*();
    1540             :         Iterator &operator++();
    1541             :         bool operator!=(const Iterator &it) const;
    1542             :     };
    1543             : 
    1544             :     friend inline Iterator begin(OGRSimpleCurve *);
    1545             :     friend inline Iterator end(OGRSimpleCurve *);
    1546             : 
    1547         272 :     class CPL_DLL ConstIterator
    1548             :     {
    1549             :         struct Private;
    1550             :         std::unique_ptr<Private> m_poPrivate;
    1551             : 
    1552             :       public:
    1553             :         ConstIterator(const OGRSimpleCurve *poSelf, int nPos);
    1554             :         ConstIterator(
    1555             :             ConstIterator &&oOther) noexcept;  // declared but not defined.
    1556             :                                                // Needed for gcc 5.4 at least
    1557             :         ~ConstIterator();
    1558             :         const OGRPoint &operator*() const;
    1559             :         ConstIterator &operator++();
    1560             :         bool operator!=(const ConstIterator &it) const;
    1561             :     };
    1562             : 
    1563             :     friend inline ConstIterator begin(const OGRSimpleCurve *);
    1564             :     friend inline ConstIterator end(const OGRSimpleCurve *);
    1565             : 
    1566             :   public:
    1567             :     ~OGRSimpleCurve() override;
    1568             : 
    1569             :     OGRSimpleCurve &operator=(const OGRSimpleCurve &other);
    1570             : 
    1571             :     OGRSimpleCurve &operator=(OGRSimpleCurve &&other);
    1572             : 
    1573             :     /** C++ type of child elements. */
    1574             :     using ChildType = OGRPoint;
    1575             : 
    1576             :     /** Return begin of point iterator.
    1577             :      *
    1578             :      * Using this iterator for standard range-based loops is safe, but
    1579             :      * due to implementation limitations, you shouldn't try to access
    1580             :      * (dereference) more than one iterator step at a time, since you will get
    1581             :      * a reference to the same OGRPoint& object.
    1582             :      */
    1583             :     Iterator begin();
    1584             :     /** Return end of point iterator. */
    1585             :     Iterator end();
    1586             :     /** Return begin of point iterator.
    1587             :      *
    1588             :      * Using this iterator for standard range-based loops is safe, but
    1589             :      * due to implementation limitations, you shouldn't try to access
    1590             :      * (dereference) more than one iterator step at a time, since you will get
    1591             :      * a reference to the same OGRPoint& object.
    1592             :      */
    1593             :     ConstIterator begin() const;
    1594             :     /** Return end of point iterator. */
    1595             :     ConstIterator end() const;
    1596             : 
    1597             :     // IWks Interface.
    1598             :     size_t WkbSize() const override;
    1599             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    1600             :                                  size_t &nBytesConsumedOut) override;
    1601             :     virtual OGRErr
    1602             :     exportToWkb(unsigned char *,
    1603             :                 const OGRwkbExportOptions * = nullptr) const override;
    1604             : 
    1605             : #ifndef DOXYGEN_XML
    1606             :     using OGRGeometry::importFromWkt; /** deprecated */
    1607             : #endif
    1608             : 
    1609             :     OGRErr importFromWkt(const char **) override;
    1610             : 
    1611             : #ifndef DOXYGEN_XML
    1612             :     using OGRGeometry::exportToWkt;
    1613             : #endif
    1614             : 
    1615             :     /// Export a simple curve to WKT
    1616             :     /// \param opts  Output options.
    1617             :     /// \param err   Pointer to error code, if desired.
    1618             :     /// \return  WKT string representing this simple curve.
    1619             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    1620             :                                     OGRErr *err = nullptr) const override;
    1621             : 
    1622             :     // IGeometry interface.
    1623             :     void empty() override;
    1624             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    1625             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    1626             :     bool IsEmpty() const override;
    1627             :     OGRSimpleCurve *clone() const override = 0;
    1628             : 
    1629             :     // ICurve methods.
    1630             :     double get_Length() const override;
    1631             :     void StartPoint(OGRPoint *) const override;
    1632             :     void EndPoint(OGRPoint *) const override;
    1633             :     void Value(double, OGRPoint *) const override;
    1634             :     virtual double Project(const OGRPoint *) const;
    1635             :     virtual OGRLineString *getSubLine(double, double, int) const;
    1636             : 
    1637             :     // ILineString methods.
    1638    19163253 :     int getNumPoints() const override
    1639             :     {
    1640    19163253 :         return nPointCount;
    1641             :     }
    1642             : 
    1643             :     void getPoint(int, OGRPoint *) const;
    1644             : 
    1645    46877055 :     double getX(int i) const
    1646             :     {
    1647    46877055 :         return paoPoints[i].x;
    1648             :     }
    1649             : 
    1650    35095906 :     double getY(int i) const
    1651             :     {
    1652    35095906 :         return paoPoints[i].y;
    1653             :     }
    1654             : 
    1655             :     double getZ(int i) const;
    1656             :     double getM(int i) const;
    1657             : 
    1658             :     // ISpatialRelation
    1659             :     bool Equals(const OGRGeometry *) const override;
    1660             : 
    1661             :     // non standard.
    1662             :     bool setCoordinateDimension(int nDimension) override;
    1663             :     bool set3D(bool bIs3D) override;
    1664             :     bool setMeasured(bool bIsMeasured) override;
    1665             :     bool setNumPoints(int nNewPointCount, int bZeroizeNewContent = TRUE);
    1666             :     bool setPoint(int, OGRPoint *);
    1667             :     bool setPoint(int, double, double);
    1668             :     bool setZ(int, double);
    1669             :     bool setM(int, double);
    1670             :     bool setPoint(int, double, double, double);
    1671             :     bool setPointM(int, double, double, double);
    1672             :     bool setPoint(int, double, double, double, double);
    1673             :     bool setPoints(int, const OGRRawPoint *, const double * = nullptr);
    1674             :     bool setPointsM(int, const OGRRawPoint *, const double *);
    1675             :     bool setPoints(int, const OGRRawPoint *, const double *, const double *);
    1676             :     bool setPoints(int, const double *padfX, const double *padfY,
    1677             :                    const double *padfZIn = nullptr);
    1678             :     bool setPointsM(int, const double *padfX, const double *padfY,
    1679             :                     const double *padfMIn = nullptr);
    1680             :     bool setPoints(int, const double *padfX, const double *padfY,
    1681             :                    const double *padfZIn, const double *padfMIn);
    1682             :     bool addPoint(const OGRPoint *);
    1683             :     bool addPoint(double, double);
    1684             :     bool addPoint(double, double, double);
    1685             :     bool addPointM(double, double, double);
    1686             :     bool addPoint(double, double, double, double);
    1687             : 
    1688             :     bool removePoint(int);
    1689             : 
    1690             :     void getPoints(OGRRawPoint *, double * = nullptr) const;
    1691             :     void getPoints(void *pabyX, int nXStride, void *pabyY, int nYStride,
    1692             :                    void *pabyZ = nullptr, int nZStride = 0,
    1693             :                    void *pabyM = nullptr, int nMStride = 0) const;
    1694             : 
    1695             :     void addSubLineString(const OGRLineString *, int nStartVertex = 0,
    1696             :                           int nEndVertex = -1);
    1697             :     void reversePoints() override;
    1698             :     OGRPointIterator *getPointIterator() const override;
    1699             : 
    1700             :     // non-standard from OGRGeometry
    1701             :     OGRErr transform(OGRCoordinateTransformation *poCT) override;
    1702             :     void flattenTo2D() override;
    1703             :     bool segmentize(double dfMaxLength) override;
    1704             : 
    1705             :     void swapXY() override;
    1706             : 
    1707           3 :     OGR_ALLOW_UPCAST_TO(Curve)
    1708             :     OGR_ALLOW_CAST_TO_THIS(SimpleCurve)
    1709             : };
    1710             : 
    1711             : //! @cond Doxygen_Suppress
    1712             : /** @see OGRSimpleCurve::begin() */
    1713           5 : inline OGRSimpleCurve::Iterator begin(OGRSimpleCurve *poCurve)
    1714             : {
    1715           5 :     return poCurve->begin();
    1716             : }
    1717             : 
    1718             : /** @see OGRSimpleCurve::end() */
    1719           5 : inline OGRSimpleCurve::Iterator end(OGRSimpleCurve *poCurve)
    1720             : {
    1721           5 :     return poCurve->end();
    1722             : }
    1723             : 
    1724             : /** @see OGRSimpleCurve::begin() const */
    1725           5 : inline OGRSimpleCurve::ConstIterator begin(const OGRSimpleCurve *poCurve)
    1726             : {
    1727           5 :     return poCurve->begin();
    1728             : }
    1729             : 
    1730             : /** @see OGRSimpleCurve::end() const */
    1731           5 : inline OGRSimpleCurve::ConstIterator end(const OGRSimpleCurve *poCurve)
    1732             : {
    1733           5 :     return poCurve->end();
    1734             : }
    1735             : 
    1736             : //! @endcond
    1737             : 
    1738             : /************************************************************************/
    1739             : /*                            OGRLineString                             */
    1740             : /************************************************************************/
    1741             : 
    1742             : /**
    1743             :  * Concrete representation of a multi-vertex line.
    1744             :  *
    1745             :  * Note: for implementation convenience, we make it inherit from OGRSimpleCurve
    1746             :  * whereas SFSQL and SQL/MM only make it inherits from OGRCurve.
    1747             :  */
    1748             : 
    1749        9386 : class CPL_DLL OGRLineString : public OGRSimpleCurve
    1750             : {
    1751             :     // cppcheck-suppress unusedPrivateFunction
    1752             :     static OGRLinearRing *CasterToLinearRing(OGRCurve *poCurve);
    1753             : 
    1754             :   protected:
    1755             :     //! @cond Doxygen_Suppress
    1756             :     static OGRLineString *TransferMembersAndDestroy(OGRLineString *poSrc,
    1757             :                                                     OGRLineString *poDst);
    1758             : 
    1759             :     OGRCurveCasterToLineString GetCasterToLineString() const override;
    1760             :     OGRCurveCasterToLinearRing GetCasterToLinearRing() const override;
    1761             : 
    1762             :     double get_AreaOfCurveSegments() const override;
    1763             :     //! @endcond
    1764             : 
    1765             :     static OGRLinearRing *CastToLinearRing(OGRLineString *poLS);
    1766             : 
    1767             :   public:
    1768             :     /** Create an empty line string. */
    1769     3473469 :     OGRLineString() = default;
    1770             :     OGRLineString(const OGRLineString &other);
    1771             :     OGRLineString(OGRLineString &&other);
    1772             : 
    1773             :     OGRLineString &operator=(const OGRLineString &other);
    1774             :     OGRLineString &operator=(OGRLineString &&other);
    1775             : 
    1776             :     /** 2D OGRwkbGeometryType constant. */
    1777             :     static constexpr OGRwkbGeometryType EnumType2D = wkbLineString;
    1778             : 
    1779             :     /**  C++ type for corresponding collection. */
    1780             :     using MultiType = OGRMultiLineString;
    1781             : 
    1782             :     OGRLineString *clone() const override;
    1783             :     virtual OGRLineString *
    1784             :     CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
    1785             :                 const char *const *papszOptions = nullptr) const override;
    1786             :     virtual OGRGeometry *
    1787             :     getCurveGeometry(const char *const *papszOptions = nullptr) const override;
    1788             :     double get_Area() const override;
    1789             :     virtual double get_GeodesicArea(
    1790             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    1791             :     virtual double get_GeodesicLength(
    1792             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    1793             : 
    1794             :     // Non-standard from OGRGeometry.
    1795             :     OGRwkbGeometryType getGeometryType() const override;
    1796             :     const char *getGeometryName() const override;
    1797             :     bool isClockwise() const override;
    1798             : 
    1799             :     /** Return pointer of this in upper class */
    1800             :     inline OGRSimpleCurve *toUpperClass()
    1801             :     {
    1802             :         return this;
    1803             :     }
    1804             : 
    1805             :     /** Return pointer of this in upper class */
    1806             :     inline const OGRSimpleCurve *toUpperClass() const
    1807             :     {
    1808             :         return this;
    1809             :     }
    1810             : 
    1811          24 :     void accept(IOGRGeometryVisitor *visitor) override
    1812             :     {
    1813          24 :         visitor->visit(this);
    1814          24 :     }
    1815             : 
    1816          11 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    1817             :     {
    1818          11 :         visitor->visit(this);
    1819          11 :     }
    1820             : 
    1821           2 :     OGR_ALLOW_UPCAST_TO(SimpleCurve)
    1822             :     OGR_ALLOW_CAST_TO_THIS(LineString)
    1823             : };
    1824             : 
    1825             : /************************************************************************/
    1826             : /*                            OGRLinearRing                             */
    1827             : /************************************************************************/
    1828             : 
    1829             : /**
    1830             :  * Concrete representation of a closed ring.
    1831             :  *
    1832             :  * This class is functionally equivalent to an OGRLineString, but has a
    1833             :  * separate identity to maintain alignment with the OpenGIS simple feature
    1834             :  * data model.  It exists to serve as a component of an OGRPolygon.
    1835             :  *
    1836             :  * The OGRLinearRing has no corresponding free standing well known binary
    1837             :  * representation, so importFromWkb() and exportToWkb() will not actually
    1838             :  * work.  There is a non-standard GDAL WKT representation though.
    1839             :  *
    1840             :  * Because OGRLinearRing is not a "proper" free standing simple features
    1841             :  * object, it cannot be directly used on a feature via SetGeometry(), and
    1842             :  * cannot generally be used with GEOS for operations like Intersects().
    1843             :  * Instead the polygon should be used, or the OGRLinearRing should be
    1844             :  * converted to an OGRLineString for such operations.
    1845             :  *
    1846             :  * Note: this class exists in SFSQL 1.2, but not in ISO SQL/MM Part 3.
    1847             :  */
    1848             : 
    1849           6 : class CPL_DLL OGRLinearRing : public OGRLineString
    1850             : {
    1851             :     static OGRLineString *CasterToLineString(OGRCurve *poCurve);
    1852             : 
    1853             :     // IWks Interface - Note this isn't really a first class object
    1854             :     // for the purposes of WKB form.  These methods always fail since this
    1855             :     // object can't be serialized on its own.
    1856             :     size_t WkbSize() const override;
    1857             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    1858             :                                  size_t &nBytesConsumedOut) override;
    1859             :     OGRErr exportToWkb(unsigned char *,
    1860             :                        const OGRwkbExportOptions * = nullptr) const override;
    1861             : 
    1862             :   protected:
    1863             :     //! @cond Doxygen_Suppress
    1864             :     friend class OGRPolygon;
    1865             :     friend class OGRTriangle;
    1866             : 
    1867             :     // These are not IWks compatible ... just a convenience for OGRPolygon.
    1868             :     virtual size_t _WkbSize(int _flags) const;
    1869             :     virtual OGRErr _importFromWkb(OGRwkbByteOrder, int _flags,
    1870             :                                   const unsigned char *, size_t,
    1871             :                                   size_t &nBytesConsumedOut);
    1872             :     virtual OGRErr _exportToWkb(int _flags, unsigned char *,
    1873             :                                 const OGRwkbExportOptions *) const;
    1874             : 
    1875             :     OGRCurveCasterToLineString GetCasterToLineString() const override;
    1876             :     OGRCurveCasterToLinearRing GetCasterToLinearRing() const override;
    1877             :     //! @endcond
    1878             : 
    1879             :     static OGRLineString *CastToLineString(OGRLinearRing *poLR);
    1880             : 
    1881             :   public:
    1882             :     /** Constructor */
    1883     3081296 :     OGRLinearRing() = default;
    1884             :     OGRLinearRing(const OGRLinearRing &other);
    1885             :     /** Move constructor*/
    1886           1 :     OGRLinearRing(OGRLinearRing &&other) = default;
    1887             :     explicit OGRLinearRing(const OGRLinearRing *);
    1888             : 
    1889             :     OGRLinearRing &operator=(const OGRLinearRing &other);
    1890             :     /** Move assignment operator */
    1891             :     OGRLinearRing &operator=(OGRLinearRing &&other) = default;
    1892             : 
    1893             :     // Non standard.
    1894             :     const char *getGeometryName() const override;
    1895             :     OGRLinearRing *clone() const override;
    1896             : 
    1897             :     //! @cond Doxygen_Suppress
    1898             :     void reverseWindingOrder()
    1899             :         CPL_WARN_DEPRECATED("Use reversePoints() instead");
    1900             :     //! @endcond
    1901             : 
    1902             :     void closeRings() override;
    1903             :     bool isPointInRing(const OGRPoint *pt, int bTestEnvelope = TRUE) const;
    1904             :     bool isPointOnRingBoundary(const OGRPoint *pt,
    1905             :                                int bTestEnvelope = TRUE) const;
    1906             :     OGRErr transform(OGRCoordinateTransformation *poCT) override;
    1907             : 
    1908             :     /** Return pointer of this in upper class */
    1909          80 :     inline OGRLineString *toUpperClass()
    1910             :     {
    1911          80 :         return this;
    1912             :     }
    1913             : 
    1914             :     /** Return pointer of this in upper class */
    1915         110 :     inline const OGRLineString *toUpperClass() const
    1916             :     {
    1917         110 :         return this;
    1918             :     }
    1919             : 
    1920          80 :     void accept(IOGRGeometryVisitor *visitor) override
    1921             :     {
    1922          80 :         visitor->visit(this);
    1923          80 :     }
    1924             : 
    1925         110 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    1926             :     {
    1927         110 :         visitor->visit(this);
    1928         110 :     }
    1929             : 
    1930             :     OGR_ALLOW_UPCAST_TO(LineString)
    1931             :     OGR_ALLOW_CAST_TO_THIS(LinearRing)
    1932             : };
    1933             : 
    1934             : /************************************************************************/
    1935             : /*                          OGRCircularString                           */
    1936             : /************************************************************************/
    1937             : 
    1938             : /**
    1939             :  * Concrete representation of a circular string, that is to say a curve made
    1940             :  * of one or several arc circles.
    1941             :  *
    1942             :  * Note: for implementation convenience, we make it inherit from OGRSimpleCurve
    1943             :  * whereas SQL/MM only makes it inherits from OGRCurve.
    1944             :  *
    1945             :  * Compatibility: ISO SQL/MM Part 3.
    1946             :  *
    1947             :  */
    1948             : 
    1949         539 : class CPL_DLL OGRCircularString : public OGRSimpleCurve
    1950             : {
    1951             :   private:
    1952             :     void ExtendEnvelopeWithCircular(OGREnvelope *psEnvelope) const;
    1953             :     bool IsValidFast(std::string *posReason = nullptr) const;
    1954             :     int IsFullCircle(double &cx, double &cy, double &square_R) const;
    1955             : 
    1956             :   protected:
    1957             :     //! @cond Doxygen_Suppress
    1958             :     OGRCurveCasterToLineString GetCasterToLineString() const override;
    1959             :     OGRCurveCasterToLinearRing GetCasterToLinearRing() const override;
    1960             :     int IntersectsPoint(const OGRPoint *p) const override;
    1961             :     int ContainsPoint(const OGRPoint *p) const override;
    1962             :     double get_AreaOfCurveSegments() const override;
    1963             :     //! @endcond
    1964             : 
    1965             :   public:
    1966             :     /** Create an empty circular string. */
    1967        7231 :     OGRCircularString() = default;
    1968             : 
    1969             :     OGRCircularString(const OGRCircularString &other);
    1970             :     /** Move constructor */
    1971           1 :     OGRCircularString(OGRCircularString &&other) = default;
    1972             : 
    1973             :     OGRCircularString &operator=(const OGRCircularString &other);
    1974             :     /** Move assignment operator */
    1975             :     OGRCircularString &operator=(OGRCircularString &&other) = default;
    1976             : 
    1977             :     /** 2D OGRwkbGeometryType constant. */
    1978             :     static constexpr OGRwkbGeometryType EnumType2D = wkbCircularString;
    1979             : 
    1980             :     /**  C++ type for corresponding collection. */
    1981             :     using MultiType = OGRMultiCurve;
    1982             : 
    1983             :     // IWks Interface.
    1984             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    1985             :                                  size_t &nBytesConsumedOut) override;
    1986             :     OGRErr exportToWkb(unsigned char *,
    1987             :                        const OGRwkbExportOptions * = nullptr) const override;
    1988             : 
    1989             : #ifndef DOXYGEN_XML
    1990             :     using OGRGeometry::importFromWkt; /** deprecated */
    1991             : #endif
    1992             : 
    1993             :     OGRErr importFromWkt(const char **) override;
    1994             : 
    1995             : #ifndef DOXYGEN_XML
    1996             :     using OGRGeometry::exportToWkt;
    1997             : #endif
    1998             : 
    1999             :     /// Export a circular string to WKT
    2000             :     /// \param opts  Output options.
    2001             :     /// \param err   Pointer to error code, if desired.
    2002             :     /// \return  WKT string representing this circular string.
    2003             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    2004             :                                     OGRErr *err = nullptr) const override;
    2005             : 
    2006             :     // IGeometry interface.
    2007             :     bool IsValid(std::string *posReason = nullptr) const override;
    2008             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    2009             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    2010             :     OGRCircularString *clone() const override;
    2011             : 
    2012             :     // ICurve methods.
    2013             :     double get_Length() const override;
    2014             :     virtual OGRLineString *
    2015             :     CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
    2016             :                 const char *const *papszOptions = nullptr) const override;
    2017             :     void Value(double, OGRPoint *) const override;
    2018             :     double get_Area() const override;
    2019             :     virtual double get_GeodesicArea(
    2020             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    2021             :     virtual double get_GeodesicLength(
    2022             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    2023             : 
    2024             :     // Non-standard from OGRGeometry.
    2025             :     OGRwkbGeometryType getGeometryType() const override;
    2026             :     const char *getGeometryName() const override;
    2027             :     bool segmentize(double dfMaxLength) override;
    2028             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    2029             :     virtual OGRGeometry *
    2030             :     getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
    2031             :                       const char *const *papszOptions = nullptr) const override;
    2032             : 
    2033             :     /** Return pointer of this in upper class */
    2034             :     inline OGRSimpleCurve *toUpperClass()
    2035             :     {
    2036             :         return this;
    2037             :     }
    2038             : 
    2039             :     /** Return pointer of this in upper class */
    2040             :     inline const OGRSimpleCurve *toUpperClass() const
    2041             :     {
    2042             :         return this;
    2043             :     }
    2044             : 
    2045           1 :     void accept(IOGRGeometryVisitor *visitor) override
    2046             :     {
    2047           1 :         visitor->visit(this);
    2048           1 :     }
    2049             : 
    2050           6 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    2051             :     {
    2052           6 :         visitor->visit(this);
    2053           6 :     }
    2054             : 
    2055           1 :     OGR_ALLOW_UPCAST_TO(SimpleCurve)
    2056             :     OGR_ALLOW_CAST_TO_THIS(CircularString)
    2057             : };
    2058             : 
    2059             : /************************************************************************/
    2060             : /*                          OGRCurveCollection                          */
    2061             : /************************************************************************/
    2062             : 
    2063             : /**
    2064             :  * Utility class to store a collection of curves. Used as a member of
    2065             :  * OGRCompoundCurve and OGRCurvePolygon.
    2066             :  *
    2067             :  * This class is only exported because of linking issues. It should never
    2068             :  * be directly used.
    2069             :  *
    2070             :  */
    2071             : 
    2072             : //! @cond Doxygen_Suppress
    2073             : class CPL_DLL OGRCurveCollection
    2074             : {
    2075             :   protected:
    2076             :     friend class OGRCompoundCurve;
    2077             :     friend class OGRCurvePolygon;
    2078             :     friend class OGRPolygon;
    2079             :     friend class OGRTriangle;
    2080             : 
    2081             :     int nCurveCount = 0;
    2082             :     OGRCurve **papoCurves = nullptr;
    2083             : 
    2084             :   public:
    2085     1568250 :     OGRCurveCollection() = default;
    2086             :     OGRCurveCollection(const OGRCurveCollection &other);
    2087             :     OGRCurveCollection(OGRCurveCollection &&other);
    2088             :     ~OGRCurveCollection();
    2089             : 
    2090             :     OGRCurveCollection &operator=(const OGRCurveCollection &other);
    2091             :     OGRCurveCollection &operator=(OGRCurveCollection &&other);
    2092             : 
    2093             :     /** C++ type of child elements. */
    2094             :     using ChildType = OGRCurve;
    2095             : 
    2096             :     /** Return begin of curve iterator.
    2097             :      */
    2098     6358023 :     OGRCurve **begin()
    2099             :     {
    2100     6358023 :         return papoCurves;
    2101             :     }
    2102             : 
    2103             :     /** Return end of curve iterator. */
    2104     6358023 :     OGRCurve **end()
    2105             :     {
    2106     6358023 :         return papoCurves + nCurveCount;
    2107             :     }
    2108             : 
    2109             :     /** Return begin of curve iterator.
    2110             :      */
    2111     1577368 :     const OGRCurve *const *begin() const
    2112             :     {
    2113     1577368 :         return papoCurves;
    2114             :     }
    2115             : 
    2116             :     /** Return end of curve iterator. */
    2117     1577368 :     const OGRCurve *const *end() const
    2118             :     {
    2119     1577368 :         return papoCurves + nCurveCount;
    2120             :     }
    2121             : 
    2122             :     void empty(OGRGeometry *poGeom);
    2123             :     bool IsEmpty() const;
    2124             :     void getEnvelope(OGREnvelope *psEnvelope) const;
    2125             :     void getEnvelope(OGREnvelope3D *psEnvelope) const;
    2126             : 
    2127             :     OGRErr addCurveDirectly(OGRGeometry *poGeom, OGRCurve *poCurve,
    2128             :                             int bNeedRealloc);
    2129             :     size_t WkbSize() const;
    2130             :     OGRErr importPreambleFromWkb(OGRGeometry *poGeom,
    2131             :                                  const unsigned char *pabyData, size_t &nSize,
    2132             :                                  size_t &nDataOffset,
    2133             :                                  OGRwkbByteOrder &eByteOrder,
    2134             :                                  size_t nMinSubGeomSize,
    2135             :                                  OGRwkbVariant eWkbVariant);
    2136             :     OGRErr
    2137             :     importBodyFromWkb(OGRGeometry *poGeom, const unsigned char *pabyData,
    2138             :                       size_t nSize, bool bAcceptCompoundCurve,
    2139             :                       OGRErr (*pfnAddCurveDirectlyFromWkb)(OGRGeometry *poGeom,
    2140             :                                                            OGRCurve *poCurve),
    2141             :                       OGRwkbVariant eWkbVariant, size_t &nBytesConsumedOut);
    2142             :     std::string exportToWkt(const OGRGeometry *geom, const OGRWktOptions &opts,
    2143             :                             OGRErr *err) const;
    2144             :     OGRErr exportToWkb(const OGRGeometry *poGeom, unsigned char *,
    2145             :                        const OGRwkbExportOptions * = nullptr) const;
    2146             :     bool Equals(const OGRCurveCollection *poOCC) const;
    2147             :     bool setCoordinateDimension(OGRGeometry *poGeom, int nNewDimension);
    2148             :     bool set3D(OGRGeometry *poGeom, bool bIs3D);
    2149             :     bool setMeasured(OGRGeometry *poGeom, bool bIsMeasured);
    2150             :     void assignSpatialReference(OGRGeometry *poGeom,
    2151             :                                 const OGRSpatialReference *poSR);
    2152             :     int getNumCurves() const;
    2153             :     OGRCurve *getCurve(int);
    2154             :     const OGRCurve *getCurve(int) const;
    2155             :     OGRCurve *stealCurve(int);
    2156             : 
    2157             :     OGRErr removeCurve(int iIndex, bool bDelete = true);
    2158             : 
    2159             :     bool hasEmptyParts() const;
    2160             :     void removeEmptyParts();
    2161             : 
    2162             :     void reversePoints();
    2163             : 
    2164             :     OGRErr transform(OGRGeometry *poGeom, OGRCoordinateTransformation *poCT);
    2165             :     void flattenTo2D(OGRGeometry *poGeom);
    2166             :     bool segmentize(double dfMaxLength);
    2167             :     void swapXY();
    2168             :     bool hasCurveGeometry(int bLookForNonLinear) const;
    2169             : };
    2170             : 
    2171             : //! @endcond
    2172             : 
    2173             : /************************************************************************/
    2174             : /*                           OGRCompoundCurve                           */
    2175             : /************************************************************************/
    2176             : 
    2177             : /**
    2178             :  * Concrete representation of a compound curve, made of curves: OGRLineString
    2179             :  * and OGRCircularString. Each curve is connected by its first point to
    2180             :  * the last point of the previous curve.
    2181             :  *
    2182             :  * Compatibility: ISO SQL/MM Part 3.
    2183             :  *
    2184             :  */
    2185             : 
    2186         326 : class CPL_DLL OGRCompoundCurve : public OGRCurve
    2187             : {
    2188             :   private:
    2189             :     OGRCurveCollection oCC{};
    2190             : 
    2191             :     OGRErr addCurveDirectlyInternal(OGRCurve *poCurve, double dfToleranceEps,
    2192             :                                     int bNeedRealloc);
    2193             :     static OGRErr addCurveDirectlyFromWkt(OGRGeometry *poSelf,
    2194             :                                           OGRCurve *poCurve);
    2195             :     static OGRErr addCurveDirectlyFromWkb(OGRGeometry *poSelf,
    2196             :                                           OGRCurve *poCurve);
    2197             :     OGRLineString *CurveToLineInternal(double dfMaxAngleStepSizeDegrees,
    2198             :                                        const char *const *papszOptions,
    2199             :                                        int bIsLinearRing) const;
    2200             :     // cppcheck-suppress unusedPrivateFunction
    2201             :     static OGRLineString *CasterToLineString(OGRCurve *poCurve);
    2202             :     // cppcheck-suppress unusedPrivateFunction
    2203             :     static OGRLinearRing *CasterToLinearRing(OGRCurve *poCurve);
    2204             : 
    2205             :   protected:
    2206             :     //! @cond Doxygen_Suppress
    2207             :     static OGRLineString *CastToLineString(OGRCompoundCurve *poCC);
    2208             :     static OGRLinearRing *CastToLinearRing(OGRCompoundCurve *poCC);
    2209             : 
    2210             :     OGRCurveCasterToLineString GetCasterToLineString() const override;
    2211             :     OGRCurveCasterToLinearRing GetCasterToLinearRing() const override;
    2212             :     //! @endcond
    2213             : 
    2214             :   public:
    2215             :     /** Create an empty compound curve. */
    2216        2712 :     OGRCompoundCurve() = default;
    2217             : 
    2218             :     OGRCompoundCurve(const OGRCompoundCurve &other);
    2219             :     /** Move constructor */
    2220           1 :     OGRCompoundCurve(OGRCompoundCurve &&other) = default;
    2221             : 
    2222             :     OGRCompoundCurve &operator=(const OGRCompoundCurve &other);
    2223             :     /** Move assignment operator */
    2224             :     OGRCompoundCurve &operator=(OGRCompoundCurve &&other) = default;
    2225             : 
    2226             :     /** C++ type of child elements. */
    2227             :     using ChildType = OGRCurve;
    2228             : 
    2229             :     /** 2D OGRwkbGeometryType constant. */
    2230             :     static constexpr OGRwkbGeometryType EnumType2D = wkbCompoundCurve;
    2231             : 
    2232             :     /**  C++ type for corresponding collection. */
    2233             :     using MultiType = OGRMultiCurve;
    2234             : 
    2235             :     /** Return begin of curve iterator.
    2236             :      */
    2237          15 :     ChildType **begin()
    2238             :     {
    2239          15 :         return oCC.begin();
    2240             :     }
    2241             : 
    2242             :     /** Return end of curve iterator. */
    2243          15 :     ChildType **end()
    2244             :     {
    2245          15 :         return oCC.end();
    2246             :     }
    2247             : 
    2248             :     /** Return begin of curve iterator.
    2249             :      */
    2250          34 :     const ChildType *const *begin() const
    2251             :     {
    2252          34 :         return oCC.begin();
    2253             :     }
    2254             : 
    2255             :     /** Return end of curve iterator. */
    2256          34 :     const ChildType *const *end() const
    2257             :     {
    2258          34 :         return oCC.end();
    2259             :     }
    2260             : 
    2261             :     // IWks Interface
    2262             :     size_t WkbSize() const override;
    2263             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    2264             :                                  size_t &nBytesConsumedOut) override;
    2265             :     OGRErr exportToWkb(unsigned char *,
    2266             :                        const OGRwkbExportOptions * = nullptr) const override;
    2267             : 
    2268             : #ifndef DOXYGEN_XML
    2269             :     using OGRGeometry::importFromWkt; /** deprecated */
    2270             : #endif
    2271             : 
    2272             :     OGRErr importFromWkt(const char **) override;
    2273             : 
    2274             : #ifndef DOXYGEN_XML
    2275             :     using OGRGeometry::exportToWkt;
    2276             : #endif
    2277             : 
    2278             :     /// Export a compound curve to WKT
    2279             :     /// \param opts  Output options.
    2280             :     /// \param err   Pointer to error code, if desired.
    2281             :     /// \return      WKT representation of the compound curve.
    2282             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    2283             :                                     OGRErr *err = nullptr) const override;
    2284             : 
    2285             :     // IGeometry interface.
    2286             :     OGRCompoundCurve *clone() const override;
    2287             :     void empty() override;
    2288             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    2289             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    2290             :     bool IsEmpty() const override;
    2291             : 
    2292             :     // ICurve methods.
    2293             :     double get_Length() const override;
    2294             :     void StartPoint(OGRPoint *) const override;
    2295             :     void EndPoint(OGRPoint *) const override;
    2296             :     void Value(double, OGRPoint *) const override;
    2297             :     virtual OGRLineString *
    2298             :     CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
    2299             :                 const char *const *papszOptions = nullptr) const override;
    2300             : 
    2301             :     int getNumPoints() const override;
    2302             :     double get_AreaOfCurveSegments() const override;
    2303             :     double get_Area() const override;
    2304             :     virtual double get_GeodesicArea(
    2305             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    2306             :     virtual double get_GeodesicLength(
    2307             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    2308             : 
    2309             :     // ISpatialRelation.
    2310             :     bool Equals(const OGRGeometry *) const override;
    2311             : 
    2312             :     // ICompoundCurve method.
    2313             :     int getNumCurves() const;
    2314             :     OGRCurve *getCurve(int);
    2315             :     const OGRCurve *getCurve(int) const;
    2316             : 
    2317             :     // Non-standard.
    2318             :     bool setCoordinateDimension(int nDimension) override;
    2319             :     bool set3D(bool bIs3D) override;
    2320             :     bool setMeasured(bool bIsMeasured) override;
    2321             : 
    2322             :     virtual void
    2323             :     assignSpatialReference(const OGRSpatialReference *poSR) override;
    2324             : 
    2325             :     /** Default relative tolerance to assume that the end of the previous curve
    2326             :      * is equal to the start of the next one.
    2327             :      */
    2328             :     static constexpr double DEFAULT_TOLERANCE_EPSILON = 1e-14;
    2329             : 
    2330             :     OGRErr addCurve(const OGRCurve *,
    2331             :                     double dfToleranceEps = DEFAULT_TOLERANCE_EPSILON);
    2332             :     OGRErr addCurveDirectly(OGRCurve *,
    2333             :                             double dfToleranceEps = DEFAULT_TOLERANCE_EPSILON);
    2334             :     OGRErr addCurve(std::unique_ptr<OGRCurve>,
    2335             :                     double dfToleranceEps = DEFAULT_TOLERANCE_EPSILON);
    2336             :     OGRCurve *stealCurve(int);
    2337             :     OGRPointIterator *getPointIterator() const override;
    2338             :     void reversePoints() override;
    2339             : 
    2340             :     // Non-standard from OGRGeometry.
    2341             :     OGRwkbGeometryType getGeometryType() const override;
    2342             :     const char *getGeometryName() const override;
    2343             :     OGRErr transform(OGRCoordinateTransformation *poCT) override;
    2344             :     void flattenTo2D() override;
    2345             :     bool segmentize(double dfMaxLength) override;
    2346             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    2347             :     virtual OGRGeometry *
    2348             :     getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
    2349             :                       const char *const *papszOptions = nullptr) const override;
    2350             : 
    2351           1 :     void accept(IOGRGeometryVisitor *visitor) override
    2352             :     {
    2353           1 :         visitor->visit(this);
    2354           1 :     }
    2355             : 
    2356           3 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    2357             :     {
    2358           3 :         visitor->visit(this);
    2359           3 :     }
    2360             : 
    2361             :     void swapXY() override;
    2362             : 
    2363             :     bool hasEmptyParts() const override;
    2364             :     void removeEmptyParts() override;
    2365             : 
    2366           1 :     OGR_ALLOW_UPCAST_TO(Curve)
    2367             :     OGR_ALLOW_CAST_TO_THIS(CompoundCurve)
    2368             : };
    2369             : 
    2370             : //! @cond Doxygen_Suppress
    2371             : /** @see OGRCompoundCurve::begin() const */
    2372             : inline const OGRCompoundCurve::ChildType *const *
    2373           3 : begin(const OGRCompoundCurve *poCurve)
    2374             : {
    2375           3 :     return poCurve->begin();
    2376             : }
    2377             : 
    2378             : /** @see OGRCompoundCurve::end() const */
    2379             : inline const OGRCompoundCurve::ChildType *const *
    2380           3 : end(const OGRCompoundCurve *poCurve)
    2381             : {
    2382           3 :     return poCurve->end();
    2383             : }
    2384             : 
    2385             : /** @see OGRCompoundCurve::begin() */
    2386          14 : inline OGRCompoundCurve::ChildType **begin(OGRCompoundCurve *poCurve)
    2387             : {
    2388          14 :     return poCurve->begin();
    2389             : }
    2390             : 
    2391             : /** @see OGRCompoundCurve::end() */
    2392          14 : inline OGRCompoundCurve::ChildType **end(OGRCompoundCurve *poCurve)
    2393             : {
    2394          14 :     return poCurve->end();
    2395             : }
    2396             : 
    2397             : //! @endcond
    2398             : 
    2399             : /************************************************************************/
    2400             : /*                              OGRSurface                              */
    2401             : /************************************************************************/
    2402             : 
    2403             : /**
    2404             :  * Abstract base class for 2 dimensional objects like polygons or curve
    2405             :  * polygons.
    2406             :  */
    2407             : 
    2408             : class CPL_DLL OGRSurface : public OGRGeometry
    2409             : {
    2410             :   protected:
    2411             :     //! @cond Doxygen_Suppress
    2412             :     virtual OGRSurfaceCasterToPolygon GetCasterToPolygon() const = 0;
    2413             :     virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon() const = 0;
    2414             :     //! @endcond
    2415             : 
    2416             :   public:
    2417             :     /** 2D OGRwkbGeometryType constant. */
    2418             :     static constexpr OGRwkbGeometryType EnumType2D = wkbSurface;
    2419             : 
    2420             :     /**  C++ type for corresponding collection. */
    2421             :     using MultiType = OGRMultiSurface;
    2422             : 
    2423             :     virtual double get_Area() const = 0;
    2424             :     virtual double get_GeodesicArea(
    2425             :         const OGRSpatialReference *poSRSOverride = nullptr) const = 0;
    2426             :     virtual double get_Length() const = 0;
    2427             :     virtual double get_GeodesicLength(
    2428             :         const OGRSpatialReference *poSRSOverride = nullptr) const = 0;
    2429             : 
    2430             :     virtual OGRErr PointOnSurface(OGRPoint *poPoint) const;
    2431             : 
    2432             :     OGRSurface *clone() const override = 0;
    2433             : 
    2434             :     //! @cond Doxygen_Suppress
    2435             :     static OGRPolygon *CastToPolygon(OGRSurface *poSurface);
    2436             :     static OGRCurvePolygon *CastToCurvePolygon(OGRSurface *poSurface);
    2437             :     //! @endcond
    2438             : 
    2439             :     OGR_FORBID_DOWNCAST_TO_POINT
    2440             :     OGR_FORBID_DOWNCAST_TO_ALL_CURVES
    2441             :     OGR_ALLOW_CAST_TO_THIS(Surface)
    2442             :     OGR_FORBID_DOWNCAST_TO_ALL_MULTI
    2443             : };
    2444             : 
    2445             : /************************************************************************/
    2446             : /*                           OGRCurvePolygon                            */
    2447             : /************************************************************************/
    2448             : 
    2449             : /**
    2450             :  * Concrete class representing curve polygons.
    2451             :  *
    2452             :  * Note that curve polygons consist of one outer (curve) ring, and zero or
    2453             :  * more inner rings.  A curve polygon cannot represent disconnected
    2454             :  * regions (such as multiple islands in a political body).  The
    2455             :  * OGRMultiSurface must be used for this.
    2456             :  *
    2457             :  * Compatibility: ISO SQL/MM Part 3.
    2458             :  *
    2459             :  */
    2460             : 
    2461     1497716 : class CPL_DLL OGRCurvePolygon : public OGRSurface
    2462             : {
    2463             :     static OGRPolygon *CasterToPolygon(OGRSurface *poSurface);
    2464             : 
    2465             :   private:
    2466             :     bool IntersectsPoint(const OGRPoint *p) const;
    2467             :     bool ContainsPoint(const OGRPoint *p) const;
    2468             : 
    2469             :     virtual bool isRingCorrectType(const OGRCurve *poRing) const;
    2470             : 
    2471             :     virtual bool checkRing(const OGRCurve *poNewRing) const;
    2472             :     OGRErr addRingDirectlyInternal(OGRCurve *poCurve, int bNeedRealloc);
    2473             :     static OGRErr addCurveDirectlyFromWkt(OGRGeometry *poSelf,
    2474             :                                           OGRCurve *poCurve);
    2475             :     static OGRErr addCurveDirectlyFromWkb(OGRGeometry *poSelf,
    2476             :                                           OGRCurve *poCurve);
    2477             : 
    2478             :   protected:
    2479             :     //! @cond Doxygen_Suppress
    2480             :     friend class OGRPolygon;
    2481             :     friend class OGRTriangle;
    2482             :     OGRCurveCollection oCC{};
    2483             : 
    2484             :     OGRSurfaceCasterToPolygon GetCasterToPolygon() const override;
    2485             :     virtual OGRSurfaceCasterToCurvePolygon
    2486             :     GetCasterToCurvePolygon() const override;
    2487             : 
    2488             :     //! @endcond
    2489             : 
    2490             :     static OGRPolygon *CastToPolygon(OGRCurvePolygon *poCP);
    2491             : 
    2492             :   public:
    2493             :     /** Create an empty curve polygon. */
    2494     1565538 :     OGRCurvePolygon() = default;
    2495             : 
    2496             :     OGRCurvePolygon(const OGRCurvePolygon &);
    2497             :     /** Move constructor */
    2498           3 :     OGRCurvePolygon(OGRCurvePolygon &&) = default;
    2499             : 
    2500             :     OGRCurvePolygon &operator=(const OGRCurvePolygon &other);
    2501             :     /** Move assignment operator */
    2502             :     OGRCurvePolygon &operator=(OGRCurvePolygon &&other) = default;
    2503             : 
    2504             :     /** C++ type of child elements. */
    2505             :     using ChildType = OGRCurve;
    2506             : 
    2507             :     /** 2D OGRwkbGeometryType constant. */
    2508             :     static constexpr OGRwkbGeometryType EnumType2D = wkbCurvePolygon;
    2509             : 
    2510             :     /**  C++ type for corresponding collection. */
    2511             :     using MultiType = OGRMultiSurface;
    2512             : 
    2513             :     /** Return begin of curve iterator.
    2514             :      */
    2515         106 :     ChildType **begin()
    2516             :     {
    2517         106 :         return oCC.begin();
    2518             :     }
    2519             : 
    2520             :     /** Return end of curve iterator. */
    2521         106 :     ChildType **end()
    2522             :     {
    2523         106 :         return oCC.end();
    2524             :     }
    2525             : 
    2526             :     /** Return begin of curve iterator.
    2527             :      */
    2528         206 :     const ChildType *const *begin() const
    2529             :     {
    2530         206 :         return oCC.begin();
    2531             :     }
    2532             : 
    2533             :     /** Return end of curve iterator. */
    2534         206 :     const ChildType *const *end() const
    2535             :     {
    2536         206 :         return oCC.end();
    2537             :     }
    2538             : 
    2539             :     // Non standard (OGRGeometry).
    2540             :     const char *getGeometryName() const override;
    2541             :     OGRwkbGeometryType getGeometryType() const override;
    2542             :     OGRCurvePolygon *clone() const override;
    2543             :     void empty() override;
    2544             :     OGRErr transform(OGRCoordinateTransformation *poCT) override;
    2545             :     void flattenTo2D() override;
    2546             :     bool IsEmpty() const override;
    2547             :     bool segmentize(double dfMaxLength) override;
    2548             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    2549             :     virtual OGRGeometry *
    2550             :     getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
    2551             :                       const char *const *papszOptions = nullptr) const override;
    2552             :     virtual double get_GeodesicArea(
    2553             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    2554             :     virtual double get_GeodesicLength(
    2555             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    2556             : 
    2557             :     // ISurface Interface
    2558             :     double get_Area() const override;
    2559             : 
    2560             :     double get_Length() const override;
    2561             : 
    2562             :     // IWks Interface
    2563             :     size_t WkbSize() const override;
    2564             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    2565             :                                  size_t &nBytesConsumedOut) override;
    2566             :     OGRErr exportToWkb(unsigned char *,
    2567             :                        const OGRwkbExportOptions * = nullptr) const override;
    2568             : 
    2569             : #ifndef DOXYGEN_XML
    2570             :     using OGRGeometry::importFromWkt; /** deprecated */
    2571             : #endif
    2572             : 
    2573             :     OGRErr importFromWkt(const char **) override;
    2574             : 
    2575             : #ifndef DOXYGEN_XML
    2576             :     using OGRGeometry::exportToWkt;
    2577             : #endif
    2578             : 
    2579             :     /// Export a curve polygon to WKT
    2580             :     /// \param opts  Output options.
    2581             :     /// \param err   Pointer to error code, if desired.
    2582             :     /// \return      WKT representation of the curve polygon.
    2583             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    2584             :                                     OGRErr *err = nullptr) const override;
    2585             : 
    2586             :     // IGeometry
    2587             :     int getDimension() const override;
    2588             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    2589             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    2590             : 
    2591             :     // ICurvePolygon
    2592             :     virtual OGRPolygon *
    2593             :     CurvePolyToPoly(double dfMaxAngleStepSizeDegrees = 0,
    2594             :                     const char *const *papszOptions = nullptr) const;
    2595             : 
    2596             :     // ISpatialRelation
    2597             :     bool Equals(const OGRGeometry *) const override;
    2598             :     bool Intersects(const OGRGeometry *) const override;
    2599             :     bool Contains(const OGRGeometry *) const override;
    2600             : 
    2601             :     // Non standard
    2602             :     bool setCoordinateDimension(int nDimension) override;
    2603             :     bool set3D(bool bIs3D) override;
    2604             :     bool setMeasured(bool bIsMeasured) override;
    2605             : 
    2606             :     virtual void
    2607             :     assignSpatialReference(const OGRSpatialReference *poSR) override;
    2608             : 
    2609             :     virtual OGRErr addRing(const OGRCurve *);
    2610             :     virtual OGRErr addRingDirectly(OGRCurve *);
    2611             :     OGRErr addRing(std::unique_ptr<OGRCurve>);
    2612             : 
    2613             :     OGRCurve *getExteriorRingCurve();
    2614             :     const OGRCurve *getExteriorRingCurve() const;
    2615             :     int getNumInteriorRings() const;
    2616             :     OGRCurve *getInteriorRingCurve(int);
    2617             :     const OGRCurve *getInteriorRingCurve(int) const;
    2618             : 
    2619             :     OGRCurve *stealExteriorRingCurve();
    2620             : 
    2621             :     OGRErr removeRing(int iIndex, bool bDelete = true);
    2622             : 
    2623           1 :     void accept(IOGRGeometryVisitor *visitor) override
    2624             :     {
    2625           1 :         visitor->visit(this);
    2626           1 :     }
    2627             : 
    2628           3 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    2629             :     {
    2630           3 :         visitor->visit(this);
    2631           3 :     }
    2632             : 
    2633             :     void swapXY() override;
    2634             : 
    2635             :     bool hasEmptyParts() const override;
    2636             :     void removeEmptyParts() override;
    2637             : 
    2638           8 :     OGR_ALLOW_UPCAST_TO(Surface)
    2639             :     OGR_ALLOW_CAST_TO_THIS(CurvePolygon)
    2640             : };
    2641             : 
    2642             : //! @cond Doxygen_Suppress
    2643             : /** @see OGRCurvePolygon::begin() const */
    2644             : inline const OGRCurvePolygon::ChildType *const *
    2645          40 : begin(const OGRCurvePolygon *poGeom)
    2646             : {
    2647          40 :     return poGeom->begin();
    2648             : }
    2649             : 
    2650             : /** @see OGRCurvePolygon::end() const */
    2651             : inline const OGRCurvePolygon::ChildType *const *
    2652          40 : end(const OGRCurvePolygon *poGeom)
    2653             : {
    2654          40 :     return poGeom->end();
    2655             : }
    2656             : 
    2657             : /** @see OGRCurvePolygon::begin() */
    2658           2 : inline OGRCurvePolygon::ChildType **begin(OGRCurvePolygon *poGeom)
    2659             : {
    2660           2 :     return poGeom->begin();
    2661             : }
    2662             : 
    2663             : /** @see OGRCurvePolygon::end() */
    2664           2 : inline OGRCurvePolygon::ChildType **end(OGRCurvePolygon *poGeom)
    2665             : {
    2666           2 :     return poGeom->end();
    2667             : }
    2668             : 
    2669             : //! @endcond
    2670             : 
    2671             : /************************************************************************/
    2672             : /*                              OGRPolygon                              */
    2673             : /************************************************************************/
    2674             : 
    2675             : /**
    2676             :  * Concrete class representing polygons.
    2677             :  *
    2678             :  * Note that the OpenGIS simple features polygons consist of one outer ring
    2679             :  * (linearring), and zero or more inner rings.  A polygon cannot represent
    2680             :  * disconnected regions (such as multiple islands in a political body).  The
    2681             :  * OGRMultiPolygon must be used for this.
    2682             :  */
    2683             : 
    2684     1497414 : class CPL_DLL OGRPolygon : public OGRCurvePolygon
    2685             : {
    2686             :     static OGRCurvePolygon *CasterToCurvePolygon(OGRSurface *poSurface);
    2687             : 
    2688             :   protected:
    2689             :     //! @cond Doxygen_Suppress
    2690             :     friend class OGRMultiSurface;
    2691             :     friend class OGRPolyhedralSurface;
    2692             :     friend class OGRTriangulatedSurface;
    2693             : 
    2694             :     bool isRingCorrectType(const OGRCurve *poRing) const override;
    2695             : 
    2696             :     bool checkRing(const OGRCurve *poNewRing) const override;
    2697             :     virtual OGRErr importFromWKTListOnly(const char **ppszInput, int bHasZ,
    2698             :                                          int bHasM, OGRRawPoint *&paoPoints,
    2699             :                                          int &nMaxPoints, double *&padfZ);
    2700             : 
    2701             :     static OGRCurvePolygon *CastToCurvePolygon(OGRPolygon *poPoly);
    2702             : 
    2703             :     OGRSurfaceCasterToPolygon GetCasterToPolygon() const override;
    2704             :     virtual OGRSurfaceCasterToCurvePolygon
    2705             :     GetCasterToCurvePolygon() const override;
    2706             :     //! @endcond
    2707             : 
    2708             :   public:
    2709             :     /** Create an empty polygon. */
    2710     1564790 :     OGRPolygon() = default;
    2711             : 
    2712             :     OGRPolygon(double x1, double y1, double x2, double y2);
    2713             : 
    2714             :     explicit OGRPolygon(const OGREnvelope &envelope);
    2715             : 
    2716             :     OGRPolygon(const OGRPolygon &other);
    2717             :     /** Move constructor */
    2718           2 :     OGRPolygon(OGRPolygon &&other) = default;
    2719             : 
    2720             :     OGRPolygon &operator=(const OGRPolygon &other);
    2721             :     /** Move assignment operator */
    2722             :     OGRPolygon &operator=(OGRPolygon &&other) = default;
    2723             : 
    2724             :     /** C++ type of child elements. */
    2725             :     using ChildType = OGRLinearRing;
    2726             : 
    2727             :     /** 2D OGRwkbGeometryType constant. */
    2728             :     static constexpr OGRwkbGeometryType EnumType2D = wkbPolygon;
    2729             : 
    2730             :     /**  C++ type for corresponding collection. */
    2731             :     using MultiType = OGRMultiPolygon;
    2732             : 
    2733             :     /** Return begin of iterator.
    2734             :      */
    2735        1451 :     ChildType **begin()
    2736             :     {
    2737        1451 :         return reinterpret_cast<ChildType **>(oCC.begin());
    2738             :     }
    2739             : 
    2740             :     /** Return end of iterator */
    2741        1451 :     ChildType **end()
    2742             :     {
    2743        1451 :         return reinterpret_cast<ChildType **>(oCC.end());
    2744             :     }
    2745             : 
    2746             :     /** Return begin of iterator.
    2747             :      */
    2748      987649 :     const ChildType *const *begin() const
    2749             :     {
    2750      987649 :         return reinterpret_cast<const ChildType *const *>(oCC.begin());
    2751             :     }
    2752             : 
    2753             :     /** Return end of iterator */
    2754      987649 :     const ChildType *const *end() const
    2755             :     {
    2756      987649 :         return reinterpret_cast<const ChildType *const *>(oCC.end());
    2757             :     }
    2758             : 
    2759             :     // Non-standard (OGRGeometry).
    2760             :     const char *getGeometryName() const override;
    2761             :     OGRwkbGeometryType getGeometryType() const override;
    2762             :     OGRPolygon *clone() const override;
    2763             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    2764             :     virtual OGRGeometry *
    2765             :     getCurveGeometry(const char *const *papszOptions = nullptr) const override;
    2766             :     virtual OGRGeometry *
    2767             :     getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
    2768             :                       const char *const *papszOptions = nullptr) const override;
    2769             : 
    2770             :     // IWks Interface.
    2771             :     size_t WkbSize() const override;
    2772             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    2773             :                                  size_t &nBytesConsumedOut) override;
    2774             :     OGRErr exportToWkb(unsigned char *,
    2775             :                        const OGRwkbExportOptions * = nullptr) const override;
    2776             : 
    2777             : #ifndef DOXYGEN_XML
    2778             :     using OGRGeometry::importFromWkt; /** deprecated */
    2779             : #endif
    2780             : 
    2781             :     OGRErr importFromWkt(const char **) override;
    2782             : 
    2783             : #ifndef DOXYGEN_XML
    2784             :     using OGRGeometry::exportToWkt;
    2785             : #endif
    2786             : 
    2787             :     /// Export a polygon to WKT
    2788             :     /// \param opts  Output options.
    2789             :     /// \param err   Pointer to error code, if desired.
    2790             :     /// \return      WKT representation of the polygon.
    2791             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    2792             :                                     OGRErr *err = nullptr) const override;
    2793             : 
    2794             :     // ICurvePolygon.
    2795             :     virtual OGRPolygon *
    2796             :     CurvePolyToPoly(double dfMaxAngleStepSizeDegrees = 0,
    2797             :                     const char *const *papszOptions = nullptr) const override;
    2798             : 
    2799             :     OGRLinearRing *getExteriorRing();
    2800             :     const OGRLinearRing *getExteriorRing() const;
    2801             :     virtual OGRLinearRing *getInteriorRing(int);
    2802             :     virtual const OGRLinearRing *getInteriorRing(int) const;
    2803             : 
    2804             :     OGRLinearRing *stealExteriorRing();
    2805             :     virtual OGRLinearRing *stealInteriorRing(int);
    2806             : 
    2807             :     bool IsPointOnSurface(const OGRPoint *) const;
    2808             : 
    2809             :     /** Return pointer of this in upper class */
    2810          77 :     inline OGRCurvePolygon *toUpperClass()
    2811             :     {
    2812          77 :         return this;
    2813             :     }
    2814             : 
    2815             :     /** Return pointer of this in upper class */
    2816         109 :     inline const OGRCurvePolygon *toUpperClass() const
    2817             :     {
    2818         109 :         return this;
    2819             :     }
    2820             : 
    2821          75 :     void accept(IOGRGeometryVisitor *visitor) override
    2822             :     {
    2823          75 :         visitor->visit(this);
    2824          75 :     }
    2825             : 
    2826         107 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    2827             :     {
    2828         107 :         visitor->visit(this);
    2829         107 :     }
    2830             : 
    2831             :     void closeRings() override;
    2832             : 
    2833           2 :     OGR_ALLOW_UPCAST_TO(CurvePolygon)
    2834             :     OGR_ALLOW_CAST_TO_THIS(Polygon)
    2835             : };
    2836             : 
    2837             : //! @cond Doxygen_Suppress
    2838             : /** @see OGRPolygon::begin() const */
    2839       15158 : inline const OGRPolygon::ChildType *const *begin(const OGRPolygon *poGeom)
    2840             : {
    2841       15158 :     return poGeom->begin();
    2842             : }
    2843             : 
    2844             : /** @see OGRPolygon::end() const */
    2845       15158 : inline const OGRPolygon::ChildType *const *end(const OGRPolygon *poGeom)
    2846             : {
    2847       15158 :     return poGeom->end();
    2848             : }
    2849             : 
    2850             : /** @see OGRPolygon::begin() */
    2851          82 : inline OGRPolygon::ChildType **begin(OGRPolygon *poGeom)
    2852             : {
    2853          82 :     return poGeom->begin();
    2854             : }
    2855             : 
    2856             : /** @see OGRPolygon::end() */
    2857          82 : inline OGRPolygon::ChildType **end(OGRPolygon *poGeom)
    2858             : {
    2859          82 :     return poGeom->end();
    2860             : }
    2861             : 
    2862             : //! @endcond
    2863             : 
    2864             : /************************************************************************/
    2865             : /*                             OGRTriangle                              */
    2866             : /************************************************************************/
    2867             : 
    2868             : /**
    2869             :  * Triangle class.
    2870             :  *
    2871             :  */
    2872             : 
    2873     1329472 : class CPL_DLL OGRTriangle : public OGRPolygon
    2874             : {
    2875             :   private:
    2876             :     // cppcheck-suppress unusedPrivateFunction
    2877             :     static OGRPolygon *CasterToPolygon(OGRSurface *poSurface);
    2878             :     bool quickValidityCheck() const;
    2879             : 
    2880             :   protected:
    2881             :     //! @cond Doxygen_Suppress
    2882             :     OGRSurfaceCasterToPolygon GetCasterToPolygon() const override;
    2883             :     virtual OGRErr importFromWKTListOnly(const char **ppszInput, int bHasZ,
    2884             :                                          int bHasM, OGRRawPoint *&paoPoints,
    2885             :                                          int &nMaxPoints,
    2886             :                                          double *&padfZ) override;
    2887             :     //! @endcond
    2888             : 
    2889             :   public:
    2890             :     /** Constructor. */
    2891       14588 :     OGRTriangle() = default;
    2892             :     OGRTriangle(const OGRPoint &p, const OGRPoint &q, const OGRPoint &r);
    2893             :     OGRTriangle(const OGRTriangle &other);
    2894             :     /** Move constructor */
    2895           1 :     OGRTriangle(OGRTriangle &&other) = default;
    2896             :     OGRTriangle(const OGRPolygon &other, OGRErr &eErr);
    2897             :     OGRTriangle &operator=(const OGRTriangle &other);
    2898             :     /** Move assignment operator */
    2899             :     OGRTriangle &operator=(OGRTriangle &&other) = default;
    2900             : 
    2901             :     /** 2D OGRwkbGeometryType constant. */
    2902             :     static constexpr OGRwkbGeometryType EnumType2D = wkbTriangle;
    2903             : 
    2904             :     /** C++ type for corresponding collection. */
    2905             :     using MultiType = OGRTriangulatedSurface;
    2906             : 
    2907             :     const char *getGeometryName() const override;
    2908             :     OGRwkbGeometryType getGeometryType() const override;
    2909             :     OGRTriangle *clone() const override;
    2910             : 
    2911             :     // IWks Interface.
    2912             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    2913             :                                  size_t &nBytesConsumedOut) override;
    2914             : 
    2915             :     // New methods rewritten from OGRPolygon/OGRCurvePolygon/OGRGeometry.
    2916             :     OGRErr addRingDirectly(OGRCurve *poNewRing) override;
    2917             : 
    2918             :     /** Return pointer of this in upper class */
    2919           2 :     inline OGRPolygon *toUpperClass()
    2920             :     {
    2921           2 :         return this;
    2922             :     }
    2923             : 
    2924             :     /** Return pointer of this in upper class */
    2925           2 :     inline const OGRPolygon *toUpperClass() const
    2926             :     {
    2927           2 :         return this;
    2928             :     }
    2929             : 
    2930           2 :     void accept(IOGRGeometryVisitor *visitor) override
    2931             :     {
    2932           2 :         visitor->visit(this);
    2933           2 :     }
    2934             : 
    2935           2 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    2936             :     {
    2937           2 :         visitor->visit(this);
    2938           2 :     }
    2939             : 
    2940             :     //! @cond Doxygen_Suppress
    2941             :     static OGRGeometry *CastToPolygon(OGRGeometry *poGeom);
    2942             :     //! @endcond
    2943             : 
    2944           1 :     OGR_ALLOW_UPCAST_TO(Polygon)
    2945             :     OGR_ALLOW_CAST_TO_THIS(Triangle)
    2946             : };
    2947             : 
    2948             : /************************************************************************/
    2949             : /*                        OGRGeometryCollection                         */
    2950             : /************************************************************************/
    2951             : 
    2952             : /**
    2953             :  * A collection of 1 or more geometry objects.
    2954             :  *
    2955             :  * All geometries must share a common spatial reference system, and
    2956             :  * Subclasses may impose additional restrictions on the contents.
    2957             :  */
    2958             : 
    2959             : class CPL_DLL OGRGeometryCollection : public OGRGeometry
    2960             : {
    2961             :     OGRErr importFromWktInternal(const char **ppszInput, int nRecLevel);
    2962             : 
    2963             :   protected:
    2964             :     //! @cond Doxygen_Suppress
    2965             :     int nGeomCount = 0;
    2966             :     OGRGeometry **papoGeoms = nullptr;
    2967             : 
    2968             :     std::string
    2969             :     exportToWktInternal(const OGRWktOptions &opts, OGRErr *err,
    2970             :                         const std::string &exclude = std::string()) const;
    2971             :     static OGRGeometryCollection *
    2972             :     TransferMembersAndDestroy(OGRGeometryCollection *poSrc,
    2973             :                               OGRGeometryCollection *poDst);
    2974             : 
    2975             :     OGRErr importFromWkbInternal(const unsigned char *pabyData, size_t nSize,
    2976             :                                  int nRecLevel, OGRwkbVariant,
    2977             :                                  size_t &nBytesConsumedOut);
    2978             :     //! @endcond
    2979             :     virtual bool isCompatibleSubType(OGRwkbGeometryType) const;
    2980             : 
    2981             :   public:
    2982             :     /** Create an empty geometry collection. */
    2983      128662 :     OGRGeometryCollection() = default;
    2984             : 
    2985             :     OGRGeometryCollection(const OGRGeometryCollection &other);
    2986             :     OGRGeometryCollection(OGRGeometryCollection &&other);
    2987             :     ~OGRGeometryCollection() override;
    2988             : 
    2989             :     OGRGeometryCollection &operator=(const OGRGeometryCollection &other);
    2990             :     OGRGeometryCollection &operator=(OGRGeometryCollection &&other);
    2991             : 
    2992             :     /** C++ type of child elements. */
    2993             :     using ChildType = OGRGeometry;
    2994             : 
    2995             :     /** 2D OGRwkbGeometryType constant. */
    2996             :     static constexpr OGRwkbGeometryType EnumType2D = wkbGeometryCollection;
    2997             : 
    2998             :     /** C++ type for corresponding collection. */
    2999             :     using MultiType = OGRGeometryCollection;
    3000             : 
    3001             :     /** Return begin of sub-geometry iterator.
    3002             :      */
    3003      379596 :     ChildType **begin()
    3004             :     {
    3005      379596 :         return papoGeoms;
    3006             :     }
    3007             : 
    3008             :     /** Return end of sub-geometry iterator. */
    3009      379596 :     ChildType **end()
    3010             :     {
    3011      379596 :         return papoGeoms + nGeomCount;
    3012             :     }
    3013             : 
    3014             :     /** Return begin of sub-geometry iterator.
    3015             :      */
    3016       93148 :     const ChildType *const *begin() const
    3017             :     {
    3018       93148 :         return papoGeoms;
    3019             :     }
    3020             : 
    3021             :     /** Return end of sub-geometry iterator. */
    3022       93148 :     const ChildType *const *end() const
    3023             :     {
    3024       93148 :         return papoGeoms + nGeomCount;
    3025             :     }
    3026             : 
    3027             :     // Non standard (OGRGeometry).
    3028             :     const char *getGeometryName() const override;
    3029             :     OGRwkbGeometryType getGeometryType() const override;
    3030             :     OGRGeometryCollection *clone() const override;
    3031             :     void empty() override;
    3032             :     OGRErr transform(OGRCoordinateTransformation *poCT) override;
    3033             :     void flattenTo2D() override;
    3034             :     bool IsEmpty() const override;
    3035             :     bool segmentize(double dfMaxLength) override;
    3036             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    3037             :     virtual OGRGeometry *
    3038             :     getCurveGeometry(const char *const *papszOptions = nullptr) const override;
    3039             :     virtual OGRGeometry *
    3040             :     getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
    3041             :                       const char *const *papszOptions = nullptr) const override;
    3042             :     virtual double
    3043             :     get_GeodesicArea(const OGRSpatialReference *poSRSOverride = nullptr) const;
    3044             :     virtual double get_GeodesicLength(
    3045             :         const OGRSpatialReference *poSRSOverride = nullptr) const;
    3046             : 
    3047             :     // IWks Interface
    3048             :     size_t WkbSize() const override;
    3049             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    3050             :                                  size_t &nBytesConsumedOut) override;
    3051             :     OGRErr exportToWkb(unsigned char *,
    3052             :                        const OGRwkbExportOptions * = nullptr) const override;
    3053             : 
    3054             : #ifndef DOXYGEN_XML
    3055             :     using OGRGeometry::importFromWkt; /** deprecated */
    3056             : #endif
    3057             : 
    3058             :     OGRErr importFromWkt(const char **) override;
    3059             : 
    3060             : #ifndef DOXYGEN_XML
    3061             :     using OGRGeometry::exportToWkt;
    3062             : #endif
    3063             : 
    3064             :     /// Export a geometry collection to WKT
    3065             :     /// \param opts  Output options.
    3066             :     /// \param err   Pointer to error code, if desired.
    3067             :     /// \return      WKT representation of the geometry collection.
    3068             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    3069             :                                     OGRErr *err = nullptr) const override;
    3070             : 
    3071             :     virtual double get_Length() const;
    3072             :     virtual double get_Area() const;
    3073             : 
    3074             :     // IGeometry methods
    3075             :     int getDimension() const override;
    3076             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    3077             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    3078             : 
    3079             :     // IGeometryCollection
    3080             :     int getNumGeometries() const;
    3081             :     OGRGeometry *getGeometryRef(int);
    3082             :     const OGRGeometry *getGeometryRef(int) const;
    3083             : 
    3084             :     // ISpatialRelation
    3085             :     bool Equals(const OGRGeometry *) const override;
    3086             : 
    3087             :     // Non standard
    3088             :     bool setCoordinateDimension(int nDimension) override;
    3089             :     bool set3D(bool bIs3D) override;
    3090             :     bool setMeasured(bool bIsMeasured) override;
    3091             :     virtual OGRErr addGeometry(const OGRGeometry *);
    3092             :     virtual OGRErr addGeometryDirectly(OGRGeometry *);
    3093             :     OGRErr addGeometry(std::unique_ptr<OGRGeometry> geom);
    3094             :     OGRErr addGeometryComponents(std::unique_ptr<OGRGeometryCollection> geom);
    3095             :     virtual OGRErr removeGeometry(int iIndex, int bDelete = TRUE);
    3096             :     std::unique_ptr<OGRGeometry> stealGeometry(int iIndex);
    3097             : 
    3098             :     bool hasEmptyParts() const override;
    3099             :     void removeEmptyParts() override;
    3100             : 
    3101             :     virtual void
    3102             :     assignSpatialReference(const OGRSpatialReference *poSR) override;
    3103             : 
    3104             :     void closeRings() override;
    3105             : 
    3106             :     void swapXY() override;
    3107             : 
    3108           1 :     void accept(IOGRGeometryVisitor *visitor) override
    3109             :     {
    3110           1 :         visitor->visit(this);
    3111           1 :     }
    3112             : 
    3113           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    3114             :     {
    3115           1 :         visitor->visit(this);
    3116           1 :     }
    3117             : 
    3118             :     static OGRGeometryCollection *
    3119             :     CastToGeometryCollection(OGRGeometryCollection *poSrc);
    3120             : 
    3121             :     OGR_FORBID_DOWNCAST_TO_POINT
    3122             :     OGR_FORBID_DOWNCAST_TO_ALL_CURVES
    3123             :     OGR_FORBID_DOWNCAST_TO_ALL_SURFACES
    3124             :     OGR_ALLOW_CAST_TO_THIS(GeometryCollection)
    3125             : };
    3126             : 
    3127             : //! @cond Doxygen_Suppress
    3128             : /** @see OGRGeometryCollection::begin() const */
    3129             : inline const OGRGeometryCollection::ChildType *const *
    3130        1507 : begin(const OGRGeometryCollection *poGeom)
    3131             : {
    3132        1507 :     return poGeom->begin();
    3133             : }
    3134             : 
    3135             : /** @see OGRGeometryCollection::end() const */
    3136             : inline const OGRGeometryCollection::ChildType *const *
    3137        1507 : end(const OGRGeometryCollection *poGeom)
    3138             : {
    3139        1507 :     return poGeom->end();
    3140             : }
    3141             : 
    3142             : /** @see OGRGeometryCollection::begin() */
    3143        3614 : inline OGRGeometryCollection::ChildType **begin(OGRGeometryCollection *poGeom)
    3144             : {
    3145        3614 :     return poGeom->begin();
    3146             : }
    3147             : 
    3148             : /** @see OGRGeometryCollection::end() */
    3149        3614 : inline OGRGeometryCollection::ChildType **end(OGRGeometryCollection *poGeom)
    3150             : {
    3151        3614 :     return poGeom->end();
    3152             : }
    3153             : 
    3154             : //! @endcond
    3155             : 
    3156             : /************************************************************************/
    3157             : /*                           OGRMultiSurface                            */
    3158             : /************************************************************************/
    3159             : 
    3160             : /**
    3161             :  * A collection of non-overlapping OGRSurface.
    3162             :  *
    3163             :  */
    3164             : 
    3165        3218 : class CPL_DLL OGRMultiSurface : public OGRGeometryCollection
    3166             : {
    3167             :   protected:
    3168             :     bool isCompatibleSubType(OGRwkbGeometryType) const override;
    3169             : 
    3170             :   public:
    3171             :     /** Create an empty multi surface collection. */
    3172       80857 :     OGRMultiSurface() = default;
    3173             : 
    3174             :     OGRMultiSurface(const OGRMultiSurface &other);
    3175             :     /** Move constructor */
    3176           4 :     OGRMultiSurface(OGRMultiSurface &&other) = default;
    3177             : 
    3178             :     OGRMultiSurface &operator=(const OGRMultiSurface &other);
    3179             :     /** Move assignment operator */
    3180             :     OGRMultiSurface &operator=(OGRMultiSurface &&other) = default;
    3181             : 
    3182             :     /** C++ type of child elements. */
    3183             :     using ChildType = OGRSurface;
    3184             : 
    3185             :     /** 2D OGRwkbGeometryType constant. */
    3186             :     static constexpr OGRwkbGeometryType EnumType2D = wkbMultiSurface;
    3187             : 
    3188             :     /** C++ type for corresponding collection. */
    3189             :     using MultiType = OGRGeometryCollection;
    3190             : 
    3191             :     /** Return begin of iterator.
    3192             :      */
    3193          64 :     ChildType **begin()
    3194             :     {
    3195          64 :         return reinterpret_cast<ChildType **>(papoGeoms);
    3196             :     }
    3197             : 
    3198             :     /** Return end of iterator */
    3199          64 :     ChildType **end()
    3200             :     {
    3201          64 :         return reinterpret_cast<ChildType **>(papoGeoms + nGeomCount);
    3202             :     }
    3203             : 
    3204             :     /** Return begin of iterator.
    3205             :      */
    3206          94 :     const ChildType *const *begin() const
    3207             :     {
    3208          94 :         return reinterpret_cast<const ChildType *const *>(papoGeoms);
    3209             :     }
    3210             : 
    3211             :     /** Return end of iterator */
    3212          94 :     const ChildType *const *end() const
    3213             :     {
    3214          94 :         return reinterpret_cast<const ChildType *const *>(papoGeoms +
    3215          94 :                                                           nGeomCount);
    3216             :     }
    3217             : 
    3218             :     // Non standard (OGRGeometry).
    3219             :     const char *getGeometryName() const override;
    3220             :     OGRwkbGeometryType getGeometryType() const override;
    3221             :     OGRMultiSurface *clone() const override;
    3222             : 
    3223             : #ifndef DOXYGEN_XML
    3224             :     using OGRGeometry::importFromWkt; /** deprecated */
    3225             : #endif
    3226             : 
    3227             :     OGRErr importFromWkt(const char **) override;
    3228             : 
    3229             : #ifndef DOXYGEN_XML
    3230             :     using OGRGeometry::exportToWkt;
    3231             : #endif
    3232             : 
    3233             :     /// Export a geometry collection to WKT
    3234             :     /// \param opts  Output options.
    3235             :     /// \param err   Pointer to error code, if desired.
    3236             :     /// \return      WKT representation of the geometry collection.
    3237             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    3238             :                                     OGRErr *err = nullptr) const override;
    3239             : 
    3240             :     // IMultiSurface methods
    3241             :     virtual OGRErr PointOnSurface(OGRPoint *poPoint) const;
    3242             : 
    3243             :     // IGeometry methods
    3244             :     int getDimension() const override;
    3245             : 
    3246             :     // IGeometryCollection
    3247             :     /** See OGRGeometryCollection::getGeometryRef() */
    3248           8 :     OGRSurface *getGeometryRef(int i)
    3249             :     {
    3250           8 :         return OGRGeometryCollection::getGeometryRef(i)->toSurface();
    3251             :     }
    3252             : 
    3253             :     /** See OGRGeometryCollection::getGeometryRef() */
    3254             :     const OGRSurface *getGeometryRef(int i) const
    3255             :     {
    3256             :         return OGRGeometryCollection::getGeometryRef(i)->toSurface();
    3257             :     }
    3258             : 
    3259             :     // Non standard
    3260             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    3261             : 
    3262             :     /** Return pointer of this in upper class */
    3263           1 :     inline OGRGeometryCollection *toUpperClass()
    3264             :     {
    3265           1 :         return this;
    3266             :     }
    3267             : 
    3268             :     /** Return pointer of this in upper class */
    3269           1 :     inline const OGRGeometryCollection *toUpperClass() const
    3270             :     {
    3271           1 :         return this;
    3272             :     }
    3273             : 
    3274           1 :     void accept(IOGRGeometryVisitor *visitor) override
    3275             :     {
    3276           1 :         visitor->visit(this);
    3277           1 :     }
    3278             : 
    3279           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    3280             :     {
    3281           1 :         visitor->visit(this);
    3282           1 :     }
    3283             : 
    3284             :     static OGRMultiPolygon *CastToMultiPolygon(OGRMultiSurface *poMS);
    3285             : 
    3286             :     OGR_ALLOW_CAST_TO_THIS(MultiSurface)
    3287           2 :     OGR_ALLOW_UPCAST_TO(GeometryCollection)
    3288             :     OGR_FORBID_DOWNCAST_TO_MULTIPOINT
    3289             :     OGR_FORBID_DOWNCAST_TO_MULTILINESTRING
    3290             :     OGR_FORBID_DOWNCAST_TO_MULTICURVE
    3291             : };
    3292             : 
    3293             : //! @cond Doxygen_Suppress
    3294             : /** @see OGRMultiSurface::begin() const */
    3295             : inline const OGRMultiSurface::ChildType *const *
    3296           2 : begin(const OGRMultiSurface *poGeom)
    3297             : {
    3298           2 :     return poGeom->begin();
    3299             : }
    3300             : 
    3301             : /** @see OGRMultiSurface::end() const */
    3302             : inline const OGRMultiSurface::ChildType *const *
    3303           2 : end(const OGRMultiSurface *poGeom)
    3304             : {
    3305           2 :     return poGeom->end();
    3306             : }
    3307             : 
    3308             : /** @see OGRMultiSurface::begin() */
    3309           2 : inline OGRMultiSurface::ChildType **begin(OGRMultiSurface *poGeom)
    3310             : {
    3311           2 :     return poGeom->begin();
    3312             : }
    3313             : 
    3314             : /** @see OGRMultiSurface::end() */
    3315           2 : inline OGRMultiSurface::ChildType **end(OGRMultiSurface *poGeom)
    3316             : {
    3317           2 :     return poGeom->end();
    3318             : }
    3319             : 
    3320             : //! @endcond
    3321             : 
    3322             : /************************************************************************/
    3323             : /*                           OGRMultiPolygon                            */
    3324             : /************************************************************************/
    3325             : 
    3326             : /**
    3327             :  * A collection of non-overlapping OGRPolygon.
    3328             :  */
    3329             : 
    3330        3069 : class CPL_DLL OGRMultiPolygon : public OGRMultiSurface
    3331             : {
    3332             :   protected:
    3333             :     bool isCompatibleSubType(OGRwkbGeometryType) const override;
    3334             :     friend class OGRPolyhedralSurface;
    3335             :     friend class OGRTriangulatedSurface;
    3336             : 
    3337             :   private:
    3338             :     //! @cond Doxygen_Suppress
    3339             :     OGRErr _addGeometryWithExpectedSubGeometryType(
    3340             :         const OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType);
    3341             :     OGRErr _addGeometryDirectlyWithExpectedSubGeometryType(
    3342             :         OGRGeometry *poNewGeom, OGRwkbGeometryType eSubGeometryType);
    3343             :     //! @endcond
    3344             : 
    3345             :   public:
    3346             :     /** Create an empty multi polygon collection. */
    3347       79350 :     OGRMultiPolygon() = default;
    3348             : 
    3349             :     OGRMultiPolygon(const OGRMultiPolygon &other);
    3350             :     /** Move constructor */
    3351           3 :     OGRMultiPolygon(OGRMultiPolygon &&other) = default;
    3352             : 
    3353             :     OGRMultiPolygon &operator=(const OGRMultiPolygon &other);
    3354             :     /** Move assignment operator */
    3355             :     OGRMultiPolygon &operator=(OGRMultiPolygon &&other) = default;
    3356             : 
    3357             :     /** C++ type of child elements. */
    3358             :     using ChildType = OGRPolygon;
    3359             : 
    3360             :     /** 2D OGRwkbGeometryType constant. */
    3361             :     static constexpr OGRwkbGeometryType EnumType2D = wkbMultiPolygon;
    3362             : 
    3363             :     /** C++ type for corresponding collection. */
    3364             :     using MultiType = OGRGeometryCollection;
    3365             : 
    3366             :     /** Return begin of iterator.
    3367             :      */
    3368        1278 :     ChildType **begin()
    3369             :     {
    3370        1278 :         return reinterpret_cast<ChildType **>(papoGeoms);
    3371             :     }
    3372             : 
    3373             :     /** Return end of iterator */
    3374        1278 :     ChildType **end()
    3375             :     {
    3376        1278 :         return reinterpret_cast<ChildType **>(papoGeoms + nGeomCount);
    3377             :     }
    3378             : 
    3379             :     /** Return begin of iterator.
    3380             :      */
    3381       19842 :     const ChildType *const *begin() const
    3382             :     {
    3383       19842 :         return reinterpret_cast<const ChildType *const *>(papoGeoms);
    3384             :     }
    3385             : 
    3386             :     /** Return end of iterator */
    3387       19842 :     const ChildType *const *end() const
    3388             :     {
    3389       19842 :         return reinterpret_cast<const ChildType *const *>(papoGeoms +
    3390       19842 :                                                           nGeomCount);
    3391             :     }
    3392             : 
    3393             :     // IGeometryCollection
    3394             :     /** See OGRGeometryCollection::getGeometryRef() */
    3395         447 :     OGRPolygon *getGeometryRef(int i)
    3396             :     {
    3397         447 :         return OGRGeometryCollection::getGeometryRef(i)->toPolygon();
    3398             :     }
    3399             : 
    3400             :     /** See OGRGeometryCollection::getGeometryRef() */
    3401      165112 :     const OGRPolygon *getGeometryRef(int i) const
    3402             :     {
    3403      165112 :         return OGRGeometryCollection::getGeometryRef(i)->toPolygon();
    3404             :     }
    3405             : 
    3406             :     // Non-standard (OGRGeometry).
    3407             :     const char *getGeometryName() const override;
    3408             :     OGRwkbGeometryType getGeometryType() const override;
    3409             :     OGRMultiPolygon *clone() const override;
    3410             : 
    3411             : #ifndef DOXYGEN_XML
    3412             :     using OGRGeometry::exportToWkt;
    3413             : #endif
    3414             : 
    3415             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    3416             :                                  size_t &nBytesConsumedOut) override;
    3417             : 
    3418             :     /// Export a multipolygon to WKT
    3419             :     /// \param opts  Output options.
    3420             :     /// \param err   Pointer to error code, if desired.
    3421             :     /// \return      WKT representation of the multipolygon.
    3422             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    3423             :                                     OGRErr *err = nullptr) const override;
    3424             : 
    3425             :     // Non standard
    3426             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    3427             : 
    3428             :     /** Return pointer of this in upper class */
    3429          14 :     inline OGRGeometryCollection *toUpperClass()
    3430             :     {
    3431          14 :         return this;
    3432             :     }
    3433             : 
    3434             :     /** Return pointer of this in upper class */
    3435           1 :     inline const OGRGeometryCollection *toUpperClass() const
    3436             :     {
    3437           1 :         return this;
    3438             :     }
    3439             : 
    3440          14 :     void accept(IOGRGeometryVisitor *visitor) override
    3441             :     {
    3442          14 :         visitor->visit(this);
    3443          14 :     }
    3444             : 
    3445           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    3446             :     {
    3447           1 :         visitor->visit(this);
    3448           1 :     }
    3449             : 
    3450             :     static OGRMultiSurface *CastToMultiSurface(OGRMultiPolygon *poMP);
    3451             : 
    3452             :     OGR_ALLOW_CAST_TO_THIS(MultiPolygon)
    3453           1 :     OGR_ALLOW_UPCAST_TO(MultiSurface)
    3454             : };
    3455             : 
    3456             : //! @cond Doxygen_Suppress
    3457             : /** @see OGRMultiPolygon::begin() const */
    3458             : inline const OGRMultiPolygon::ChildType *const *
    3459         120 : begin(const OGRMultiPolygon *poGeom)
    3460             : {
    3461         120 :     return poGeom->begin();
    3462             : }
    3463             : 
    3464             : /** @see OGRMultiPolygon::end() const */
    3465             : inline const OGRMultiPolygon::ChildType *const *
    3466         120 : end(const OGRMultiPolygon *poGeom)
    3467             : {
    3468         120 :     return poGeom->end();
    3469             : }
    3470             : 
    3471             : /** @see OGRMultiPolygon::begin() */
    3472          13 : inline OGRMultiPolygon::ChildType **begin(OGRMultiPolygon *poGeom)
    3473             : {
    3474          13 :     return poGeom->begin();
    3475             : }
    3476             : 
    3477             : /** @see OGRMultiPolygon::end() */
    3478          13 : inline OGRMultiPolygon::ChildType **end(OGRMultiPolygon *poGeom)
    3479             : {
    3480          13 :     return poGeom->end();
    3481             : }
    3482             : 
    3483             : //! @endcond
    3484             : 
    3485             : /************************************************************************/
    3486             : /*                         OGRPolyhedralSurface                         */
    3487             : /************************************************************************/
    3488             : 
    3489             : /**
    3490             :  * PolyhedralSurface class.
    3491             :  *
    3492             :  */
    3493             : 
    3494          43 : class CPL_DLL OGRPolyhedralSurface : public OGRSurface
    3495             : {
    3496             :   protected:
    3497             :     //! @cond Doxygen_Suppress
    3498             :     friend class OGRTriangulatedSurface;
    3499             :     OGRMultiPolygon oMP{};
    3500             :     OGRSurfaceCasterToPolygon GetCasterToPolygon() const override;
    3501             :     virtual OGRSurfaceCasterToCurvePolygon
    3502             :     GetCasterToCurvePolygon() const override;
    3503             :     virtual bool isCompatibleSubType(OGRwkbGeometryType) const;
    3504             :     virtual const char *getSubGeometryName() const;
    3505             :     virtual OGRwkbGeometryType getSubGeometryType() const;
    3506             :     std::string exportToWktInternal(const OGRWktOptions &opts,
    3507             :                                     OGRErr *err) const;
    3508             : 
    3509             :     virtual OGRPolyhedralSurfaceCastToMultiPolygon
    3510             :     GetCasterToMultiPolygon() const;
    3511             :     static OGRMultiPolygon *CastToMultiPolygonImpl(OGRPolyhedralSurface *poPS);
    3512             :     //! @endcond
    3513             : 
    3514             :   public:
    3515             :     /** Create an empty PolyhedralSurface */
    3516       50910 :     OGRPolyhedralSurface() = default;
    3517             : 
    3518             :     OGRPolyhedralSurface(const OGRPolyhedralSurface &other);
    3519             :     /** Move constructor */
    3520           2 :     OGRPolyhedralSurface(OGRPolyhedralSurface &&other) = default;
    3521             : 
    3522             :     OGRPolyhedralSurface &operator=(const OGRPolyhedralSurface &other);
    3523             :     /** Move assignment operator */
    3524             :     OGRPolyhedralSurface &operator=(OGRPolyhedralSurface &&other) = default;
    3525             : 
    3526             :     /** C++ type of child elements. */
    3527             :     using ChildType = OGRPolygon;
    3528             : 
    3529             :     /** 2D OGRwkbGeometryType constant. */
    3530             :     static constexpr OGRwkbGeometryType EnumType2D = wkbPolyhedralSurface;
    3531             : 
    3532             :     /** C++ type for corresponding collection. */
    3533             :     using MultiType = OGRGeometryCollection;
    3534             : 
    3535             :     /** Return begin of iterator.
    3536             :      */
    3537         979 :     ChildType **begin()
    3538             :     {
    3539         979 :         return oMP.begin();
    3540             :     }
    3541             : 
    3542             :     /** Return end of iterator */
    3543         979 :     ChildType **end()
    3544             :     {
    3545         979 :         return oMP.end();
    3546             :     }
    3547             : 
    3548             :     /** Return begin of iterator.
    3549             :      */
    3550       18096 :     const ChildType *const *begin() const
    3551             :     {
    3552       18096 :         return oMP.begin();
    3553             :     }
    3554             : 
    3555             :     /** Return end of iterator */
    3556       18096 :     const ChildType *const *end() const
    3557             :     {
    3558       18096 :         return oMP.end();
    3559             :     }
    3560             : 
    3561             :     // IWks Interface.
    3562             :     size_t WkbSize() const override;
    3563             :     const char *getGeometryName() const override;
    3564             :     OGRwkbGeometryType getGeometryType() const override;
    3565             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    3566             :                                  size_t &nBytesConsumedOut) override;
    3567             :     OGRErr exportToWkb(unsigned char *,
    3568             :                        const OGRwkbExportOptions * = nullptr) const override;
    3569             : 
    3570             : #ifndef DOXYGEN_XML
    3571             :     using OGRGeometry::importFromWkt; /** deprecated */
    3572             : #endif
    3573             : 
    3574             :     OGRErr importFromWkt(const char **) override;
    3575             : 
    3576             : #ifndef DOXYGEN_XML
    3577             :     using OGRGeometry::exportToWkt;
    3578             : #endif
    3579             : 
    3580             :     /// Export a polyhedral surface to WKT
    3581             :     /// \param opts  Output options.
    3582             :     /// \param err   Pointer to error code, if desired.
    3583             :     /// \return      WKT representation of the polyhedral surface.
    3584             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    3585             :                                     OGRErr *err = nullptr) const override;
    3586             : 
    3587             :     // IGeometry methods.
    3588             :     int getDimension() const override;
    3589             : 
    3590             :     void empty() override;
    3591             : 
    3592             :     OGRPolyhedralSurface *clone() const override;
    3593             :     void getEnvelope(OGREnvelope *psEnvelope) const override;
    3594             :     void getEnvelope(OGREnvelope3D *psEnvelope) const override;
    3595             : 
    3596             :     void flattenTo2D() override;
    3597             :     OGRErr transform(OGRCoordinateTransformation *) override;
    3598             :     bool Equals(const OGRGeometry *) const override;
    3599             :     double get_Area() const override;
    3600             :     virtual double get_GeodesicArea(
    3601             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    3602             :     double get_Length() const override;
    3603             :     virtual double get_GeodesicLength(
    3604             :         const OGRSpatialReference *poSRSOverride = nullptr) const override;
    3605             : 
    3606             :     OGRErr PointOnSurface(OGRPoint *) const override;
    3607             : 
    3608             :     static OGRMultiPolygon *CastToMultiPolygon(OGRPolyhedralSurface *poPS);
    3609             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    3610             :     virtual OGRErr addGeometry(const OGRGeometry *);
    3611             :     OGRErr addGeometryDirectly(OGRGeometry *poNewGeom);
    3612             :     OGRErr addGeometry(std::unique_ptr<OGRGeometry> poNewGeom);
    3613             : 
    3614             :     int getNumGeometries() const;
    3615             :     OGRPolygon *getGeometryRef(int i);
    3616             :     const OGRPolygon *getGeometryRef(int i) const;
    3617             : 
    3618             :     bool IsEmpty() const override;
    3619             :     bool setCoordinateDimension(int nDimension) override;
    3620             :     bool set3D(bool bIs3D) override;
    3621             :     bool setMeasured(bool bIsMeasured) override;
    3622             :     void swapXY() override;
    3623             :     OGRErr removeGeometry(int iIndex, int bDelete = TRUE);
    3624             : 
    3625             :     bool hasEmptyParts() const override;
    3626             :     void removeEmptyParts() override;
    3627             : 
    3628           1 :     void accept(IOGRGeometryVisitor *visitor) override
    3629             :     {
    3630           1 :         visitor->visit(this);
    3631           1 :     }
    3632             : 
    3633           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    3634             :     {
    3635           1 :         visitor->visit(this);
    3636           1 :     }
    3637             : 
    3638             :     virtual void
    3639             :     assignSpatialReference(const OGRSpatialReference *poSR) override;
    3640             : 
    3641             :     OGR_ALLOW_CAST_TO_THIS(PolyhedralSurface)
    3642           2 :     OGR_ALLOW_UPCAST_TO(Surface)
    3643             : };
    3644             : 
    3645             : //! @cond Doxygen_Suppress
    3646             : /** @see OGRPolyhedralSurface::begin() const */
    3647             : inline const OGRPolyhedralSurface::ChildType *const *
    3648           2 : begin(const OGRPolyhedralSurface *poGeom)
    3649             : {
    3650           2 :     return poGeom->begin();
    3651             : }
    3652             : 
    3653             : /** @see OGRPolyhedralSurface::end() const */
    3654             : inline const OGRPolyhedralSurface::ChildType *const *
    3655           2 : end(const OGRPolyhedralSurface *poGeom)
    3656             : {
    3657           2 :     return poGeom->end();
    3658             : }
    3659             : 
    3660             : /** @see OGRPolyhedralSurface::begin() */
    3661           2 : inline OGRPolyhedralSurface::ChildType **begin(OGRPolyhedralSurface *poGeom)
    3662             : {
    3663           2 :     return poGeom->begin();
    3664             : }
    3665             : 
    3666             : /** @see OGRPolyhedralSurface::end() */
    3667           2 : inline OGRPolyhedralSurface::ChildType **end(OGRPolyhedralSurface *poGeom)
    3668             : {
    3669           2 :     return poGeom->end();
    3670             : }
    3671             : 
    3672             : //! @endcond
    3673             : 
    3674             : /************************************************************************/
    3675             : /*                        OGRTriangulatedSurface                        */
    3676             : /************************************************************************/
    3677             : 
    3678             : /**
    3679             :  * TriangulatedSurface class.
    3680             :  *
    3681             :  */
    3682             : 
    3683           2 : class CPL_DLL OGRTriangulatedSurface : public OGRPolyhedralSurface
    3684             : {
    3685             :   protected:
    3686             :     //! @cond Doxygen_Suppress
    3687             :     bool isCompatibleSubType(OGRwkbGeometryType) const override;
    3688             :     const char *getSubGeometryName() const override;
    3689             :     OGRwkbGeometryType getSubGeometryType() const override;
    3690             : 
    3691             :     virtual OGRPolyhedralSurfaceCastToMultiPolygon
    3692             :     GetCasterToMultiPolygon() const override;
    3693             :     static OGRMultiPolygon *CastToMultiPolygonImpl(OGRPolyhedralSurface *poPS);
    3694             :     //! @endcond
    3695             : 
    3696             :   public:
    3697             :     /** Constructor */
    3698       42247 :     OGRTriangulatedSurface() = default;
    3699             : 
    3700             :     OGRTriangulatedSurface(const OGRTriangulatedSurface &other);
    3701             :     /** Move constructor */
    3702           1 :     OGRTriangulatedSurface(OGRTriangulatedSurface &&other) = default;
    3703             : 
    3704             :     OGRTriangulatedSurface &operator=(const OGRTriangulatedSurface &other);
    3705             :     /** Move assignment operator */
    3706             :     OGRTriangulatedSurface &operator=(OGRTriangulatedSurface &&other) = default;
    3707             : 
    3708             :     /** C++ type of child elements. */
    3709             :     using ChildType = OGRTriangle;
    3710             : 
    3711             :     /** 2D OGRwkbGeometryType constant. */
    3712             :     static constexpr OGRwkbGeometryType EnumType2D = wkbTIN;
    3713             : 
    3714             :     /** C++ type for corresponding collection. */
    3715             :     using MultiType = OGRGeometryCollection;
    3716             : 
    3717             :     /** Return begin of iterator.
    3718             :      */
    3719           3 :     ChildType **begin()
    3720             :     {
    3721           3 :         return reinterpret_cast<ChildType **>(oMP.begin());
    3722             :     }
    3723             : 
    3724             :     /** Return end of iterator */
    3725           3 :     ChildType **end()
    3726             :     {
    3727           3 :         return reinterpret_cast<ChildType **>(oMP.end());
    3728             :     }
    3729             : 
    3730             :     /** Return begin of iterator.
    3731             :      */
    3732           3 :     const ChildType *const *begin() const
    3733             :     {
    3734           3 :         return reinterpret_cast<const ChildType *const *>(oMP.begin());
    3735             :     }
    3736             : 
    3737             :     /** Return end of iterator */
    3738           3 :     const ChildType *const *end() const
    3739             :     {
    3740           3 :         return reinterpret_cast<const ChildType *const *>(oMP.end());
    3741             :     }
    3742             : 
    3743             :     const char *getGeometryName() const override;
    3744             :     OGRwkbGeometryType getGeometryType() const override;
    3745             :     OGRTriangulatedSurface *clone() const override;
    3746             : 
    3747             :     /** See OGRPolyhedralSurface::getGeometryRef() */
    3748             :     OGRTriangle *getGeometryRef(int i)
    3749             :     {
    3750             :         return OGRPolyhedralSurface::getGeometryRef(i)->toTriangle();
    3751             :     }
    3752             : 
    3753             :     /** See OGRPolyhedralSurface::getGeometryRef() */
    3754           1 :     const OGRTriangle *getGeometryRef(int i) const
    3755             :     {
    3756           1 :         return OGRPolyhedralSurface::getGeometryRef(i)->toTriangle();
    3757             :     }
    3758             : 
    3759             :     // IWks Interface.
    3760             :     OGRErr addGeometry(const OGRGeometry *) override;
    3761             : 
    3762             : #ifndef DOXYGEN_XML
    3763             :     using OGRPolyhedralSurface::addGeometry;
    3764             : #endif
    3765             : 
    3766             :     /** Return pointer of this in upper class */
    3767           1 :     inline OGRPolyhedralSurface *toUpperClass()
    3768             :     {
    3769           1 :         return this;
    3770             :     }
    3771             : 
    3772             :     /** Return pointer of this in upper class */
    3773           1 :     inline const OGRPolyhedralSurface *toUpperClass() const
    3774             :     {
    3775           1 :         return this;
    3776             :     }
    3777             : 
    3778           1 :     void accept(IOGRGeometryVisitor *visitor) override
    3779             :     {
    3780           1 :         visitor->visit(this);
    3781           1 :     }
    3782             : 
    3783           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    3784             :     {
    3785           1 :         visitor->visit(this);
    3786           1 :     }
    3787             : 
    3788             :     static OGRPolyhedralSurface *
    3789             :     CastToPolyhedralSurface(OGRTriangulatedSurface *poTS);
    3790             : 
    3791             :     OGR_ALLOW_CAST_TO_THIS(TriangulatedSurface)
    3792           1 :     OGR_ALLOW_UPCAST_TO(PolyhedralSurface)
    3793             : };
    3794             : 
    3795             : //! @cond Doxygen_Suppress
    3796             : /** @see OGRTriangulatedSurface::begin() const */
    3797             : inline const OGRTriangulatedSurface::ChildType *const *
    3798           2 : begin(const OGRTriangulatedSurface *poGeom)
    3799             : {
    3800           2 :     return poGeom->begin();
    3801             : }
    3802             : 
    3803             : /** @see OGRTriangulatedSurface::end() const */
    3804             : inline const OGRTriangulatedSurface::ChildType *const *
    3805           2 : end(const OGRTriangulatedSurface *poGeom)
    3806             : {
    3807           2 :     return poGeom->end();
    3808             : }
    3809             : 
    3810             : /** @see OGRTriangulatedSurface::begin() */
    3811           2 : inline OGRTriangulatedSurface::ChildType **begin(OGRTriangulatedSurface *poGeom)
    3812             : {
    3813           2 :     return poGeom->begin();
    3814             : }
    3815             : 
    3816             : /** @see OGRTriangulatedSurface::end() */
    3817           2 : inline OGRTriangulatedSurface::ChildType **end(OGRTriangulatedSurface *poGeom)
    3818             : {
    3819           2 :     return poGeom->end();
    3820             : }
    3821             : 
    3822             : //! @endcond
    3823             : 
    3824             : /************************************************************************/
    3825             : /*                            OGRMultiPoint                             */
    3826             : /************************************************************************/
    3827             : 
    3828             : /**
    3829             :  * A collection of OGRPoint.
    3830             :  */
    3831             : 
    3832         797 : class CPL_DLL OGRMultiPoint : public OGRGeometryCollection
    3833             : {
    3834             :   private:
    3835             :     OGRErr importFromWkt_Bracketed(const char **, int bHasM, int bHasZ);
    3836             : 
    3837             :   protected:
    3838             :     bool isCompatibleSubType(OGRwkbGeometryType) const override;
    3839             : 
    3840             :   public:
    3841             :     /** Create an empty multi point collection. */
    3842        5439 :     OGRMultiPoint() = default;
    3843             : 
    3844             :     OGRMultiPoint(const OGRMultiPoint &other);
    3845             :     /** Move constructor */
    3846           1 :     OGRMultiPoint(OGRMultiPoint &&other) = default;
    3847             : 
    3848             :     OGRMultiPoint &operator=(const OGRMultiPoint &other);
    3849             :     /** Move assignment operator */
    3850             :     OGRMultiPoint &operator=(OGRMultiPoint &&other) = default;
    3851             : 
    3852             :     /** C++ type of child elements. */
    3853             :     using ChildType = OGRPoint;
    3854             : 
    3855             :     /** 2D OGRwkbGeometryType constant. */
    3856             :     static constexpr OGRwkbGeometryType EnumType2D = wkbMultiPoint;
    3857             : 
    3858             :     /** C++ type for corresponding collection. */
    3859             :     using MultiType = OGRGeometryCollection;
    3860             : 
    3861             :     /** Return begin of iterator.
    3862             :      */
    3863         172 :     ChildType **begin()
    3864             :     {
    3865         172 :         return reinterpret_cast<ChildType **>(papoGeoms);
    3866             :     }
    3867             : 
    3868             :     /** Return end of iterator */
    3869         172 :     ChildType **end()
    3870             :     {
    3871         172 :         return reinterpret_cast<ChildType **>(papoGeoms + nGeomCount);
    3872             :     }
    3873             : 
    3874             :     /** Return begin of iterator.
    3875             :      */
    3876         416 :     const ChildType *const *begin() const
    3877             :     {
    3878         416 :         return reinterpret_cast<const ChildType *const *>(papoGeoms);
    3879             :     }
    3880             : 
    3881             :     /** Return end of iterator */
    3882         416 :     const ChildType *const *end() const
    3883             :     {
    3884         416 :         return reinterpret_cast<const ChildType *const *>(papoGeoms +
    3885         416 :                                                           nGeomCount);
    3886             :     }
    3887             : 
    3888             :     // IGeometryCollection
    3889             :     /** See OGRGeometryCollection::getGeometryRef() */
    3890        1014 :     OGRPoint *getGeometryRef(int i)
    3891             :     {
    3892        1014 :         return OGRGeometryCollection::getGeometryRef(i)->toPoint();
    3893             :     }
    3894             : 
    3895             :     /** See OGRGeometryCollection::getGeometryRef() */
    3896          56 :     const OGRPoint *getGeometryRef(int i) const
    3897             :     {
    3898          56 :         return OGRGeometryCollection::getGeometryRef(i)->toPoint();
    3899             :     }
    3900             : 
    3901             :     // Non-standard (OGRGeometry).
    3902             :     const char *getGeometryName() const override;
    3903             :     OGRwkbGeometryType getGeometryType() const override;
    3904             :     OGRMultiPoint *clone() const override;
    3905             : 
    3906             : #ifndef DOXYGEN_XML
    3907             :     using OGRGeometry::importFromWkt; /** deprecated */
    3908             : #endif
    3909             : 
    3910             :     OGRErr importFromWkt(const char **) override;
    3911             : 
    3912             : #ifndef DOXYGEN_XML
    3913             :     using OGRGeometry::exportToWkt;
    3914             : #endif
    3915             : 
    3916             :     /// Export a multipoint to WKT
    3917             :     /// \param opts  Output options.
    3918             :     /// \param err   Pointer to error code, if desired.
    3919             :     /// \return      WKT representation of the multipoint.
    3920             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    3921             :                                     OGRErr *err = nullptr) const override;
    3922             : 
    3923             :     // IGeometry methods.
    3924             :     int getDimension() const override;
    3925             : 
    3926             :     /** Return pointer of this in upper class */
    3927           1 :     inline OGRGeometryCollection *toUpperClass()
    3928             :     {
    3929           1 :         return this;
    3930             :     }
    3931             : 
    3932             :     /** Return pointer of this in upper class */
    3933          64 :     inline const OGRGeometryCollection *toUpperClass() const
    3934             :     {
    3935          64 :         return this;
    3936             :     }
    3937             : 
    3938           1 :     void accept(IOGRGeometryVisitor *visitor) override
    3939             :     {
    3940           1 :         visitor->visit(this);
    3941           1 :     }
    3942             : 
    3943          64 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    3944             :     {
    3945          64 :         visitor->visit(this);
    3946          64 :     }
    3947             : 
    3948             :     // Non-standard.
    3949             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    3950             : 
    3951             :     OGR_ALLOW_CAST_TO_THIS(MultiPoint)
    3952           1 :     OGR_ALLOW_UPCAST_TO(GeometryCollection)
    3953             :     OGR_FORBID_DOWNCAST_TO_MULTILINESTRING
    3954             :     OGR_FORBID_DOWNCAST_TO_MULTICURVE
    3955             :     OGR_FORBID_DOWNCAST_TO_MULTISURFACE
    3956             :     OGR_FORBID_DOWNCAST_TO_MULTIPOLYGON
    3957             : };
    3958             : 
    3959             : //! @cond Doxygen_Suppress
    3960             : /** @see OGRMultiPoint::begin() const */
    3961         329 : inline const OGRMultiPoint::ChildType *const *begin(const OGRMultiPoint *poGeom)
    3962             : {
    3963         329 :     return poGeom->begin();
    3964             : }
    3965             : 
    3966             : /** @see OGRMultiPoint::end() const */
    3967         329 : inline const OGRMultiPoint::ChildType *const *end(const OGRMultiPoint *poGeom)
    3968             : {
    3969         329 :     return poGeom->end();
    3970             : }
    3971             : 
    3972             : /** @see OGRMultiPoint::begin() */
    3973           2 : inline OGRMultiPoint::ChildType **begin(OGRMultiPoint *poGeom)
    3974             : {
    3975           2 :     return poGeom->begin();
    3976             : }
    3977             : 
    3978             : /** @see OGRMultiPoint::end() */
    3979           2 : inline OGRMultiPoint::ChildType **end(OGRMultiPoint *poGeom)
    3980             : {
    3981           2 :     return poGeom->end();
    3982             : }
    3983             : 
    3984             : //! @endcond
    3985             : 
    3986             : /************************************************************************/
    3987             : /*                            OGRMultiCurve                             */
    3988             : /************************************************************************/
    3989             : 
    3990             : /**
    3991             :  * A collection of OGRCurve.
    3992             :  *
    3993             :  */
    3994             : 
    3995        1039 : class CPL_DLL OGRMultiCurve : public OGRGeometryCollection
    3996             : {
    3997             :   protected:
    3998             :     //! @cond Doxygen_Suppress
    3999             :     static OGRErr addCurveDirectlyFromWkt(OGRGeometry *poSelf,
    4000             :                                           OGRCurve *poCurve);
    4001             :     //! @endcond
    4002             :     bool isCompatibleSubType(OGRwkbGeometryType) const override;
    4003             : 
    4004             :   public:
    4005             :     /** Create an empty multi curve collection. */
    4006       33538 :     OGRMultiCurve() = default;
    4007             : 
    4008             :     OGRMultiCurve(const OGRMultiCurve &other);
    4009             :     /** Move constructor */
    4010           2 :     OGRMultiCurve(OGRMultiCurve &&other) = default;
    4011             : 
    4012             :     OGRMultiCurve &operator=(const OGRMultiCurve &other);
    4013             :     /** Move assignment operator */
    4014             :     OGRMultiCurve &operator=(OGRMultiCurve &&other) = default;
    4015             : 
    4016             :     /** C++ type of child elements. */
    4017             :     using ChildType = OGRCurve;
    4018             : 
    4019             :     /** 2D OGRwkbGeometryType constant. */
    4020             :     static constexpr OGRwkbGeometryType EnumType2D = wkbMultiCurve;
    4021             : 
    4022             :     /** C++ type for corresponding collection. */
    4023             :     using MultiType = OGRGeometryCollection;
    4024             : 
    4025             :     /** Return begin of iterator.
    4026             :      */
    4027          64 :     ChildType **begin()
    4028             :     {
    4029          64 :         return reinterpret_cast<ChildType **>(papoGeoms);
    4030             :     }
    4031             : 
    4032             :     /** Return end of iterator */
    4033          64 :     ChildType **end()
    4034             :     {
    4035          64 :         return reinterpret_cast<ChildType **>(papoGeoms + nGeomCount);
    4036             :     }
    4037             : 
    4038             :     /** Return begin of iterator.
    4039             :      */
    4040          37 :     const ChildType *const *begin() const
    4041             :     {
    4042          37 :         return reinterpret_cast<const ChildType *const *>(papoGeoms);
    4043             :     }
    4044             : 
    4045             :     /** Return end of iterator */
    4046          37 :     const ChildType *const *end() const
    4047             :     {
    4048          37 :         return reinterpret_cast<const ChildType *const *>(papoGeoms +
    4049          37 :                                                           nGeomCount);
    4050             :     }
    4051             : 
    4052             :     // IGeometryCollection
    4053             :     /** See OGRGeometryCollection::getGeometryRef() */
    4054             :     OGRCurve *getGeometryRef(int i)
    4055             :     {
    4056             :         return OGRGeometryCollection::getGeometryRef(i)->toCurve();
    4057             :     }
    4058             : 
    4059             :     /** See OGRGeometryCollection::getGeometryRef() */
    4060             :     const OGRCurve *getGeometryRef(int i) const
    4061             :     {
    4062             :         return OGRGeometryCollection::getGeometryRef(i)->toCurve();
    4063             :     }
    4064             : 
    4065             :     // Non standard (OGRGeometry).
    4066             :     const char *getGeometryName() const override;
    4067             :     OGRwkbGeometryType getGeometryType() const override;
    4068             :     OGRMultiCurve *clone() const override;
    4069             : 
    4070             : #ifndef DOXYGEN_XML
    4071             :     using OGRGeometry::importFromWkt; /** deprecated */
    4072             : #endif
    4073             : 
    4074             :     OGRErr importFromWkt(const char **) override;
    4075             : 
    4076             : #ifndef DOXYGEN_XML
    4077             :     using OGRGeometry::exportToWkt;
    4078             : #endif
    4079             : 
    4080             :     /// Export a multicurve to WKT
    4081             :     /// \param opts  Output options.
    4082             :     /// \param err   Pointer to error code, if desired.
    4083             :     /// \return      WKT representation of the multicurve.
    4084             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    4085             :                                     OGRErr *err = nullptr) const override;
    4086             : 
    4087             :     // IGeometry methods.
    4088             :     int getDimension() const override;
    4089             : 
    4090             :     // Non-standard.
    4091             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    4092             : 
    4093             :     /** Return pointer of this in upper class */
    4094           1 :     inline OGRGeometryCollection *toUpperClass()
    4095             :     {
    4096           1 :         return this;
    4097             :     }
    4098             : 
    4099             :     /** Return pointer of this in upper class */
    4100           1 :     inline const OGRGeometryCollection *toUpperClass() const
    4101             :     {
    4102           1 :         return this;
    4103             :     }
    4104             : 
    4105           1 :     void accept(IOGRGeometryVisitor *visitor) override
    4106             :     {
    4107           1 :         visitor->visit(this);
    4108           1 :     }
    4109             : 
    4110           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    4111             :     {
    4112           1 :         visitor->visit(this);
    4113           1 :     }
    4114             : 
    4115             :     static OGRMultiLineString *CastToMultiLineString(OGRMultiCurve *poMC);
    4116             : 
    4117             :     OGR_ALLOW_CAST_TO_THIS(MultiCurve)
    4118           2 :     OGR_ALLOW_UPCAST_TO(GeometryCollection)
    4119             :     OGR_FORBID_DOWNCAST_TO_MULTIPOINT
    4120             :     OGR_FORBID_DOWNCAST_TO_MULTISURFACE
    4121             :     OGR_FORBID_DOWNCAST_TO_MULTIPOLYGON
    4122             : };
    4123             : 
    4124             : //! @cond Doxygen_Suppress
    4125             : /** @see OGRMultiCurve::begin() const */
    4126           2 : inline const OGRMultiCurve::ChildType *const *begin(const OGRMultiCurve *poGeom)
    4127             : {
    4128           2 :     return poGeom->begin();
    4129             : }
    4130             : 
    4131             : /** @see OGRMultiCurve::end() const */
    4132           2 : inline const OGRMultiCurve::ChildType *const *end(const OGRMultiCurve *poGeom)
    4133             : {
    4134           2 :     return poGeom->end();
    4135             : }
    4136             : 
    4137             : /** @see OGRMultiCurve::begin() */
    4138          21 : inline OGRMultiCurve::ChildType **begin(OGRMultiCurve *poGeom)
    4139             : {
    4140          21 :     return poGeom->begin();
    4141             : }
    4142             : 
    4143             : /** @see OGRMultiCurve::end() */
    4144          21 : inline OGRMultiCurve::ChildType **end(OGRMultiCurve *poGeom)
    4145             : {
    4146          21 :     return poGeom->end();
    4147             : }
    4148             : 
    4149             : //! @endcond
    4150             : 
    4151             : /************************************************************************/
    4152             : /*                          OGRMultiLineString                          */
    4153             : /************************************************************************/
    4154             : 
    4155             : /**
    4156             :  * A collection of OGRLineString.
    4157             :  */
    4158             : 
    4159         863 : class CPL_DLL OGRMultiLineString : public OGRMultiCurve
    4160             : {
    4161             :   protected:
    4162             :     bool isCompatibleSubType(OGRwkbGeometryType) const override;
    4163             : 
    4164             :   public:
    4165             :     /** Create an empty multi line string collection. */
    4166       32093 :     OGRMultiLineString() = default;
    4167             : 
    4168             :     OGRMultiLineString(const OGRMultiLineString &other);
    4169             :     /** Move constructor */
    4170           1 :     OGRMultiLineString(OGRMultiLineString &&other) = default;
    4171             : 
    4172             :     OGRMultiLineString &operator=(const OGRMultiLineString &other);
    4173             :     /** Move assignment operator */
    4174             :     OGRMultiLineString &operator=(OGRMultiLineString &&other) = default;
    4175             : 
    4176             :     /** C++ type of child elements. */
    4177             :     using ChildType = OGRLineString;
    4178             : 
    4179             :     /** 2D OGRwkbGeometryType constant. */
    4180             :     static constexpr OGRwkbGeometryType EnumType2D = wkbMultiLineString;
    4181             : 
    4182             :     /** C++ type for corresponding collection. */
    4183             :     using MultiType = OGRGeometryCollection;
    4184             : 
    4185             :     /** Return begin of iterator.
    4186             :      */
    4187         156 :     ChildType **begin()
    4188             :     {
    4189         156 :         return reinterpret_cast<ChildType **>(papoGeoms);
    4190             :     }
    4191             : 
    4192             :     /** Return end of iterator */
    4193         156 :     ChildType **end()
    4194             :     {
    4195         156 :         return reinterpret_cast<ChildType **>(papoGeoms + nGeomCount);
    4196             :     }
    4197             : 
    4198             :     /** Return begin of iterator.
    4199             :      */
    4200        8892 :     const ChildType *const *begin() const
    4201             :     {
    4202        8892 :         return reinterpret_cast<const ChildType *const *>(papoGeoms);
    4203             :     }
    4204             : 
    4205             :     /** Return end of iterator */
    4206        8892 :     const ChildType *const *end() const
    4207             :     {
    4208        8892 :         return reinterpret_cast<const ChildType *const *>(papoGeoms +
    4209        8892 :                                                           nGeomCount);
    4210             :     }
    4211             : 
    4212             :     // IGeometryCollection
    4213             :     /** See OGRGeometryCollection::getGeometryRef() */
    4214       26931 :     OGRLineString *getGeometryRef(int i)
    4215             :     {
    4216       26931 :         return OGRGeometryCollection::getGeometryRef(i)->toLineString();
    4217             :     }
    4218             : 
    4219             :     /** See OGRGeometryCollection::getGeometryRef() */
    4220          24 :     const OGRLineString *getGeometryRef(int i) const
    4221             :     {
    4222          24 :         return OGRGeometryCollection::getGeometryRef(i)->toLineString();
    4223             :     }
    4224             : 
    4225             :     // Non standard (OGRGeometry).
    4226             :     const char *getGeometryName() const override;
    4227             :     OGRwkbGeometryType getGeometryType() const override;
    4228             :     OGRMultiLineString *clone() const override;
    4229             : 
    4230             : #ifndef DOXYGEN_XML
    4231             :     using OGRGeometry::exportToWkt;
    4232             : #endif
    4233             : 
    4234             :     virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant,
    4235             :                                  size_t &nBytesConsumedOut) override;
    4236             : 
    4237             :     /// Export a multilinestring to WKT
    4238             :     /// \param opts  Output options.
    4239             :     /// \param err   Pointer to error code, if desired.
    4240             :     /// \return      WKT representation of the multilinestring.
    4241             :     virtual std::string exportToWkt(const OGRWktOptions &opts = OGRWktOptions(),
    4242             :                                     OGRErr *err = nullptr) const override;
    4243             : 
    4244             :     // Non standard
    4245             :     bool hasCurveGeometry(int bLookForNonLinear = FALSE) const override;
    4246             : 
    4247             :     /** Return pointer of this in upper class */
    4248           8 :     inline OGRGeometryCollection *toUpperClass()
    4249             :     {
    4250           8 :         return this;
    4251             :     }
    4252             : 
    4253             :     /** Return pointer of this in upper class */
    4254           1 :     inline const OGRGeometryCollection *toUpperClass() const
    4255             :     {
    4256           1 :         return this;
    4257             :     }
    4258             : 
    4259           8 :     void accept(IOGRGeometryVisitor *visitor) override
    4260             :     {
    4261           8 :         visitor->visit(this);
    4262           8 :     }
    4263             : 
    4264           1 :     void accept(IOGRConstGeometryVisitor *visitor) const override
    4265             :     {
    4266           1 :         visitor->visit(this);
    4267           1 :     }
    4268             : 
    4269             :     static OGRMultiCurve *CastToMultiCurve(OGRMultiLineString *poMLS);
    4270             : 
    4271             :     OGR_ALLOW_CAST_TO_THIS(MultiLineString)
    4272           1 :     OGR_ALLOW_UPCAST_TO(MultiCurve)
    4273             :     OGR_FORBID_DOWNCAST_TO_MULTIPOINT
    4274             :     OGR_FORBID_DOWNCAST_TO_MULTISURFACE
    4275             :     OGR_FORBID_DOWNCAST_TO_MULTIPOLYGON
    4276             : };
    4277             : 
    4278             : //! @cond Doxygen_Suppress
    4279             : /** @see OGRMultiLineString::begin() const */
    4280             : inline const OGRMultiLineString::ChildType *const *
    4281        8862 : begin(const OGRMultiLineString *poGeom)
    4282             : {
    4283        8862 :     return poGeom->begin();
    4284             : }
    4285             : 
    4286             : /** @see OGRMultiLineString::end() const */
    4287             : inline const OGRMultiLineString::ChildType *const *
    4288        8862 : end(const OGRMultiLineString *poGeom)
    4289             : {
    4290        8862 :     return poGeom->end();
    4291             : }
    4292             : 
    4293             : /** @see OGRMultiLineString::begin() */
    4294           2 : inline OGRMultiLineString::ChildType **begin(OGRMultiLineString *poGeom)
    4295             : {
    4296           2 :     return poGeom->begin();
    4297             : }
    4298             : 
    4299             : /** @see OGRMultiLineString::end() */
    4300           2 : inline OGRMultiLineString::ChildType **end(OGRMultiLineString *poGeom)
    4301             : {
    4302           2 :     return poGeom->end();
    4303             : }
    4304             : 
    4305             : //! @endcond
    4306             : 
    4307             : /************************************************************************/
    4308             : /*                          OGRGeometryFactory                          */
    4309             : /************************************************************************/
    4310             : 
    4311             : /**
    4312             :  * Create geometry objects from well known text/binary.
    4313             :  */
    4314             : 
    4315             : class CPL_DLL OGRGeometryFactory
    4316             : {
    4317             :     static OGRErr createFromFgfInternal(const unsigned char *pabyData,
    4318             :                                         OGRSpatialReference *poSR,
    4319             :                                         OGRGeometry **ppoReturn, int nBytes,
    4320             :                                         int *pnBytesConsumed, int nRecLevel);
    4321             : 
    4322             :   public:
    4323             :     static OGRErr createFromWkb(const void *, const OGRSpatialReference *,
    4324             :                                 OGRGeometry **,
    4325             :                                 size_t = static_cast<size_t>(-1),
    4326             :                                 OGRwkbVariant = wkbVariantOldOgc);
    4327             :     static OGRErr createFromWkb(const void *pabyData,
    4328             :                                 const OGRSpatialReference *, OGRGeometry **,
    4329             :                                 size_t nSize, OGRwkbVariant eVariant,
    4330             :                                 size_t &nBytesConsumedOut);
    4331             :     static OGRErr createFromWkt(const char *, const OGRSpatialReference *,
    4332             :                                 OGRGeometry **);
    4333             :     static OGRErr createFromWkt(const char **, const OGRSpatialReference *,
    4334             :                                 OGRGeometry **);
    4335             :     static std::pair<std::unique_ptr<OGRGeometry>, OGRErr>
    4336             :     createFromWkt(const char *, const OGRSpatialReference * = nullptr);
    4337             : 
    4338             :     /** Deprecated.
    4339             :      * @deprecated
    4340             :      */
    4341             :     static OGRErr createFromWkt(char **ppszInput,
    4342             :                                 const OGRSpatialReference *poSRS,
    4343             :                                 OGRGeometry **ppoGeom)
    4344             :         CPL_WARN_DEPRECATED("Use createFromWkt(const char**, ...) instead")
    4345             :     {
    4346             :         return createFromWkt(const_cast<const char **>(ppszInput), poSRS,
    4347             :                              ppoGeom);
    4348             :     }
    4349             : 
    4350             :     static OGRErr createFromFgf(const void *, OGRSpatialReference *,
    4351             :                                 OGRGeometry **, int = -1, int * = nullptr);
    4352             :     static OGRGeometry *createFromGML(const char *);
    4353             :     static OGRGeometry *createFromGEOS(GEOSContextHandle_t hGEOSCtxt, GEOSGeom);
    4354             :     static OGRGeometry *createFromGeoJson(const char *, int = -1);
    4355             :     static OGRGeometry *createFromGeoJson(const CPLJSONObject &oJSONObject);
    4356             : 
    4357             :     static void destroyGeometry(OGRGeometry *);
    4358             :     static OGRGeometry *createGeometry(OGRwkbGeometryType);
    4359             : 
    4360             :     static OGRGeometry *forceToPolygon(OGRGeometry *);
    4361             :     static OGRGeometry *forceToLineString(OGRGeometry *,
    4362             :                                           bool bOnlyInOrder = true);
    4363             :     static OGRGeometry *forceToMultiPolygon(OGRGeometry *);
    4364             :     static OGRGeometry *forceToMultiPoint(OGRGeometry *);
    4365             :     static OGRGeometry *forceToMultiLineString(OGRGeometry *);
    4366             : 
    4367             :     static OGRGeometry *forceTo(OGRGeometry *poGeom,
    4368             :                                 OGRwkbGeometryType eTargetType,
    4369             :                                 const char *const *papszOptions = nullptr)
    4370             : #ifndef DOXYGEN_SKIP
    4371             :         CPL_WARN_DEPRECATED("Use variant that accepts and returns a "
    4372             :                             "std::unique_ptr<OGRGeometry")
    4373             : #endif
    4374             :             ;
    4375             : 
    4376             :     static std::unique_ptr<OGRGeometry>
    4377             :     forceTo(std::unique_ptr<OGRGeometry> poGeom, OGRwkbGeometryType eTargetType,
    4378             :             const char *const *papszOptions = nullptr);
    4379             : 
    4380             :     static std::unique_ptr<OGRGeometry>
    4381             :     makeCompatibleWith(std::unique_ptr<OGRGeometry>,
    4382             :                        OGRwkbGeometryType eTargetType);
    4383             : 
    4384             :     static OGRGeometry *removeLowerDimensionSubGeoms(const OGRGeometry *poGeom);
    4385             : 
    4386             :     static std::unique_ptr<OGRGeometry>
    4387             :     organizePolygons(std::vector<std::unique_ptr<OGRGeometry>> &apoPolygons,
    4388             :                      bool *pbResultValidGeometry = nullptr,
    4389             :                      CSLConstList papszOptions = nullptr);
    4390             : 
    4391             :     static OGRGeometry *organizePolygons(OGRGeometry **papoPolygons,
    4392             :                                          int nPolygonCount,
    4393             :                                          int *pbResultValidGeometry,
    4394             :                                          CSLConstList papszOptions = nullptr)
    4395             : #ifndef DOXYGEN_SKIP
    4396             :         CPL_WARN_DEPRECATED("Use variant that accepts a "
    4397             :                             "std::vector<std::unique_ptr<OGRGeometry>>&")
    4398             : #endif
    4399             :             ;
    4400             : 
    4401             :     static bool haveGEOS();
    4402             : 
    4403             :     /** Opaque class used as argument to transformWithOptions() */
    4404             :     class CPL_DLL TransformWithOptionsCache
    4405             :     {
    4406             :         friend class OGRGeometryFactory;
    4407             :         struct Private;
    4408             :         std::unique_ptr<Private> d;
    4409             : 
    4410             :       public:
    4411             :         TransformWithOptionsCache();
    4412             :         ~TransformWithOptionsCache();
    4413             :     };
    4414             : 
    4415             :     //! @cond Doxygen_Suppress
    4416             :     static bool isTransformWithOptionsRegularTransform(
    4417             :         const OGRSpatialReference *poSourceCRS,
    4418             :         const OGRSpatialReference *poTargetCRS, CSLConstList papszOptions);
    4419             :     //! @endcond
    4420             : 
    4421             :     static OGRGeometry *transformWithOptions(
    4422             :         const OGRGeometry *poSrcGeom, OGRCoordinateTransformation *poCT,
    4423             :         CSLConstList papszOptions,
    4424             :         const TransformWithOptionsCache &cache = TransformWithOptionsCache());
    4425             : 
    4426             :     static double GetDefaultArcStepSize();
    4427             : 
    4428             :     static OGRGeometry *
    4429             :     approximateArcAngles(double dfX, double dfY, double dfZ,
    4430             :                          double dfPrimaryRadius, double dfSecondaryAxis,
    4431             :                          double dfRotation, double dfStartAngle,
    4432             :                          double dfEndAngle, double dfMaxAngleStepSizeDegrees,
    4433             :                          const bool bUseMaxGap = false);
    4434             : 
    4435             :     static int GetCurveParameters(double x0, double y0, double x1, double y1,
    4436             :                                   double x2, double y2, double &R, double &cx,
    4437             :                                   double &cy, double &alpha0, double &alpha1,
    4438             :                                   double &alpha2);
    4439             :     static OGRLineString *
    4440             :     curveToLineString(double x0, double y0, double z0, double x1, double y1,
    4441             :                       double z1, double x2, double y2, double z2, int bHasZ,
    4442             :                       double dfMaxAngleStepSizeDegrees,
    4443             :                       const char *const *papszOptions = nullptr);
    4444             :     static OGRCurve *
    4445             :     curveFromLineString(const OGRLineString *poLS,
    4446             :                         const char *const *papszOptions = nullptr);
    4447             : };
    4448             : 
    4449             : OGRwkbGeometryType CPL_DLL OGRFromOGCGeomType(const char *pszGeomType);
    4450             : const char CPL_DLL *OGRToOGCGeomType(OGRwkbGeometryType eGeomType,
    4451             :                                      bool bCamelCase = false,
    4452             :                                      bool bAddZM = false,
    4453             :                                      bool bSpaceBeforeZM = false);
    4454             : 
    4455             : //! @cond Doxygen_Suppress
    4456             : typedef struct _OGRPreparedGeometry OGRPreparedGeometry;
    4457             : 
    4458             : struct CPL_DLL OGRPreparedGeometryUniquePtrDeleter
    4459             : {
    4460             :     void operator()(OGRPreparedGeometry *) const;
    4461             : };
    4462             : 
    4463             : //! @endcond
    4464             : 
    4465             : /** Unique pointer type for OGRPreparedGeometry.
    4466             :  */
    4467             : typedef std::unique_ptr<OGRPreparedGeometry,
    4468             :                         OGRPreparedGeometryUniquePtrDeleter>
    4469             :     OGRPreparedGeometryUniquePtr;
    4470             : 
    4471             : #endif /* ndef OGR_GEOMETRY_H_INCLUDED */

Generated by: LCOV version 1.14