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

Generated by: LCOV version 1.14