LCOV - code coverage report
Current view: top level - ogr - ogr_api.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 382 590 64.7 %
Date: 2024-05-03 15:49:35 Functions: 43 51 84.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  C API Functions that don't correspond one-to-one with C++
       5             :  *           methods, such as the "simplified" geometry access functions.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2002, Frank Warmerdam
      10             :  * Copyright (c) 2009-2011, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * Permission is hereby granted, free of charge, to any person obtaining a
      13             :  * copy of this software and associated documentation files (the "Software"),
      14             :  * to deal in the Software without restriction, including without limitation
      15             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16             :  * and/or sell copies of the Software, and to permit persons to whom the
      17             :  * Software is furnished to do so, subject to the following conditions:
      18             :  *
      19             :  * The above copyright notice and this permission notice shall be included
      20             :  * in all copies or substantial portions of the Software.
      21             :  *
      22             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28             :  * DEALINGS IN THE SOFTWARE.
      29             :  ****************************************************************************/
      30             : 
      31             : #include "cpl_port.h"
      32             : #include "ogr_api.h"
      33             : 
      34             : #include <cstddef>
      35             : 
      36             : #include "cpl_error.h"
      37             : #include "ogr_geometry.h"
      38             : #include "ogr_geos.h"
      39             : 
      40             : static bool bNonLinearGeometriesEnabled = true;
      41             : 
      42             : /************************************************************************/
      43             : /*                         OGRGetGEOSVersion()                          */
      44             : /************************************************************************/
      45             : 
      46             : /** \brief Get the GEOS version
      47             :  *
      48             :  * @param pnMajor Pointer to major version number, or NULL
      49             :  * @param pnMinor Pointer to minor version number, or NULL
      50             :  * @param pnPatch Pointer to patch version number, or NULL
      51             :  * @return TRUE if GDAL is built against GEOS
      52             :  * @since GDAL 3.4.0
      53             :  */
      54             : #ifdef HAVE_GEOS
      55        4226 : bool OGRGetGEOSVersion(int *pnMajor, int *pnMinor, int *pnPatch)
      56             : {
      57        4226 :     CPLStringList aosTokens(CSLTokenizeString2(GEOSversion(), ".", 0));
      58             : 
      59        4226 :     if (pnMajor && aosTokens.size() > 0)
      60        3820 :         *pnMajor = std::stoi(aosTokens[0]);
      61        4226 :     if (pnMinor && aosTokens.size() > 1)
      62         203 :         *pnMinor = std::stoi(aosTokens[1]);
      63        4226 :     if (pnPatch && aosTokens.size() > 2)
      64         203 :         *pnPatch = std::stoi(aosTokens[2]);
      65        8452 :     return TRUE;
      66             : }
      67             : #else
      68             : bool OGRGetGEOSVersion(int *pnMajor, int *pnMinor, int *pnPatch)
      69             : {
      70             :     if (pnMajor)
      71             :         *pnMajor = 0;
      72             :     if (pnMinor)
      73             :         *pnMinor = 0;
      74             :     if (pnPatch)
      75             :         *pnPatch = 0;
      76             :     return FALSE;
      77             : }
      78             : #endif
      79             : 
      80             : /************************************************************************/
      81             : /*                           ToPointer()                                */
      82             : /************************************************************************/
      83             : 
      84      936768 : static inline OGRGeometry *ToPointer(OGRGeometryH hGeom)
      85             : {
      86      936768 :     return OGRGeometry::FromHandle(hGeom);
      87             : }
      88             : 
      89             : /************************************************************************/
      90             : /*                           ToHandle()                                 */
      91             : /************************************************************************/
      92             : 
      93        9109 : static inline OGRGeometryH ToHandle(OGRGeometry *poGeom)
      94             : {
      95        9109 :     return OGRGeometry::ToHandle(poGeom);
      96             : }
      97             : 
      98             : /************************************************************************/
      99             : /*                        OGR_G_GetPointCount()                         */
     100             : /************************************************************************/
     101             : /**
     102             :  * \brief Fetch number of points from a Point or a LineString/LinearRing
     103             :  * geometry.
     104             :  *
     105             :  * Only wkbPoint[25D] or wkbLineString[25D] may return a valid value.
     106             :  * Other geometry types will silently return 0.
     107             :  *
     108             :  * @param hGeom handle to the geometry from which to get the number of points.
     109             :  * @return the number of points.
     110             :  */
     111             : 
     112       11715 : int OGR_G_GetPointCount(OGRGeometryH hGeom)
     113             : 
     114             : {
     115       11715 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetPointCount", 0);
     116             : 
     117             :     const OGRwkbGeometryType eGType =
     118       11715 :         wkbFlatten(ToPointer(hGeom)->getGeometryType());
     119       11715 :     if (eGType == wkbPoint)
     120             :     {
     121        1538 :         return 1;
     122             :     }
     123       10177 :     else if (OGR_GT_IsCurve(eGType))
     124             :     {
     125        6767 :         return ToPointer(hGeom)->toCurve()->getNumPoints();
     126             :     }
     127             :     else
     128             :     {
     129             :         // autotest/pymod/ogrtest.py calls this method on any geometry. So keep
     130             :         // silent.
     131             :         // CPLError(CE_Failure, CPLE_NotSupported,
     132             :         //          "Incompatible geometry for operation");
     133        3410 :         return 0;
     134             :     }
     135             : }
     136             : 
     137             : /************************************************************************/
     138             : /*                        OGR_G_SetPointCount()                         */
     139             : /************************************************************************/
     140             : /**
     141             :  * \brief Set number of points in a geometry.
     142             :  *
     143             :  * This method primary exists to preset the number of points in a linestring
     144             :  * geometry before setPoint() is used to assign them to avoid reallocating
     145             :  * the array larger with each call to addPoint().
     146             :  *
     147             :  * @param hGeom handle to the geometry.
     148             :  * @param nNewPointCount the new number of points for geometry.
     149             :  */
     150             : 
     151           0 : void OGR_G_SetPointCount(OGRGeometryH hGeom, int nNewPointCount)
     152             : 
     153             : {
     154           0 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPointCount");
     155             : 
     156           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     157             :     {
     158           0 :         case wkbLineString:
     159             :         case wkbCircularString:
     160             :         {
     161           0 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     162           0 :             poSC->setNumPoints(nNewPointCount);
     163           0 :             break;
     164             :         }
     165           0 :         default:
     166           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     167             :                      "Incompatible geometry for operation");
     168           0 :             break;
     169             :     }
     170             : }
     171             : 
     172             : /************************************************************************/
     173             : /*                        OGR_G_Get_Component()                         */
     174             : /************************************************************************/
     175             : template <typename Getter>
     176       86275 : static double OGR_G_Get_Component(OGRGeometryH hGeom, int i)
     177             : {
     178       86275 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     179             :     {
     180        3998 :         case wkbPoint:
     181             :         {
     182        3998 :             if (i == 0)
     183             :             {
     184        3995 :                 return Getter::get(ToPointer(hGeom)->toPoint());
     185             :             }
     186             :             else
     187             :             {
     188           3 :                 CPLError(CE_Failure, CPLE_NotSupported,
     189             :                          "Only i == 0 is supported");
     190           3 :                 return 0.0;
     191             :             }
     192             :         }
     193             : 
     194       82274 :         case wkbLineString:
     195             :         case wkbCircularString:
     196             :         {
     197       82274 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     198       82274 :             if (i < 0 || i >= poSC->getNumPoints())
     199             :             {
     200           3 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
     201           3 :                 return 0.0;
     202             :             }
     203       82271 :             return Getter::get(poSC, i);
     204             :         }
     205             : 
     206           3 :         default:
     207           3 :             CPLError(CE_Failure, CPLE_NotSupported,
     208             :                      "Incompatible geometry for operation");
     209           3 :             return 0.0;
     210             :     }
     211             : }
     212             : 
     213             : /************************************************************************/
     214             : /*                             OGR_G_GetX()                             */
     215             : /************************************************************************/
     216             : /**
     217             :  * \brief Fetch the x coordinate of a point from a Point or a
     218             :  * LineString/LinearRing geometry.
     219             :  *
     220             :  * @param hGeom handle to the geometry from which to get the x coordinate.
     221             :  * @param i point to get the x coordinate.
     222             :  * @return the X coordinate of this point.
     223             :  */
     224             : 
     225       35948 : double OGR_G_GetX(OGRGeometryH hGeom, int i)
     226             : 
     227             : {
     228       35948 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetX", 0);
     229             : 
     230             :     struct Getter
     231             :     {
     232        2197 :         static double get(const OGRPoint *poPoint)
     233             :         {
     234        2197 :             return poPoint->getX();
     235             :         }
     236             : 
     237       33748 :         static double get(const OGRSimpleCurve *poSC, int l_i)
     238             :         {
     239       33748 :             return poSC->getX(l_i);
     240             :         }
     241             :     };
     242             : 
     243       35948 :     return OGR_G_Get_Component<Getter>(hGeom, i);
     244             : }
     245             : 
     246             : /************************************************************************/
     247             : /*                             OGR_G_GetY()                             */
     248             : /************************************************************************/
     249             : /**
     250             :  * \brief Fetch the x coordinate of a point from a Point or a
     251             :  * LineString/LinearRing geometry.
     252             :  *
     253             :  * @param hGeom handle to the geometry from which to get the y coordinate.
     254             :  * @param i point to get the Y coordinate.
     255             :  * @return the Y coordinate of this point.
     256             :  */
     257             : 
     258       34738 : double OGR_G_GetY(OGRGeometryH hGeom, int i)
     259             : 
     260             : {
     261       34738 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetY", 0);
     262             : 
     263             :     struct Getter
     264             :     {
     265         987 :         static double get(const OGRPoint *poPoint)
     266             :         {
     267         987 :             return poPoint->getY();
     268             :         }
     269             : 
     270       33748 :         static double get(const OGRSimpleCurve *poSC, int l_i)
     271             :         {
     272       33748 :             return poSC->getY(l_i);
     273             :         }
     274             :     };
     275             : 
     276       34738 :     return OGR_G_Get_Component<Getter>(hGeom, i);
     277             : }
     278             : 
     279             : /************************************************************************/
     280             : /*                             OGR_G_GetZ()                             */
     281             : /************************************************************************/
     282             : /**
     283             :  * \brief Fetch the z coordinate of a point from a Point or a
     284             :  * LineString/LinearRing geometry.
     285             :  *
     286             :  * @param hGeom handle to the geometry from which to get the Z coordinate.
     287             :  * @param i point to get the Z coordinate.
     288             :  * @return the Z coordinate of this point.
     289             :  */
     290             : 
     291       13335 : double OGR_G_GetZ(OGRGeometryH hGeom, int i)
     292             : 
     293             : {
     294       13335 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetZ", 0);
     295             : 
     296             :     struct Getter
     297             :     {
     298         705 :         static double get(const OGRPoint *poPoint)
     299             :         {
     300         705 :             return poPoint->getZ();
     301             :         }
     302             : 
     303       12627 :         static double get(const OGRSimpleCurve *poSC, int l_i)
     304             :         {
     305       12627 :             return poSC->getZ(l_i);
     306             :         }
     307             :     };
     308             : 
     309       13335 :     return OGR_G_Get_Component<Getter>(hGeom, i);
     310             : }
     311             : 
     312             : /************************************************************************/
     313             : /*                             OGR_G_GetM()                             */
     314             : /************************************************************************/
     315             : /**
     316             :  * \brief Fetch the m coordinate of a point from a geometry.
     317             :  *
     318             :  * @param hGeom handle to the geometry from which to get the M coordinate.
     319             :  * @param i point to get the M coordinate.
     320             :  * @return the M coordinate of this point.
     321             :  */
     322             : 
     323        2254 : double OGR_G_GetM(OGRGeometryH hGeom, int i)
     324             : 
     325             : {
     326        2254 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetM", 0);
     327             : 
     328             :     struct Getter
     329             :     {
     330         106 :         static double get(const OGRPoint *poPoint)
     331             :         {
     332         106 :             return poPoint->getM();
     333             :         }
     334             : 
     335        2148 :         static double get(const OGRSimpleCurve *poSC, int l_i)
     336             :         {
     337        2148 :             return poSC->getM(l_i);
     338             :         }
     339             :     };
     340             : 
     341        2254 :     return OGR_G_Get_Component<Getter>(hGeom, i);
     342             : }
     343             : 
     344             : /************************************************************************/
     345             : /*                          OGR_G_GetPoints()                           */
     346             : /************************************************************************/
     347             : 
     348             : /**
     349             :  * \brief Returns all points of line string.
     350             :  *
     351             :  * This method copies all points into user arrays. The user provides the
     352             :  * stride between 2 consecutive elements of the array.
     353             :  *
     354             :  * On some CPU architectures, care must be taken so that the arrays are properly
     355             :  * aligned.
     356             :  *
     357             :  * @param hGeom handle to the geometry from which to get the coordinates.
     358             :  * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount)
     359             :  * bytes, may be NULL.
     360             :  * @param nXStride the number of bytes between 2 elements of pabyX.
     361             :  * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount)
     362             :  * bytes, may be NULL.
     363             :  * @param nYStride the number of bytes between 2 elements of pabyY.
     364             :  * @param pabyZ a buffer of at last size (sizeof(double) * nZStride *
     365             :  * nPointCount) bytes, may be NULL.
     366             :  * @param nZStride the number of bytes between 2 elements of pabyZ.
     367             :  *
     368             :  * @return the number of points
     369             :  *
     370             :  * @since OGR 1.9.0
     371             :  */
     372             : 
     373          15 : int OGR_G_GetPoints(OGRGeometryH hGeom, void *pabyX, int nXStride, void *pabyY,
     374             :                     int nYStride, void *pabyZ, int nZStride)
     375             : {
     376          15 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetPoints", 0);
     377             : 
     378          15 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     379             :     {
     380           4 :         case wkbPoint:
     381             :         {
     382           4 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     383           4 :             if (pabyX)
     384           4 :                 *(static_cast<double *>(pabyX)) = poPoint->getX();
     385           4 :             if (pabyY)
     386           4 :                 *(static_cast<double *>(pabyY)) = poPoint->getY();
     387           4 :             if (pabyZ)
     388           2 :                 *(static_cast<double *>(pabyZ)) = poPoint->getZ();
     389           4 :             return 1;
     390             :         }
     391             :         break;
     392             : 
     393          10 :         case wkbLineString:
     394             :         case wkbCircularString:
     395             :         {
     396          10 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     397          10 :             poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
     398          10 :             return poSC->getNumPoints();
     399             :         }
     400             :         break;
     401             : 
     402           1 :         default:
     403           1 :             CPLError(CE_Failure, CPLE_NotSupported,
     404             :                      "Incompatible geometry for operation");
     405           1 :             return 0;
     406             :             break;
     407             :     }
     408             : }
     409             : 
     410             : /************************************************************************/
     411             : /*                          OGR_G_GetPointsZM()                         */
     412             : /************************************************************************/
     413             : 
     414             : /**
     415             :  * \brief Returns all points of line string.
     416             :  *
     417             :  * This method copies all points into user arrays. The user provides the
     418             :  * stride between 2 consecutive elements of the array.
     419             :  *
     420             :  * On some CPU architectures, care must be taken so that the arrays are properly
     421             :  * aligned.
     422             :  *
     423             :  * @param hGeom handle to the geometry from which to get the coordinates.
     424             :  * @param pabyX a buffer of at least (nXStride * nPointCount)
     425             :  * bytes, may be NULL.
     426             :  * @param nXStride the number of bytes between 2 elements of pabyX.
     427             :  * @param pabyY a buffer of at least (nYStride * nPointCount)
     428             :  * bytes, may be NULL.
     429             :  * @param nYStride the number of bytes between 2 elements of pabyY.
     430             :  * @param pabyZ a buffer of at last size (nZStride *
     431             :  * nPointCount) bytes, may be NULL.
     432             :  * @param nZStride the number of bytes between 2 elements of pabyZ.
     433             :  * @param pabyM a buffer of at last size (nMStride *
     434             :  * nPointCount) bytes, may be NULL.
     435             :  * @param nMStride the number of bytes between 2 elements of pabyM.
     436             :  *
     437             :  * @return the number of points
     438             :  *
     439             :  * @since OGR 1.9.0
     440             :  */
     441             : 
     442           0 : int OGR_G_GetPointsZM(OGRGeometryH hGeom, void *pabyX, int nXStride,
     443             :                       void *pabyY, int nYStride, void *pabyZ, int nZStride,
     444             :                       void *pabyM, int nMStride)
     445             : {
     446           0 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetPointsZM", 0);
     447             : 
     448           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     449             :     {
     450           0 :         case wkbPoint:
     451             :         {
     452           0 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     453           0 :             if (pabyX)
     454           0 :                 *static_cast<double *>(pabyX) = poPoint->getX();
     455           0 :             if (pabyY)
     456           0 :                 *static_cast<double *>(pabyY) = poPoint->getY();
     457           0 :             if (pabyZ)
     458           0 :                 *static_cast<double *>(pabyZ) = poPoint->getZ();
     459           0 :             if (pabyM)
     460           0 :                 *static_cast<double *>(pabyM) = poPoint->getM();
     461           0 :             return 1;
     462             :         }
     463             :         break;
     464             : 
     465           0 :         case wkbLineString:
     466             :         case wkbCircularString:
     467             :         {
     468           0 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     469           0 :             poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride,
     470             :                             pabyM, nMStride);
     471           0 :             return poSC->getNumPoints();
     472             :         }
     473             :         break;
     474             : 
     475           0 :         default:
     476           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     477             :                      "Incompatible geometry for operation");
     478           0 :             return 0;
     479             :             break;
     480             :     }
     481             : }
     482             : 
     483             : /************************************************************************/
     484             : /*                           OGR_G_GetPoint()                           */
     485             : /************************************************************************/
     486             : 
     487             : /**
     488             :  * \brief Fetch a point in line string or a point geometry.
     489             :  *
     490             :  * @param hGeom handle to the geometry from which to get the coordinates.
     491             :  * @param i the vertex to fetch, from 0 to getNumPoints()-1, zero for a point.
     492             :  * @param pdfX value of x coordinate.
     493             :  * @param pdfY value of y coordinate.
     494             :  * @param pdfZ value of z coordinate.
     495             :  */
     496             : 
     497         756 : void OGR_G_GetPoint(OGRGeometryH hGeom, int i, double *pdfX, double *pdfY,
     498             :                     double *pdfZ)
     499             : 
     500             : {
     501         756 :     VALIDATE_POINTER0(hGeom, "OGR_G_GetPoint");
     502             : 
     503         756 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     504             :     {
     505          21 :         case wkbPoint:
     506             :         {
     507          21 :             if (i == 0)
     508             :             {
     509          20 :                 OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     510          20 :                 *pdfX = poPoint->getX();
     511          20 :                 *pdfY = poPoint->getY();
     512          20 :                 if (pdfZ != nullptr)
     513          20 :                     *pdfZ = poPoint->getZ();
     514             :             }
     515             :             else
     516             :             {
     517           1 :                 CPLError(CE_Failure, CPLE_NotSupported,
     518             :                          "Only i == 0 is supported");
     519             :             }
     520             :         }
     521          21 :         break;
     522             : 
     523         734 :         case wkbLineString:
     524             :         case wkbCircularString:
     525             :         {
     526         734 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     527         734 :             if (i < 0 || i >= poSC->getNumPoints())
     528             :             {
     529           5 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
     530           5 :                 *pdfX = 0.0;
     531           5 :                 *pdfY = 0.0;
     532           5 :                 if (pdfZ != nullptr)
     533           3 :                     *pdfZ = 0.0;
     534             :             }
     535             :             else
     536             :             {
     537         729 :                 *pdfX = poSC->getX(i);
     538         729 :                 *pdfY = poSC->getY(i);
     539         729 :                 if (pdfZ != nullptr)
     540         728 :                     *pdfZ = poSC->getZ(i);
     541             :             }
     542             :         }
     543         734 :         break;
     544             : 
     545           1 :         default:
     546           1 :             CPLError(CE_Failure, CPLE_NotSupported,
     547             :                      "Incompatible geometry for operation");
     548           1 :             break;
     549             :     }
     550             : }
     551             : 
     552             : /************************************************************************/
     553             : /*                           OGR_G_GetPointZM()                         */
     554             : /************************************************************************/
     555             : 
     556             : /**
     557             :  * \brief Fetch a point in line string or a point geometry.
     558             :  *
     559             :  * @param hGeom handle to the geometry from which to get the coordinates.
     560             :  * @param i the vertex to fetch, from 0 to getNumPoints()-1, zero for a point.
     561             :  * @param pdfX value of x coordinate.
     562             :  * @param pdfY value of y coordinate.
     563             :  * @param pdfZ value of z coordinate.
     564             :  * @param pdfM value of m coordinate.
     565             :  */
     566             : 
     567           1 : void OGR_G_GetPointZM(OGRGeometryH hGeom, int i, double *pdfX, double *pdfY,
     568             :                       double *pdfZ, double *pdfM)
     569             : 
     570             : {
     571           1 :     VALIDATE_POINTER0(hGeom, "OGR_G_GetPointZM");
     572             : 
     573           1 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     574             :     {
     575           1 :         case wkbPoint:
     576             :         {
     577           1 :             if (i == 0)
     578             :             {
     579           1 :                 OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     580           1 :                 *pdfX = poPoint->getX();
     581           1 :                 *pdfY = poPoint->getY();
     582           1 :                 if (pdfZ != nullptr)
     583           1 :                     *pdfZ = poPoint->getZ();
     584           1 :                 if (pdfM != nullptr)
     585           1 :                     *pdfM = poPoint->getM();
     586             :             }
     587             :             else
     588             :             {
     589           0 :                 CPLError(CE_Failure, CPLE_NotSupported,
     590             :                          "Only i == 0 is supported");
     591             :             }
     592             :         }
     593           1 :         break;
     594             : 
     595           0 :         case wkbLineString:
     596             :         case wkbCircularString:
     597             :         {
     598           0 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     599           0 :             if (i < 0 || i >= poSC->getNumPoints())
     600             :             {
     601           0 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
     602           0 :                 *pdfX = 0.0;
     603           0 :                 *pdfY = 0.0;
     604           0 :                 if (pdfZ != nullptr)
     605           0 :                     *pdfZ = 0.0;
     606           0 :                 if (pdfM != nullptr)
     607           0 :                     *pdfM = 0.0;
     608             :             }
     609             :             else
     610             :             {
     611           0 :                 *pdfX = poSC->getX(i);
     612           0 :                 *pdfY = poSC->getY(i);
     613           0 :                 if (pdfZ != nullptr)
     614           0 :                     *pdfZ = poSC->getZ(i);
     615           0 :                 if (pdfM != nullptr)
     616           0 :                     *pdfM = poSC->getM(i);
     617             :             }
     618             :         }
     619           0 :         break;
     620             : 
     621           0 :         default:
     622           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     623             :                      "Incompatible geometry for operation");
     624           0 :             break;
     625             :     }
     626             : }
     627             : 
     628             : /************************************************************************/
     629             : /*                           OGR_G_SetPoints()                          */
     630             : /************************************************************************/
     631             : /**
     632             :  * \brief Assign all points in a point or a line string geometry.
     633             :  *
     634             :  * This method clear any existing points assigned to this geometry,
     635             :  * and assigns a whole new set.
     636             :  *
     637             :  * @param hGeom handle to the geometry to set the coordinates.
     638             :  * @param nPointsIn number of points being passed in padfX and padfY.
     639             :  * @param pabyX list of X coordinates (double values) of points being assigned.
     640             :  * @param nXStride the number of bytes between 2 elements of pabyX.
     641             :  * @param pabyY list of Y coordinates (double values) of points being assigned.
     642             :  * @param nYStride the number of bytes between 2 elements of pabyY.
     643             :  * @param pabyZ list of Z coordinates (double values) of points being assigned
     644             :  * (defaults to NULL for 2D objects).
     645             :  * @param nZStride the number of bytes between 2 elements of pabyZ.
     646             :  */
     647             : 
     648           9 : void CPL_DLL OGR_G_SetPoints(OGRGeometryH hGeom, int nPointsIn,
     649             :                              const void *pabyX, int nXStride, const void *pabyY,
     650             :                              int nYStride, const void *pabyZ, int nZStride)
     651             : 
     652             : {
     653           9 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPoints");
     654             : 
     655           9 :     if (pabyX == nullptr || pabyY == nullptr)
     656             :     {
     657           2 :         CPLError(CE_Failure, CPLE_NotSupported,
     658             :                  "pabyX == NULL || pabyY == NULL");
     659           2 :         return;
     660             :     }
     661             : 
     662           7 :     const double *const padfX = static_cast<const double *>(pabyX);
     663           7 :     const double *const padfY = static_cast<const double *>(pabyY);
     664           7 :     const double *const padfZ = static_cast<const double *>(pabyZ);
     665             : 
     666           7 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     667             :     {
     668           2 :         case wkbPoint:
     669             :         {
     670           2 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     671           2 :             poPoint->setX(*padfX);
     672           2 :             poPoint->setY(*padfY);
     673           2 :             if (pabyZ != nullptr)
     674           1 :                 poPoint->setZ(*(padfZ));
     675           2 :             break;
     676             :         }
     677           5 :         case wkbLineString:
     678             :         case wkbCircularString:
     679             :         {
     680           5 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     681             : 
     682           5 :             const int nSizeDouble = static_cast<int>(sizeof(double));
     683           5 :             if (nXStride == nSizeDouble && nYStride == nSizeDouble &&
     684           2 :                 ((nZStride == 0 && pabyZ == nullptr) ||
     685           1 :                  (nZStride == nSizeDouble && pabyZ != nullptr)))
     686             :             {
     687           2 :                 poSC->setPoints(nPointsIn, padfX, padfY, padfZ);
     688             :             }
     689             :             else
     690             :             {
     691           3 :                 poSC->setNumPoints(nPointsIn);
     692             : 
     693             :                 // TODO(schwehr): Create pasX and pasY.
     694           6 :                 for (int i = 0; i < nPointsIn; ++i)
     695             :                 {
     696           3 :                     const double x = *reinterpret_cast<const double *>(
     697           3 :                         static_cast<const char *>(pabyX) + i * nXStride);
     698           3 :                     const double y = *reinterpret_cast<const double *>(
     699           3 :                         static_cast<const char *>(pabyY) + i * nYStride);
     700           3 :                     if (pabyZ)
     701             :                     {
     702           1 :                         const double z = *reinterpret_cast<const double *>(
     703           1 :                             static_cast<const char *>(pabyZ) + i * nZStride);
     704           1 :                         poSC->setPoint(i, x, y, z);
     705             :                     }
     706             :                     else
     707             :                     {
     708           2 :                         poSC->setPoint(i, x, y);
     709             :                     }
     710             :                 }
     711             :             }
     712           5 :             break;
     713             :         }
     714           0 :         default:
     715           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     716             :                      "Incompatible geometry for operation");
     717           0 :             break;
     718             :     }
     719             : }
     720             : 
     721             : /************************************************************************/
     722             : /*                           OGR_G_SetPointsZM()                        */
     723             : /************************************************************************/
     724             : /**
     725             :  * \brief Assign all points in a point or a line string geometry.
     726             :  *
     727             :  * This method clear any existing points assigned to this geometry,
     728             :  * and assigns a whole new set.
     729             :  *
     730             :  * @param hGeom handle to the geometry to set the coordinates.
     731             :  * @param nPointsIn number of points being passed in padfX and padfY.
     732             :  * @param pX list of X coordinates (double values) of points being assigned.
     733             :  * @param nXStride the number of bytes between 2 elements of pX.
     734             :  * @param pY list of Y coordinates (double values) of points being assigned.
     735             :  * @param nYStride the number of bytes between 2 elements of pY.
     736             :  * @param pZ list of Z coordinates (double values) of points being assigned
     737             :  * (if not NULL, upgrades the geometry to have Z coordinate).
     738             :  * @param nZStride the number of bytes between 2 elements of pZ.
     739             :  * @param pM list of M coordinates (double values) of points being assigned
     740             :  * (if not NULL, upgrades the geometry to have M coordinate).
     741             :  * @param nMStride the number of bytes between 2 elements of pM.
     742             :  */
     743             : 
     744           0 : void CPL_DLL OGR_G_SetPointsZM(OGRGeometryH hGeom, int nPointsIn,
     745             :                                const void *pX, int nXStride, const void *pY,
     746             :                                int nYStride, const void *pZ, int nZStride,
     747             :                                const void *pM, int nMStride)
     748             : 
     749             : {
     750           0 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPointsZM");
     751             : 
     752           0 :     if (pX == nullptr || pY == nullptr)
     753             :     {
     754           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     755             :                  "pabyX == NULL || pabyY == NULL");
     756           0 :         return;
     757             :     }
     758             : 
     759           0 :     const double *const padfX = static_cast<const double *>(pX);
     760           0 :     const double *const padfY = static_cast<const double *>(pY);
     761           0 :     const double *const padfZ = static_cast<const double *>(pZ);
     762           0 :     const double *const padfM = static_cast<const double *>(pM);
     763           0 :     const char *const pabyX = static_cast<const char *>(pX);
     764           0 :     const char *const pabyY = static_cast<const char *>(pY);
     765           0 :     const char *const pabyZ = static_cast<const char *>(pZ);
     766           0 :     const char *const pabyM = static_cast<const char *>(pM);
     767             : 
     768           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     769             :     {
     770           0 :         case wkbPoint:
     771             :         {
     772           0 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     773           0 :             poPoint->setX(*padfX);
     774           0 :             poPoint->setY(*padfY);
     775           0 :             if (pabyZ)
     776           0 :                 poPoint->setZ(*padfZ);
     777           0 :             if (pabyM)
     778           0 :                 poPoint->setM(*padfM);
     779           0 :             break;
     780             :         }
     781           0 :         case wkbLineString:
     782             :         case wkbCircularString:
     783             :         {
     784           0 :             OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
     785             : 
     786           0 :             const int nSizeDouble = static_cast<int>(sizeof(double));
     787           0 :             if (nXStride == nSizeDouble && nYStride == nSizeDouble &&
     788           0 :                 ((nZStride == 0 && padfZ == nullptr) ||
     789           0 :                  (nZStride == nSizeDouble && padfZ != nullptr)) &&
     790           0 :                 ((nMStride == 0 && padfM == nullptr) ||
     791           0 :                  (nMStride == nSizeDouble && padfM != nullptr)))
     792             :             {
     793           0 :                 if (!padfZ && !padfM)
     794           0 :                     poSC->setPoints(nPointsIn, padfX, padfY);
     795           0 :                 else if (pabyZ && !pabyM)
     796           0 :                     poSC->setPoints(nPointsIn, padfX, padfY, padfZ);
     797           0 :                 else if (!pabyZ && pabyM)
     798           0 :                     poSC->setPointsM(nPointsIn, padfX, padfY, padfM);
     799             :                 else
     800           0 :                     poSC->setPoints(nPointsIn, padfX, padfY, padfZ, padfM);
     801             :             }
     802             :             else
     803             :             {
     804           0 :                 poSC->setNumPoints(nPointsIn);
     805             : 
     806           0 :                 if (!pabyM)
     807             :                 {
     808           0 :                     if (!pabyZ)
     809             :                     {
     810           0 :                         for (int i = 0; i < nPointsIn; ++i)
     811             :                         {
     812           0 :                             const double x = *reinterpret_cast<const double *>(
     813           0 :                                 pabyX + i * nXStride);
     814           0 :                             const double y = *reinterpret_cast<const double *>(
     815           0 :                                 pabyY + i * nYStride);
     816           0 :                             poSC->setPoint(i, x, y);
     817             :                         }
     818             :                     }
     819             :                     else
     820             :                     {
     821           0 :                         for (int i = 0; i < nPointsIn; ++i)
     822             :                         {
     823           0 :                             const double x = *reinterpret_cast<const double *>(
     824           0 :                                 pabyX + i * nXStride);
     825           0 :                             const double y = *reinterpret_cast<const double *>(
     826           0 :                                 pabyY + i * nYStride);
     827           0 :                             const double z = *reinterpret_cast<const double *>(
     828           0 :                                 pabyZ + i * nZStride);
     829           0 :                             poSC->setPoint(i, x, y, z);
     830             :                         }
     831             :                     }
     832             :                 }
     833             :                 else
     834             :                 {
     835           0 :                     if (!pabyZ)
     836             :                     {
     837           0 :                         for (int i = 0; i < nPointsIn; ++i)
     838             :                         {
     839           0 :                             const double x = *reinterpret_cast<const double *>(
     840           0 :                                 pabyX + i * nXStride);
     841           0 :                             const double y = *reinterpret_cast<const double *>(
     842           0 :                                 pabyY + i * nYStride);
     843           0 :                             const double m = *reinterpret_cast<const double *>(
     844           0 :                                 pabyM + i * nMStride);
     845           0 :                             poSC->setPointM(i, x, y, m);
     846             :                         }
     847             :                     }
     848             :                     else
     849             :                     {
     850           0 :                         for (int i = 0; i < nPointsIn; ++i)
     851             :                         {
     852           0 :                             const double x = *reinterpret_cast<const double *>(
     853           0 :                                 pabyX + i * nXStride);
     854           0 :                             const double y = *reinterpret_cast<const double *>(
     855           0 :                                 pabyY + i * nYStride);
     856           0 :                             const double z = *reinterpret_cast<const double *>(
     857           0 :                                 pabyZ + i * nZStride);
     858           0 :                             const double m = *reinterpret_cast<const double *>(
     859           0 :                                 pabyM + i * nMStride);
     860           0 :                             poSC->setPoint(i, x, y, z, m);
     861             :                         }
     862             :                     }
     863             :                 }
     864             :             }
     865           0 :             break;
     866             :         }
     867           0 :         default:
     868           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     869             :                      "Incompatible geometry for operation");
     870           0 :             break;
     871             :     }
     872             : }
     873             : 
     874             : /************************************************************************/
     875             : /*                           OGR_G_SetPoint()                           */
     876             : /************************************************************************/
     877             : /**
     878             :  * \brief Set the location of a vertex in a point or linestring geometry.
     879             :  *
     880             :  * If iPoint is larger than the number of existing
     881             :  * points in the linestring, the point count will be increased to
     882             :  * accommodate the request.
     883             :  *
     884             :  * @param hGeom handle to the geometry to add a vertex to.
     885             :  * @param i the index of the vertex to assign (zero based) or
     886             :  *  zero for a point.
     887             :  * @param dfX input X coordinate to assign.
     888             :  * @param dfY input Y coordinate to assign.
     889             :  * @param dfZ input Z coordinate to assign (defaults to zero).
     890             :  */
     891             : 
     892       49903 : void OGR_G_SetPoint(OGRGeometryH hGeom, int i, double dfX, double dfY,
     893             :                     double dfZ)
     894             : 
     895             : {
     896       49903 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPoint");
     897             : 
     898       49903 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     899             :     {
     900         164 :         case wkbPoint:
     901             :         {
     902         164 :             if (i == 0)
     903             :             {
     904         163 :                 OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     905         163 :                 poPoint->setX(dfX);
     906         163 :                 poPoint->setY(dfY);
     907         163 :                 poPoint->setZ(dfZ);
     908             :             }
     909             :             else
     910             :             {
     911           1 :                 CPLError(CE_Failure, CPLE_NotSupported,
     912             :                          "Only i == 0 is supported");
     913             :             }
     914             :         }
     915         164 :         break;
     916             : 
     917       49738 :         case wkbLineString:
     918             :         case wkbCircularString:
     919             :         {
     920       49738 :             if (i < 0)
     921             :             {
     922           2 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
     923           2 :                 return;
     924             :             }
     925       49736 :             ToPointer(hGeom)->toSimpleCurve()->setPoint(i, dfX, dfY, dfZ);
     926       49736 :             break;
     927             :         }
     928             : 
     929           1 :         default:
     930           1 :             CPLError(CE_Failure, CPLE_NotSupported,
     931             :                      "Incompatible geometry for operation");
     932           1 :             break;
     933             :     }
     934             : }
     935             : 
     936             : /************************************************************************/
     937             : /*                         OGR_G_SetPoint_2D()                          */
     938             : /************************************************************************/
     939             : /**
     940             :  * \brief Set the location of a vertex in a point or linestring geometry.
     941             :  *
     942             :  * If iPoint is larger than the number of existing
     943             :  * points in the linestring, the point count will be increased to
     944             :  * accommodate the request.
     945             :  *
     946             :  * @param hGeom handle to the geometry to add a vertex to.
     947             :  * @param i the index of the vertex to assign (zero based) or
     948             :  *  zero for a point.
     949             :  * @param dfX input X coordinate to assign.
     950             :  * @param dfY input Y coordinate to assign.
     951             :  */
     952             : 
     953      229247 : void OGR_G_SetPoint_2D(OGRGeometryH hGeom, int i, double dfX, double dfY)
     954             : 
     955             : {
     956      229247 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPoint_2D");
     957             : 
     958      229247 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
     959             :     {
     960      160001 :         case wkbPoint:
     961             :         {
     962      160001 :             if (i == 0)
     963             :             {
     964      160000 :                 OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
     965      160000 :                 poPoint->setX(dfX);
     966      160000 :                 poPoint->setY(dfY);
     967             :             }
     968             :             else
     969             :             {
     970           1 :                 CPLError(CE_Failure, CPLE_NotSupported,
     971             :                          "Only i == 0 is supported");
     972             :             }
     973             :         }
     974      160001 :         break;
     975             : 
     976       69245 :         case wkbLineString:
     977             :         case wkbCircularString:
     978             :         {
     979       69245 :             if (i < 0)
     980             :             {
     981           2 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
     982           2 :                 return;
     983             :             }
     984       69243 :             ToPointer(hGeom)->toSimpleCurve()->setPoint(i, dfX, dfY);
     985       69243 :             break;
     986             :         }
     987             : 
     988           1 :         default:
     989           1 :             CPLError(CE_Failure, CPLE_NotSupported,
     990             :                      "Incompatible geometry for operation");
     991           1 :             break;
     992             :     }
     993             : }
     994             : 
     995             : /************************************************************************/
     996             : /*                           OGR_G_SetPointM()                          */
     997             : /************************************************************************/
     998             : /**
     999             :  * \brief Set the location of a vertex in a point or linestring geometry.
    1000             :  *
    1001             :  * If iPoint is larger than the number of existing
    1002             :  * points in the linestring, the point count will be increased to
    1003             :  * accommodate the request.
    1004             :  *
    1005             :  * @param hGeom handle to the geometry to add a vertex to.
    1006             :  * @param i the index of the vertex to assign (zero based) or
    1007             :  *  zero for a point.
    1008             :  * @param dfX input X coordinate to assign.
    1009             :  * @param dfY input Y coordinate to assign.
    1010             :  * @param dfM input M coordinate to assign.
    1011             :  */
    1012             : 
    1013           0 : void OGR_G_SetPointM(OGRGeometryH hGeom, int i, double dfX, double dfY,
    1014             :                      double dfM)
    1015             : 
    1016             : {
    1017           0 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPointM");
    1018             : 
    1019           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
    1020             :     {
    1021           0 :         case wkbPoint:
    1022             :         {
    1023           0 :             if (i == 0)
    1024             :             {
    1025           0 :                 OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
    1026           0 :                 poPoint->setX(dfX);
    1027           0 :                 poPoint->setY(dfY);
    1028           0 :                 poPoint->setM(dfM);
    1029             :             }
    1030             :             else
    1031             :             {
    1032           0 :                 CPLError(CE_Failure, CPLE_NotSupported,
    1033             :                          "Only i == 0 is supported");
    1034             :             }
    1035             :         }
    1036           0 :         break;
    1037             : 
    1038           0 :         case wkbLineString:
    1039             :         case wkbCircularString:
    1040             :         {
    1041           0 :             if (i < 0)
    1042             :             {
    1043           0 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
    1044           0 :                 return;
    1045             :             }
    1046           0 :             ToPointer(hGeom)->toSimpleCurve()->setPointM(i, dfX, dfY, dfM);
    1047           0 :             break;
    1048             :         }
    1049             : 
    1050           0 :         default:
    1051           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    1052             :                      "Incompatible geometry for operation");
    1053           0 :             break;
    1054             :     }
    1055             : }
    1056             : 
    1057             : /************************************************************************/
    1058             : /*                           OGR_G_SetPointZM()                         */
    1059             : /************************************************************************/
    1060             : /**
    1061             :  * \brief Set the location of a vertex in a point or linestring geometry.
    1062             :  *
    1063             :  * If iPoint is larger than the number of existing
    1064             :  * points in the linestring, the point count will be increased to
    1065             :  * accommodate the request.
    1066             :  *
    1067             :  * @param hGeom handle to the geometry to add a vertex to.
    1068             :  * @param i the index of the vertex to assign (zero based) or
    1069             :  *  zero for a point.
    1070             :  * @param dfX input X coordinate to assign.
    1071             :  * @param dfY input Y coordinate to assign.
    1072             :  * @param dfZ input Z coordinate to assign.
    1073             :  * @param dfM input M coordinate to assign.
    1074             :  */
    1075             : 
    1076           0 : void OGR_G_SetPointZM(OGRGeometryH hGeom, int i, double dfX, double dfY,
    1077             :                       double dfZ, double dfM)
    1078             : 
    1079             : {
    1080           0 :     VALIDATE_POINTER0(hGeom, "OGR_G_SetPointZM");
    1081             : 
    1082           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
    1083             :     {
    1084           0 :         case wkbPoint:
    1085             :         {
    1086           0 :             if (i == 0)
    1087             :             {
    1088           0 :                 OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
    1089           0 :                 poPoint->setX(dfX);
    1090           0 :                 poPoint->setY(dfY);
    1091           0 :                 poPoint->setZ(dfZ);
    1092           0 :                 poPoint->setM(dfM);
    1093             :             }
    1094             :             else
    1095             :             {
    1096           0 :                 CPLError(CE_Failure, CPLE_NotSupported,
    1097             :                          "Only i == 0 is supported");
    1098             :             }
    1099             :         }
    1100           0 :         break;
    1101             : 
    1102           0 :         case wkbLineString:
    1103             :         case wkbCircularString:
    1104             :         {
    1105           0 :             if (i < 0)
    1106             :             {
    1107           0 :                 CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
    1108           0 :                 return;
    1109             :             }
    1110           0 :             ToPointer(hGeom)->toSimpleCurve()->setPoint(i, dfX, dfY, dfZ, dfM);
    1111           0 :             break;
    1112             :         }
    1113             : 
    1114           0 :         default:
    1115           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    1116             :                      "Incompatible geometry for operation");
    1117           0 :             break;
    1118             :     }
    1119             : }
    1120             : 
    1121             : /************************************************************************/
    1122             : /*                           OGR_G_AddPoint()                           */
    1123             : /************************************************************************/
    1124             : /**
    1125             :  * \brief Add a point to a geometry (line string or point).
    1126             :  *
    1127             :  * The vertex count of the line string is increased by one, and assigned from
    1128             :  * the passed location value.
    1129             :  *
    1130             :  * @param hGeom handle to the geometry to add a point to.
    1131             :  * @param dfX x coordinate of point to add.
    1132             :  * @param dfY y coordinate of point to add.
    1133             :  * @param dfZ z coordinate of point to add.
    1134             :  */
    1135             : 
    1136         254 : void OGR_G_AddPoint(OGRGeometryH hGeom, double dfX, double dfY, double dfZ)
    1137             : 
    1138             : {
    1139         254 :     VALIDATE_POINTER0(hGeom, "OGR_G_AddPoint");
    1140             : 
    1141         254 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
    1142             :     {
    1143           4 :         case wkbPoint:
    1144             :         {
    1145           4 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
    1146           4 :             poPoint->setX(dfX);
    1147           4 :             poPoint->setY(dfY);
    1148           4 :             poPoint->setZ(dfZ);
    1149             :         }
    1150           4 :         break;
    1151             : 
    1152         249 :         case wkbLineString:
    1153             :         case wkbCircularString:
    1154         249 :             ToPointer(hGeom)->toSimpleCurve()->addPoint(dfX, dfY, dfZ);
    1155         249 :             break;
    1156             : 
    1157           1 :         default:
    1158           1 :             CPLError(CE_Failure, CPLE_NotSupported,
    1159             :                      "Incompatible geometry for operation");
    1160           1 :             break;
    1161             :     }
    1162             : }
    1163             : 
    1164             : /************************************************************************/
    1165             : /*                           OGR_G_AddPoint_2D()                        */
    1166             : /************************************************************************/
    1167             : /**
    1168             :  * \brief Add a point to a geometry (line string or point).
    1169             :  *
    1170             :  * The vertex count of the line string is increased by one, and assigned from
    1171             :  * the passed location value.
    1172             :  *
    1173             :  * @param hGeom handle to the geometry to add a point to.
    1174             :  * @param dfX x coordinate of point to add.
    1175             :  * @param dfY y coordinate of point to add.
    1176             :  */
    1177             : 
    1178       78120 : void OGR_G_AddPoint_2D(OGRGeometryH hGeom, double dfX, double dfY)
    1179             : 
    1180             : {
    1181       78120 :     VALIDATE_POINTER0(hGeom, "OGR_G_AddPoint_2D");
    1182             : 
    1183       78120 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
    1184             :     {
    1185          74 :         case wkbPoint:
    1186             :         {
    1187          74 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
    1188          74 :             poPoint->setX(dfX);
    1189          74 :             poPoint->setY(dfY);
    1190             :         }
    1191          74 :         break;
    1192             : 
    1193       78045 :         case wkbLineString:
    1194             :         case wkbCircularString:
    1195       78045 :             ToPointer(hGeom)->toSimpleCurve()->addPoint(dfX, dfY);
    1196       78045 :             break;
    1197             : 
    1198           1 :         default:
    1199           1 :             CPLError(CE_Failure, CPLE_NotSupported,
    1200             :                      "Incompatible geometry for operation");
    1201           1 :             break;
    1202             :     }
    1203             : }
    1204             : 
    1205             : /************************************************************************/
    1206             : /*                           OGR_G_AddPointM()                          */
    1207             : /************************************************************************/
    1208             : /**
    1209             :  * \brief Add a point to a geometry (line string or point).
    1210             :  *
    1211             :  * The vertex count of the line string is increased by one, and assigned from
    1212             :  * the passed location value.
    1213             :  *
    1214             :  * @param hGeom handle to the geometry to add a point to.
    1215             :  * @param dfX x coordinate of point to add.
    1216             :  * @param dfY y coordinate of point to add.
    1217             :  * @param dfM m coordinate of point to add.
    1218             :  */
    1219             : 
    1220           0 : void OGR_G_AddPointM(OGRGeometryH hGeom, double dfX, double dfY, double dfM)
    1221             : 
    1222             : {
    1223           0 :     VALIDATE_POINTER0(hGeom, "OGR_G_AddPointM");
    1224             : 
    1225           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
    1226             :     {
    1227           0 :         case wkbPoint:
    1228             :         {
    1229           0 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
    1230           0 :             poPoint->setX(dfX);
    1231           0 :             poPoint->setY(dfY);
    1232           0 :             poPoint->setM(dfM);
    1233             :         }
    1234           0 :         break;
    1235             : 
    1236           0 :         case wkbLineString:
    1237             :         case wkbCircularString:
    1238           0 :             ToPointer(hGeom)->toSimpleCurve()->addPointM(dfX, dfY, dfM);
    1239           0 :             break;
    1240             : 
    1241           0 :         default:
    1242           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    1243             :                      "Incompatible geometry for operation");
    1244           0 :             break;
    1245             :     }
    1246             : }
    1247             : 
    1248             : /************************************************************************/
    1249             : /*                           OGR_G_AddPointZM()                         */
    1250             : /************************************************************************/
    1251             : /**
    1252             :  * \brief Add a point to a geometry (line string or point).
    1253             :  *
    1254             :  * The vertex count of the line string is increased by one, and assigned from
    1255             :  * the passed location value.
    1256             :  *
    1257             :  * @param hGeom handle to the geometry to add a point to.
    1258             :  * @param dfX x coordinate of point to add.
    1259             :  * @param dfY y coordinate of point to add.
    1260             :  * @param dfZ z coordinate of point to add.
    1261             :  * @param dfM m coordinate of point to add.
    1262             :  */
    1263             : 
    1264           0 : void OGR_G_AddPointZM(OGRGeometryH hGeom, double dfX, double dfY, double dfZ,
    1265             :                       double dfM)
    1266             : 
    1267             : {
    1268           0 :     VALIDATE_POINTER0(hGeom, "OGR_G_AddPointZM");
    1269             : 
    1270           0 :     switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
    1271             :     {
    1272           0 :         case wkbPoint:
    1273             :         {
    1274           0 :             OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
    1275           0 :             poPoint->setX(dfX);
    1276           0 :             poPoint->setY(dfY);
    1277           0 :             poPoint->setZ(dfZ);
    1278           0 :             poPoint->setM(dfM);
    1279             :         }
    1280           0 :         break;
    1281             : 
    1282           0 :         case wkbLineString:
    1283             :         case wkbCircularString:
    1284           0 :             ToPointer(hGeom)->toSimpleCurve()->addPoint(dfX, dfY, dfZ, dfM);
    1285           0 :             break;
    1286             : 
    1287           0 :         default:
    1288           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    1289             :                      "Incompatible geometry for operation");
    1290           0 :             break;
    1291             :     }
    1292             : }
    1293             : 
    1294             : /************************************************************************/
    1295             : /*                       OGR_G_GetGeometryCount()                       */
    1296             : /************************************************************************/
    1297             : /**
    1298             :  * \brief Fetch the number of elements in a geometry or number of geometries in
    1299             :  * container.
    1300             :  *
    1301             :  * Only geometries of type wkbPolygon[25D], wkbMultiPoint[25D],
    1302             :  * wkbMultiLineString[25D], wkbMultiPolygon[25D] or wkbGeometryCollection[25D]
    1303             :  * may return a valid value.  Other geometry types will silently return 0.
    1304             :  *
    1305             :  * For a polygon, the returned number is the number of rings (exterior ring +
    1306             :  * interior rings).
    1307             :  *
    1308             :  * @param hGeom single geometry or geometry container from which to get
    1309             :  * the number of elements.
    1310             :  * @return the number of elements.
    1311             :  */
    1312             : 
    1313       10790 : int OGR_G_GetGeometryCount(OGRGeometryH hGeom)
    1314             : 
    1315             : {
    1316       10790 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetGeometryCount", 0);
    1317             : 
    1318       10790 :     const auto poGeom = ToPointer(hGeom);
    1319       10790 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1320       10790 :     if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
    1321             :     {
    1322        2720 :         if (poGeom->toCurvePolygon()->getExteriorRingCurve() == nullptr)
    1323         111 :             return 0;
    1324             :         else
    1325        2609 :             return poGeom->toCurvePolygon()->getNumInteriorRings() + 1;
    1326             :     }
    1327        8070 :     else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
    1328             :     {
    1329         231 :         return poGeom->toCompoundCurve()->getNumCurves();
    1330             :     }
    1331        7839 :     else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
    1332             :     {
    1333        2706 :         return poGeom->toGeometryCollection()->getNumGeometries();
    1334             :     }
    1335        5133 :     else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
    1336             :     {
    1337          86 :         return poGeom->toPolyhedralSurface()->getNumGeometries();
    1338             :     }
    1339             :     else
    1340             :     {
    1341             :         // autotest/pymod/ogrtest.py calls this method on any geometry. So keep
    1342             :         // silent.
    1343             :         // CPLError(CE_Failure, CPLE_NotSupported,
    1344             :         //          "Incompatible geometry for operation");
    1345        5047 :         return 0;
    1346             :     }
    1347             : }
    1348             : 
    1349             : /************************************************************************/
    1350             : /*                        OGR_G_GetGeometryRef()                        */
    1351             : /************************************************************************/
    1352             : 
    1353             : /**
    1354             :  * \brief Fetch geometry from a geometry container.
    1355             :  *
    1356             :  * This function returns a handle to a geometry within the container.
    1357             :  * The returned geometry remains owned by the container, and should not be
    1358             :  * modified.  The handle is only valid until the next change to the
    1359             :  * geometry container.  Use OGR_G_Clone() to make a copy.
    1360             :  *
    1361             :  * This function relates to the SFCOM
    1362             :  * IGeometryCollection::get_Geometry() method.
    1363             :  *
    1364             :  * This function is the same as the CPP method
    1365             :  * OGRGeometryCollection::getGeometryRef().
    1366             :  *
    1367             :  * For a polygon, OGR_G_GetGeometryRef(iSubGeom) returns the exterior ring
    1368             :  * if iSubGeom == 0, and the interior rings for iSubGeom > 0.
    1369             :  *
    1370             :  * @param hGeom handle to the geometry container from which to get a
    1371             :  * geometry from.
    1372             :  * @param iSubGeom the index of the geometry to fetch, between 0 and
    1373             :  *          getNumGeometries() - 1.
    1374             :  * @return handle to the requested geometry.
    1375             :  */
    1376             : 
    1377        2949 : OGRGeometryH OGR_G_GetGeometryRef(OGRGeometryH hGeom, int iSubGeom)
    1378             : 
    1379             : {
    1380        2949 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetGeometryRef", nullptr);
    1381             : 
    1382        2949 :     const auto poGeom = ToPointer(hGeom);
    1383        2949 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1384        2949 :     if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
    1385             :     {
    1386        1122 :         if (iSubGeom == 0)
    1387        1044 :             return ToHandle(poGeom->toCurvePolygon()->getExteriorRingCurve());
    1388             :         else
    1389          78 :             return ToHandle(
    1390          78 :                 poGeom->toCurvePolygon()->getInteriorRingCurve(iSubGeom - 1));
    1391             :     }
    1392        1827 :     else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
    1393             :     {
    1394         232 :         return ToHandle(poGeom->toCompoundCurve()->getCurve(iSubGeom));
    1395             :     }
    1396        1595 :     else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
    1397             :     {
    1398        1463 :         return ToHandle(
    1399        1463 :             poGeom->toGeometryCollection()->getGeometryRef(iSubGeom));
    1400             :     }
    1401         132 :     else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
    1402             :     {
    1403         131 :         return ToHandle(
    1404         131 :             poGeom->toPolyhedralSurface()->getGeometryRef(iSubGeom));
    1405             :     }
    1406             :     else
    1407             :     {
    1408           1 :         CPLError(CE_Failure, CPLE_NotSupported,
    1409             :                  "Incompatible geometry for operation");
    1410           1 :         return nullptr;
    1411             :     }
    1412             : }
    1413             : 
    1414             : /************************************************************************/
    1415             : /*                         OGR_G_AddGeometry()                          */
    1416             : /************************************************************************/
    1417             : 
    1418             : /**
    1419             :  * \brief Add a geometry to a geometry container.
    1420             :  *
    1421             :  * Some subclasses of OGRGeometryCollection restrict the types of geometry
    1422             :  * that can be added, and may return an error.  The passed geometry is cloned
    1423             :  * to make an internal copy.
    1424             :  *
    1425             :  * There is no SFCOM analog to this method.
    1426             :  *
    1427             :  * This function is the same as the CPP method
    1428             :  * OGRGeometryCollection::addGeometry.
    1429             :  *
    1430             :  * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
    1431             :  * the first added subgeometry will be the exterior ring. The next ones will be
    1432             :  * the interior rings.
    1433             :  *
    1434             :  * @param hGeom existing geometry container.
    1435             :  * @param hNewSubGeom geometry to add to the container.
    1436             :  *
    1437             :  * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
    1438             :  * the geometry type is illegal for the type of existing geometry.
    1439             :  */
    1440             : 
    1441         106 : OGRErr OGR_G_AddGeometry(OGRGeometryH hGeom, OGRGeometryH hNewSubGeom)
    1442             : 
    1443             : {
    1444         106 :     VALIDATE_POINTER1(hGeom, "OGR_G_AddGeometry", OGRERR_UNSUPPORTED_OPERATION);
    1445         106 :     VALIDATE_POINTER1(hNewSubGeom, "OGR_G_AddGeometry",
    1446             :                       OGRERR_UNSUPPORTED_OPERATION);
    1447             : 
    1448         106 :     OGRErr eErr = OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
    1449             : 
    1450         106 :     auto poGeom = ToPointer(hGeom);
    1451         106 :     auto poNewSubGeom = ToPointer(hNewSubGeom);
    1452         106 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1453         106 :     if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
    1454             :     {
    1455          57 :         if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
    1456          57 :             eErr = poGeom->toCurvePolygon()->addRing(poNewSubGeom->toCurve());
    1457             :     }
    1458          49 :     else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
    1459             :     {
    1460           2 :         if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
    1461           2 :             eErr = poGeom->toCompoundCurve()->addCurve(poNewSubGeom->toCurve());
    1462             :     }
    1463          47 :     else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
    1464             :     {
    1465          41 :         eErr = poGeom->toGeometryCollection()->addGeometry(poNewSubGeom);
    1466             :     }
    1467           6 :     else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
    1468             :     {
    1469           5 :         eErr = poGeom->toPolyhedralSurface()->addGeometry(poNewSubGeom);
    1470             :     }
    1471             : 
    1472         106 :     return eErr;
    1473             : }
    1474             : 
    1475             : /************************************************************************/
    1476             : /*                     OGR_G_AddGeometryDirectly()                      */
    1477             : /************************************************************************/
    1478             : /**
    1479             :  * \brief Add a geometry directly to an existing geometry container.
    1480             :  *
    1481             :  * Some subclasses of OGRGeometryCollection restrict the types of geometry
    1482             :  * that can be added, and may return an error.  Ownership of the passed
    1483             :  * geometry is taken by the container rather than cloning as addGeometry()
    1484             :  * does.
    1485             :  *
    1486             :  * This function is the same as the CPP method
    1487             :  * OGRGeometryCollection::addGeometryDirectly.
    1488             :  *
    1489             :  * There is no SFCOM analog to this method.
    1490             :  *
    1491             :  * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
    1492             :  * the first added subgeometry will be the exterior ring. The next ones will be
    1493             :  * the interior rings.
    1494             :  *
    1495             :  * @param hGeom existing geometry.
    1496             :  * @param hNewSubGeom geometry to add to the existing geometry.
    1497             :  *
    1498             :  * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
    1499             :  * the geometry type is illegal for the type of geometry container.
    1500             :  */
    1501             : 
    1502        3709 : OGRErr OGR_G_AddGeometryDirectly(OGRGeometryH hGeom, OGRGeometryH hNewSubGeom)
    1503             : 
    1504             : {
    1505        3709 :     VALIDATE_POINTER1(hGeom, "OGR_G_AddGeometryDirectly",
    1506             :                       OGRERR_UNSUPPORTED_OPERATION);
    1507        3709 :     VALIDATE_POINTER1(hNewSubGeom, "OGR_G_AddGeometryDirectly",
    1508             :                       OGRERR_UNSUPPORTED_OPERATION);
    1509             : 
    1510        3709 :     OGRErr eErr = OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
    1511             : 
    1512        3709 :     auto poGeom = ToPointer(hGeom);
    1513        3709 :     auto poNewSubGeom = ToPointer(hNewSubGeom);
    1514        3709 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1515             : 
    1516        3709 :     if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
    1517             :     {
    1518        3651 :         if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
    1519        7302 :             eErr = poGeom->toCurvePolygon()->addRingDirectly(
    1520        3651 :                 poNewSubGeom->toCurve());
    1521             :     }
    1522          58 :     else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
    1523             :     {
    1524           3 :         if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
    1525           3 :             eErr = poGeom->toCompoundCurve()->addCurveDirectly(
    1526             :                 poNewSubGeom->toCurve());
    1527             :     }
    1528          55 :     else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
    1529             :     {
    1530             :         eErr =
    1531          51 :             poGeom->toGeometryCollection()->addGeometryDirectly(poNewSubGeom);
    1532             :     }
    1533           4 :     else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
    1534             :     {
    1535           3 :         eErr = poGeom->toPolyhedralSurface()->addGeometryDirectly(poNewSubGeom);
    1536             :     }
    1537             : 
    1538        3709 :     if (eErr != OGRERR_NONE)
    1539           3 :         delete poNewSubGeom;
    1540             : 
    1541        3709 :     return eErr;
    1542             : }
    1543             : 
    1544             : /************************************************************************/
    1545             : /*                        OGR_G_RemoveGeometry()                        */
    1546             : /************************************************************************/
    1547             : 
    1548             : /**
    1549             :  * \brief Remove a geometry from an exiting geometry container.
    1550             :  *
    1551             :  * Removing a geometry will cause the geometry count to drop by one, and all
    1552             :  * "higher" geometries will shuffle down one in index.
    1553             :  *
    1554             :  * There is no SFCOM analog to this method.
    1555             :  *
    1556             :  * This function is the same as the CPP method
    1557             :  * OGRGeometryCollection::removeGeometry() for geometry collections,
    1558             :  * OGRCurvePolygon::removeRing() for polygons / curve polygons and
    1559             :  * OGRPolyhedralSurface::removeGeometry() for polyhedral surfaces and TINs.
    1560             :  *
    1561             :  * @param hGeom the existing geometry to delete from.
    1562             :  * @param iGeom the index of the geometry to delete.  A value of -1 is a
    1563             :  * special flag meaning that all geometries should be removed.
    1564             :  *
    1565             :  * @param bDelete if TRUE the geometry will be destroyed, otherwise it will
    1566             :  * not.  The default is TRUE as the existing geometry is considered to own the
    1567             :  * geometries in it.
    1568             :  *
    1569             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
    1570             :  * out of range.
    1571             :  */
    1572             : 
    1573          63 : OGRErr OGR_G_RemoveGeometry(OGRGeometryH hGeom, int iGeom, int bDelete)
    1574             : 
    1575             : {
    1576          63 :     VALIDATE_POINTER1(hGeom, "OGR_G_RemoveGeometry", OGRERR_FAILURE);
    1577             : 
    1578          63 :     const auto poGeom = ToPointer(hGeom);
    1579          63 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1580          63 :     if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
    1581             :     {
    1582          30 :         return poGeom->toCurvePolygon()->removeRing(iGeom,
    1583          30 :                                                     CPL_TO_BOOL(bDelete));
    1584             :     }
    1585          48 :     else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
    1586             :     {
    1587          42 :         return poGeom->toGeometryCollection()->removeGeometry(iGeom, bDelete);
    1588             :     }
    1589           6 :     else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
    1590             :     {
    1591           5 :         return poGeom->toPolyhedralSurface()->removeGeometry(iGeom, bDelete);
    1592             :     }
    1593             :     else
    1594             :     {
    1595           1 :         return OGRERR_UNSUPPORTED_OPERATION;
    1596             :     }
    1597             : }
    1598             : 
    1599             : /************************************************************************/
    1600             : /*                           OGR_G_Length()                             */
    1601             : /************************************************************************/
    1602             : 
    1603             : /**
    1604             :  * \brief Compute length of a geometry.
    1605             :  *
    1606             :  * Computes the length for OGRCurve or MultiCurve objects.
    1607             :  * Undefined for all other geometry types (returns zero).
    1608             :  *
    1609             :  * This function utilizes the C++ get_Length() method.
    1610             :  *
    1611             :  * @param hGeom the geometry to operate on.
    1612             :  * @return the length or 0.0 for unsupported geometry types.
    1613             :  *
    1614             :  * @since OGR 1.8.0
    1615             :  */
    1616             : 
    1617          27 : double OGR_G_Length(OGRGeometryH hGeom)
    1618             : 
    1619             : {
    1620          27 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetLength", 0);
    1621             : 
    1622          27 :     double dfLength = 0.0;
    1623             : 
    1624          27 :     const auto poGeom = ToPointer(hGeom);
    1625             :     const OGRwkbGeometryType eType =
    1626          27 :         wkbFlatten(ToPointer(hGeom)->getGeometryType());
    1627          27 :     if (OGR_GT_IsCurve(eType))
    1628             :     {
    1629          21 :         dfLength = poGeom->toCurve()->get_Length();
    1630             :     }
    1631           6 :     else if (OGR_GT_IsSubClassOf(eType, wkbMultiCurve) ||
    1632             :              eType == wkbGeometryCollection)
    1633             :     {
    1634           5 :         dfLength = poGeom->toGeometryCollection()->get_Length();
    1635             :     }
    1636             :     else
    1637             :     {
    1638           1 :         CPLError(CE_Warning, CPLE_AppDefined,
    1639             :                  "OGR_G_Length() called against a non-curve geometry type.");
    1640           1 :         dfLength = 0.0;
    1641             :     }
    1642             : 
    1643          27 :     return dfLength;
    1644             : }
    1645             : 
    1646             : /************************************************************************/
    1647             : /*                           OGR_G_Area()                               */
    1648             : /************************************************************************/
    1649             : 
    1650             : /**
    1651             :  * \brief Compute geometry area.
    1652             :  *
    1653             :  * The returned area is a 2D Cartesian (planar) area in square units of the
    1654             :  * spatial reference system in use, so potentially "square degrees" for a
    1655             :  * geometry expressed in a geographic SRS.
    1656             :  *
    1657             :  * Computes the area for surfaces or closed curves.
    1658             :  * Undefined for all other geometry types (returns 0.0).
    1659             :  *
    1660             :  * This function utilizes the C++ OGRSurface::get_Area() method.
    1661             :  *
    1662             :  * @param hGeom the geometry to operate on.
    1663             :  * @return the area of the geometry in square units of the spatial reference
    1664             :  * system in use, or 0.0 for unsupported geometry types.
    1665             : 
    1666             :  * @see OGR_G_GeodesicArea() for an alternative function returning areas
    1667             :  * computed on the ellipsoid, an in square meters.
    1668             :  *
    1669             :  * @since OGR 1.8.0
    1670             :  */
    1671             : 
    1672        1444 : double OGR_G_Area(OGRGeometryH hGeom)
    1673             : 
    1674             : {
    1675        1444 :     VALIDATE_POINTER1(hGeom, "OGR_G_Area", 0);
    1676             : 
    1677        1444 :     double dfArea = 0.0;
    1678             : 
    1679        1444 :     const auto poGeom = ToPointer(hGeom);
    1680        1444 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1681        1444 :     if (OGR_GT_IsSurface(eType))
    1682             :     {
    1683        1435 :         dfArea = poGeom->toSurface()->get_Area();
    1684             :     }
    1685           9 :     else if (OGR_GT_IsCurve(eType))
    1686             :     {
    1687           3 :         dfArea = poGeom->toCurve()->get_Area();
    1688             :     }
    1689           6 :     else if (OGR_GT_IsSubClassOf(eType, wkbMultiSurface) ||
    1690             :              eType == wkbGeometryCollection)
    1691             :     {
    1692           5 :         dfArea = poGeom->toGeometryCollection()->get_Area();
    1693             :     }
    1694             :     else
    1695             :     {
    1696           1 :         CPLError(CE_Warning, CPLE_AppDefined,
    1697             :                  "OGR_G_Area() called against non-surface geometry type.");
    1698             : 
    1699           1 :         dfArea = 0.0;
    1700             :     }
    1701             : 
    1702        1444 :     return dfArea;
    1703             : }
    1704             : 
    1705             : /**
    1706             :  * \brief Compute geometry area (deprecated)
    1707             :  *
    1708             :  * @deprecated
    1709             :  * @see OGR_G_Area()
    1710             :  */
    1711           0 : double OGR_G_GetArea(OGRGeometryH hGeom)
    1712             : 
    1713             : {
    1714           0 :     return OGR_G_Area(hGeom);
    1715             : }
    1716             : 
    1717             : /************************************************************************/
    1718             : /*                         OGR_G_GeodesicArea()                         */
    1719             : /************************************************************************/
    1720             : 
    1721             : /**
    1722             :  * \brief Compute geometry area, considered as a surface on the underlying
    1723             :  * ellipsoid of the SRS attached to the geometry.
    1724             :  *
    1725             :  * The returned area will always be in square meters, and assumes that
    1726             :  * polygon edges describe geodesic lines on the ellipsoid.
    1727             :  *
    1728             :  * If the geometry' SRS is not a geographic one, geometries are reprojected to
    1729             :  * the underlying geographic SRS of the geometry' SRS.
    1730             :  * OGRSpatialReference::GetDataAxisToSRSAxisMapping() is honored.
    1731             :  *
    1732             :  * Computes the area for surfaces or closed curves.
    1733             :  * Undefined for all other geometry types (returns a negative value).
    1734             :  *
    1735             :  * Note that geometries with circular arcs will be linearized in their original
    1736             :  * coordinate space first, so the resulting geodesic area will be an
    1737             :  * approximation.
    1738             :  *
    1739             :  * This function utilizes the C++ OGRSurface::get_GeodesicArea() method.
    1740             :  *
    1741             :  * @param hGeom the geometry to operate on.
    1742             :  * @return the area, or a negative value in case of error (unsupported geometry
    1743             :  * type, no SRS attached, etc.)
    1744             :  *
    1745             :  * @see OGR_G_Area() for an alternative method returning areas computed in
    1746             :  * 2D Cartesian space.
    1747             :  *
    1748             :  * @since OGR 3.9.0
    1749             :  */
    1750             : 
    1751          29 : double OGR_G_GeodesicArea(OGRGeometryH hGeom)
    1752             : 
    1753             : {
    1754          29 :     VALIDATE_POINTER1(hGeom, "OGR_G_GeodesicArea", -1);
    1755             : 
    1756          29 :     double dfArea = -1;
    1757             : 
    1758          29 :     const auto poGeom = ToPointer(hGeom);
    1759          29 :     const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1760          29 :     if (OGR_GT_IsSurface(eType))
    1761             :     {
    1762          16 :         dfArea = poGeom->toSurface()->get_GeodesicArea();
    1763             :     }
    1764          13 :     else if (OGR_GT_IsCurve(eType))
    1765             :     {
    1766           8 :         dfArea = poGeom->toCurve()->get_GeodesicArea();
    1767             :     }
    1768           5 :     else if (OGR_GT_IsSubClassOf(eType, wkbMultiSurface) ||
    1769             :              eType == wkbGeometryCollection)
    1770             :     {
    1771           4 :         dfArea = poGeom->toGeometryCollection()->get_GeodesicArea();
    1772             :     }
    1773             :     else
    1774             :     {
    1775           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1776             :                  "OGR_G_GeodesicArea() called against non-surface geometry "
    1777             :                  "type.");
    1778             :     }
    1779             : 
    1780          29 :     return dfArea;
    1781             : }
    1782             : 
    1783             : /************************************************************************/
    1784             : /*                         OGR_G_IsClockwise()                          */
    1785             : /************************************************************************/
    1786             : /**
    1787             :  * \brief Returns true if the ring has clockwise winding (or less than 2 points)
    1788             :  *
    1789             :  * Assumes that the ring is closed.
    1790             :  *
    1791             :  * @param hGeom handle to a curve geometry
    1792             :  * @since GDAL 3.8
    1793             :  */
    1794             : 
    1795          33 : bool OGR_G_IsClockwise(OGRGeometryH hGeom)
    1796             : 
    1797             : {
    1798          33 :     VALIDATE_POINTER1(hGeom, "OGR_G_IsClockwise", false);
    1799             : 
    1800          33 :     auto poGeom = OGRGeometry::FromHandle(hGeom);
    1801          33 :     const OGRwkbGeometryType eGType = wkbFlatten(poGeom->getGeometryType());
    1802          33 :     if (OGR_GT_IsCurve(eGType))
    1803             :     {
    1804          32 :         return poGeom->toCurve()->isClockwise();
    1805             :     }
    1806             :     else
    1807             :     {
    1808           1 :         CPLError(CE_Failure, CPLE_NotSupported,
    1809             :                  "Incompatible geometry for operation");
    1810           1 :         return false;
    1811             :     }
    1812             : }
    1813             : 
    1814             : /************************************************************************/
    1815             : /*                         OGR_G_HasCurveGeometry()                     */
    1816             : /************************************************************************/
    1817             : 
    1818             : /**
    1819             :  * \brief Returns if this geometry is or has curve geometry.
    1820             :  *
    1821             :  * Returns if a geometry is or has CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
    1822             :  * MULTICURVE or MULTISURFACE in it.
    1823             :  *
    1824             :  * If bLookForNonLinear is set to TRUE, it will be actually looked if the
    1825             :  * geometry or its subgeometries are or contain a non-linear geometry in
    1826             :  * them. In which case, if the method returns TRUE, it means that
    1827             :  * OGR_G_GetLinearGeometry() would return an approximate version of the
    1828             :  * geometry. Otherwise, OGR_G_GetLinearGeometry() would do a conversion, but
    1829             :  * with just converting container type, like COMPOUNDCURVE -> LINESTRING,
    1830             :  * MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON, resulting in a
    1831             :  * "loss-less" conversion.
    1832             :  *
    1833             :  * This function is the same as C++ method OGRGeometry::hasCurveGeometry().
    1834             :  *
    1835             :  * @param hGeom the geometry to operate on.
    1836             :  * @param bLookForNonLinear set it to TRUE to check if the geometry is or
    1837             :  * contains a CIRCULARSTRING.
    1838             :  * @return TRUE if this geometry is or has curve geometry.
    1839             :  *
    1840             :  * @since GDAL 2.0
    1841             :  */
    1842             : 
    1843          29 : int OGR_G_HasCurveGeometry(OGRGeometryH hGeom, int bLookForNonLinear)
    1844             : {
    1845          29 :     VALIDATE_POINTER1(hGeom, "OGR_G_HasCurveGeometry", FALSE);
    1846          29 :     return ToPointer(hGeom)->hasCurveGeometry(bLookForNonLinear);
    1847             : }
    1848             : 
    1849             : /************************************************************************/
    1850             : /*                         OGR_G_GetLinearGeometry()                   */
    1851             : /************************************************************************/
    1852             : 
    1853             : /**
    1854             :  * \brief Return, possibly approximate, linear version of this geometry.
    1855             :  *
    1856             :  * Returns a geometry that has no CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
    1857             :  * MULTICURVE or MULTISURFACE in it, by approximating curve geometries.
    1858             :  *
    1859             :  * The ownership of the returned geometry belongs to the caller.
    1860             :  *
    1861             :  * The reverse function is OGR_G_GetCurveGeometry().
    1862             :  *
    1863             :  * This method relates to the ISO SQL/MM Part 3 ICurve::CurveToLine() and
    1864             :  * CurvePolygon::CurvePolyToPoly() methods.
    1865             :  *
    1866             :  * This function is the same as C++ method OGRGeometry::getLinearGeometry().
    1867             :  *
    1868             :  * @param hGeom the geometry to operate on.
    1869             :  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
    1870             :  * arc, zero to use the default setting.
    1871             :  * @param papszOptions options as a null-terminated list of strings or NULL.
    1872             :  * See OGRGeometryFactory::curveToLineString() for valid options.
    1873             :  *
    1874             :  * @return a new geometry.
    1875             :  *
    1876             :  * @since GDAL 2.0
    1877             :  */
    1878             : 
    1879        3083 : OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry(OGRGeometryH hGeom,
    1880             :                                              double dfMaxAngleStepSizeDegrees,
    1881             :                                              char **papszOptions)
    1882             : {
    1883        3083 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetLinearGeometry", nullptr);
    1884        6166 :     return ToHandle(ToPointer(hGeom)->getLinearGeometry(
    1885        6166 :         dfMaxAngleStepSizeDegrees, papszOptions));
    1886             : }
    1887             : 
    1888             : /************************************************************************/
    1889             : /*                         OGR_G_GetCurveGeometry()                     */
    1890             : /************************************************************************/
    1891             : 
    1892             : /**
    1893             :  * \brief Return curve version of this geometry.
    1894             :  *
    1895             :  * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE,
    1896             :  * CURVEPOLYGON, MULTICURVE or MULTISURFACE in it, by de-approximating linear
    1897             :  * into curve geometries.
    1898             :  *
    1899             :  * If the geometry has no curve portion, the returned geometry will be a clone
    1900             :  * of it.
    1901             :  *
    1902             :  * The ownership of the returned geometry belongs to the caller.
    1903             :  *
    1904             :  * The reverse function is OGR_G_GetLinearGeometry().
    1905             :  *
    1906             :  * This function is the same as C++ method OGRGeometry::getCurveGeometry().
    1907             :  *
    1908             :  * @param hGeom the geometry to operate on.
    1909             :  * @param papszOptions options as a null-terminated list of strings.
    1910             :  *                     Unused for now. Must be set to NULL.
    1911             :  *
    1912             :  * @return a new geometry.
    1913             :  *
    1914             :  * @since GDAL 2.0
    1915             :  */
    1916             : 
    1917        3056 : OGRGeometryH CPL_DLL OGR_G_GetCurveGeometry(OGRGeometryH hGeom,
    1918             :                                             char **papszOptions)
    1919             : {
    1920        3056 :     VALIDATE_POINTER1(hGeom, "OGR_G_GetCurveGeometry", nullptr);
    1921             : 
    1922        3056 :     return ToHandle(ToPointer(hGeom)->getCurveGeometry(papszOptions));
    1923             : }
    1924             : 
    1925             : /************************************************************************/
    1926             : /*                          OGR_G_Value()                               */
    1927             : /************************************************************************/
    1928             : /**
    1929             :  * \brief Fetch point at given distance along curve.
    1930             :  *
    1931             :  * This function relates to the SF COM ICurve::get_Value() method.
    1932             :  *
    1933             :  * This function is the same as the C++ method OGRCurve::Value().
    1934             :  *
    1935             :  * @param hGeom curve geometry.
    1936             :  * @param dfDistance distance along the curve at which to sample position.
    1937             :  *                   This distance should be between zero and get_Length()
    1938             :  *                   for this curve.
    1939             :  * @return a point or NULL.
    1940             :  *
    1941             :  * @since GDAL 2.0
    1942             :  */
    1943             : 
    1944          22 : OGRGeometryH OGR_G_Value(OGRGeometryH hGeom, double dfDistance)
    1945             : {
    1946          22 :     VALIDATE_POINTER1(hGeom, "OGR_G_Value", nullptr);
    1947             : 
    1948          22 :     const auto poGeom = ToPointer(hGeom);
    1949          22 :     if (OGR_GT_IsCurve(poGeom->getGeometryType()))
    1950             :     {
    1951          22 :         OGRPoint *p = new OGRPoint();
    1952          22 :         poGeom->toCurve()->Value(dfDistance, p);
    1953          22 :         return ToHandle(p);
    1954             :     }
    1955             : 
    1956           0 :     return nullptr;
    1957             : }
    1958             : 
    1959             : /************************************************************************/
    1960             : /*                 OGRSetNonLinearGeometriesEnabledFlag()               */
    1961             : /************************************************************************/
    1962             : 
    1963             : /**
    1964             :  * \brief Set flag to enable/disable returning non-linear geometries in the C
    1965             :  * API.
    1966             :  *
    1967             :  * This flag has only an effect on the OGR_F_GetGeometryRef(),
    1968             :  * OGR_F_GetGeomFieldRef(), OGR_L_GetGeomType(), OGR_GFld_GetType() and
    1969             :  * OGR_FD_GetGeomType() C API, and corresponding methods in the SWIG
    1970             :  * bindings. It is meant as making it simple for applications using the OGR C
    1971             :  * API not to have to deal with non-linear geometries, even if such geometries
    1972             :  * might be returned by drivers. In which case, they will be transformed into
    1973             :  * their closest linear geometry, by doing linear approximation, with
    1974             :  * OGR_G_ForceTo().
    1975             :  *
    1976             :  * Libraries should generally *not* use that method, since that could interfere
    1977             :  * with other libraries or applications.
    1978             :  *
    1979             :  * Note that it *does* not affect the behavior of the C++ API.
    1980             :  *
    1981             :  * @param bFlag TRUE if non-linear geometries might be returned (default value).
    1982             :  *              FALSE to ask for non-linear geometries to be approximated as
    1983             :  *              linear geometries.
    1984             :  *
    1985             :  * @since GDAL 2.0
    1986             :  */
    1987             : 
    1988           2 : void OGRSetNonLinearGeometriesEnabledFlag(int bFlag)
    1989             : {
    1990           2 :     bNonLinearGeometriesEnabled = bFlag != FALSE;
    1991           2 : }
    1992             : 
    1993             : /************************************************************************/
    1994             : /*                 OGRGetNonLinearGeometriesEnabledFlag()               */
    1995             : /************************************************************************/
    1996             : 
    1997             : /**
    1998             :  * \brief Get flag to enable/disable returning non-linear geometries in the C
    1999             :  * API.
    2000             :  *
    2001             :  * return TRUE if non-linear geometries might be returned (default value is
    2002             :  * TRUE).
    2003             :  *
    2004             :  * @since GDAL 2.0
    2005             :  * @see OGRSetNonLinearGeometriesEnabledFlag()
    2006             :  */
    2007             : 
    2008       38253 : int OGRGetNonLinearGeometriesEnabledFlag(void)
    2009             : {
    2010       38253 :     return bNonLinearGeometriesEnabled;
    2011             : }

Generated by: LCOV version 1.14