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

Generated by: LCOV version 1.14