LCOV - code coverage report
Current view: top level - ogr - ogr_api.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 402 614 65.5 %
Date: 2025-02-18 14:19:29 Functions: 44 52 84.6 %

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

Generated by: LCOV version 1.14