LCOV - code coverage report
Current view: top level - ogr - ogrcurvecollection.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 248 276 89.9 %
Date: 2024-05-04 12:52:34 Functions: 28 28 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRCurveCollection class.
       5             :  * Author:   Even Rouault, even dot rouault at spatialys dot com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_port.h"
      30             : #include "ogr_geometry.h"
      31             : 
      32             : #include <cstddef>
      33             : #include <cstring>
      34             : #include <new>
      35             : 
      36             : #include "ogr_core.h"
      37             : #include "ogr_p.h"
      38             : #include "ogr_spatialref.h"
      39             : #include "cpl_conv.h"
      40             : #include "cpl_error.h"
      41             : #include "cpl_string.h"
      42             : #include "cpl_vsi.h"
      43             : 
      44             : //! @cond Doxygen_Suppress
      45             : 
      46             : /************************************************************************/
      47             : /*                         OGRCurveCollection()                         */
      48             : /************************************************************************/
      49             : 
      50             : OGRCurveCollection::OGRCurveCollection() = default;
      51             : 
      52             : /************************************************************************/
      53             : /*             OGRCurveCollection( const OGRCurveCollection& )          */
      54             : /************************************************************************/
      55             : 
      56             : /**
      57             :  * \brief Copy constructor.
      58             :  *
      59             :  * Note: before GDAL 2.1, only the default implementation of the constructor
      60             :  * existed, which could be unsafe to use.
      61             :  *
      62             :  * @since GDAL 2.1
      63             :  */
      64             : 
      65      106031 : OGRCurveCollection::OGRCurveCollection(const OGRCurveCollection &other)
      66             : {
      67      106031 :     if (other.nCurveCount > 0)
      68             :     {
      69      105730 :         nCurveCount = other.nCurveCount;
      70      105730 :         papoCurves = static_cast<OGRCurve **>(
      71      105730 :             VSI_CALLOC_VERBOSE(sizeof(void *), nCurveCount));
      72             : 
      73      105730 :         if (papoCurves)
      74             :         {
      75      212418 :             for (int i = 0; i < nCurveCount; i++)
      76             :             {
      77      106688 :                 papoCurves[i] = other.papoCurves[i]->clone();
      78             :             }
      79             :         }
      80             :     }
      81      106031 : }
      82             : 
      83             : /************************************************************************/
      84             : /*                         ~OGRCurveCollection()                        */
      85             : /************************************************************************/
      86             : 
      87      561172 : OGRCurveCollection::~OGRCurveCollection()
      88             : 
      89             : {
      90      280590 :     empty(nullptr);
      91      280582 : }
      92             : 
      93             : /************************************************************************/
      94             : /*                 operator=( const OGRCurveCollection& )               */
      95             : /************************************************************************/
      96             : 
      97             : /**
      98             :  * \brief Assignment operator.
      99             :  *
     100             :  * Note: before GDAL 2.1, only the default implementation of the operator
     101             :  * existed, which could be unsafe to use.
     102             :  *
     103             :  * @since GDAL 2.1
     104             :  */
     105             : 
     106             : OGRCurveCollection &
     107          16 : OGRCurveCollection::operator=(const OGRCurveCollection &other)
     108             : {
     109          16 :     if (this != &other)
     110             :     {
     111          16 :         empty(nullptr);
     112             : 
     113          16 :         if (other.nCurveCount > 0)
     114             :         {
     115           8 :             nCurveCount = other.nCurveCount;
     116           8 :             papoCurves = static_cast<OGRCurve **>(
     117           8 :                 VSI_MALLOC2_VERBOSE(sizeof(void *), nCurveCount));
     118             : 
     119           8 :             if (papoCurves)
     120             :             {
     121          22 :                 for (int i = 0; i < nCurveCount; i++)
     122             :                 {
     123          14 :                     papoCurves[i] = other.papoCurves[i]->clone();
     124             :                 }
     125             :             }
     126             :         }
     127             :     }
     128          16 :     return *this;
     129             : }
     130             : 
     131             : /************************************************************************/
     132             : /*                              WkbSize()                               */
     133             : /************************************************************************/
     134             : 
     135         938 : size_t OGRCurveCollection::WkbSize() const
     136             : {
     137         938 :     size_t nSize = 9;
     138             : 
     139        1890 :     for (auto &&poSubGeom : *this)
     140             :     {
     141         952 :         nSize += poSubGeom->WkbSize();
     142             :     }
     143             : 
     144         938 :     return nSize;
     145             : }
     146             : 
     147             : /************************************************************************/
     148             : /*                          addCurveDirectly()                          */
     149             : /************************************************************************/
     150             : 
     151      116828 : OGRErr OGRCurveCollection::addCurveDirectly(OGRGeometry *poGeom,
     152             :                                             OGRCurve *poCurve, int bNeedRealloc)
     153             : {
     154      116828 :     poGeom->HomogenizeDimensionalityWith(poCurve);
     155             : 
     156      116826 :     if (bNeedRealloc)
     157             :     {
     158      115083 :         OGRCurve **papoNewCurves = static_cast<OGRCurve **>(VSI_REALLOC_VERBOSE(
     159             :             papoCurves, sizeof(OGRCurve *) * (nCurveCount + 1)));
     160      115083 :         if (papoNewCurves == nullptr)
     161           0 :             return OGRERR_FAILURE;
     162      115083 :         papoCurves = papoNewCurves;
     163             :     }
     164             : 
     165      116826 :     papoCurves[nCurveCount] = poCurve;
     166             : 
     167      116826 :     nCurveCount++;
     168             : 
     169      116826 :     return OGRERR_NONE;
     170             : }
     171             : 
     172             : /************************************************************************/
     173             : /*                        importPreambleFromWkb()                      */
     174             : /************************************************************************/
     175             : 
     176       42345 : OGRErr OGRCurveCollection::importPreambleFromWkb(
     177             :     OGRGeometry *poGeom, const unsigned char *pabyData, size_t &nSize,
     178             :     size_t &nDataOffset, OGRwkbByteOrder &eByteOrder, size_t nMinSubGeomSize,
     179             :     OGRwkbVariant eWkbVariant)
     180             : {
     181       42345 :     int nCurveCountNew = 0;
     182             : 
     183       42345 :     OGRErr eErr = poGeom->importPreambleOfCollectionFromWkb(
     184             :         pabyData, nSize, nDataOffset, eByteOrder, nMinSubGeomSize,
     185             :         nCurveCountNew, eWkbVariant);
     186       42345 :     if (eErr != OGRERR_NONE)
     187         391 :         return eErr;
     188             : 
     189       41954 :     CPLAssert(nCurveCount == 0);
     190       41954 :     nCurveCount = nCurveCountNew;
     191             : 
     192             :     // coverity[tainted_data]
     193       41954 :     papoCurves = static_cast<OGRCurve **>(
     194       41954 :         VSI_CALLOC_VERBOSE(sizeof(void *), nCurveCount));
     195       41954 :     if (nCurveCount != 0 && papoCurves == nullptr)
     196             :     {
     197           0 :         nCurveCount = 0;
     198           0 :         return OGRERR_NOT_ENOUGH_MEMORY;
     199             :     }
     200             : 
     201       41954 :     return OGRERR_NONE;
     202             : }
     203             : 
     204             : /************************************************************************/
     205             : /*                       importBodyFromWkb()                            */
     206             : /************************************************************************/
     207             : 
     208        1922 : OGRErr OGRCurveCollection::importBodyFromWkb(
     209             :     OGRGeometry *poGeom, const unsigned char *pabyData, size_t nSize,
     210             :     bool bAcceptCompoundCurve,
     211             :     OGRErr (*pfnAddCurveDirectlyFromWkb)(OGRGeometry *poGeom,
     212             :                                          OGRCurve *poCurve),
     213             :     OGRwkbVariant eWkbVariant, size_t &nBytesConsumedOut)
     214             : {
     215        1922 :     nBytesConsumedOut = 0;
     216             :     /* -------------------------------------------------------------------- */
     217             :     /*      Get the Geoms.                                                  */
     218             :     /* -------------------------------------------------------------------- */
     219        1922 :     const int nIter = nCurveCount;
     220        1922 :     nCurveCount = 0;
     221        1922 :     size_t nDataOffset = 0;
     222        3665 :     for (int iGeom = 0; iGeom < nIter; iGeom++)
     223             :     {
     224        1923 :         OGRGeometry *poSubGeom = nullptr;
     225             : 
     226             :         // Parses sub-geometry.
     227        1923 :         const unsigned char *pabySubData = pabyData + nDataOffset;
     228        1923 :         if (nSize < 9 && nSize != static_cast<size_t>(-1))
     229         180 :             return OGRERR_NOT_ENOUGH_DATA;
     230             : 
     231        1921 :         OGRwkbGeometryType eFlattenSubGeomType = wkbUnknown;
     232        1921 :         if (OGRReadWKBGeometryType(pabySubData, eWkbVariant,
     233        1921 :                                    &eFlattenSubGeomType) != OGRERR_NONE)
     234          63 :             return OGRERR_FAILURE;
     235        1858 :         eFlattenSubGeomType = wkbFlatten(eFlattenSubGeomType);
     236             : 
     237        1858 :         OGRErr eErr = OGRERR_NONE;
     238        1858 :         size_t nSubGeomBytesConsumedOut = 0;
     239        5570 :         if ((eFlattenSubGeomType != wkbCompoundCurve &&
     240        1861 :              OGR_GT_IsCurve(eFlattenSubGeomType)) ||
     241           3 :             (bAcceptCompoundCurve && eFlattenSubGeomType == wkbCompoundCurve))
     242             :         {
     243        1856 :             eErr = OGRGeometryFactory::createFromWkb(
     244             :                 pabySubData, nullptr, &poSubGeom, nSize, eWkbVariant,
     245             :                 nSubGeomBytesConsumedOut);
     246             :         }
     247             :         else
     248             :         {
     249           2 :             CPLDebug(
     250             :                 "OGR",
     251             :                 "Cannot add geometry of type (%d) to geometry of type (%d)",
     252           2 :                 eFlattenSubGeomType, poGeom->getGeometryType());
     253           2 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     254             :         }
     255             : 
     256        1856 :         if (eErr == OGRERR_NONE)
     257             :         {
     258        1745 :             CPLAssert(nSubGeomBytesConsumedOut > 0);
     259        1745 :             if (nSize != static_cast<size_t>(-1))
     260             :             {
     261        1745 :                 CPLAssert(nSize >= nSubGeomBytesConsumedOut);
     262        1745 :                 nSize -= nSubGeomBytesConsumedOut;
     263             :             }
     264             : 
     265        1745 :             nDataOffset += nSubGeomBytesConsumedOut;
     266             : 
     267        1745 :             OGRCurve *poCurve = poSubGeom->toCurve();
     268        1745 :             eErr = pfnAddCurveDirectlyFromWkb(poGeom, poCurve);
     269             :         }
     270        1856 :         if (eErr != OGRERR_NONE)
     271             :         {
     272         113 :             delete poSubGeom;
     273         113 :             return eErr;
     274             :         }
     275             :     }
     276        1742 :     nBytesConsumedOut = nDataOffset;
     277             : 
     278        1742 :     return OGRERR_NONE;
     279             : }
     280             : 
     281             : /************************************************************************/
     282             : /*                            exportToWkt()                             */
     283             : /************************************************************************/
     284             : 
     285         213 : std::string OGRCurveCollection::exportToWkt(const OGRGeometry *baseGeom,
     286             :                                             const OGRWktOptions &opts,
     287             :                                             OGRErr *err) const
     288             : {
     289             :     try
     290             :     {
     291         213 :         bool first = true;
     292         426 :         std::string wkt(baseGeom->getGeometryName());
     293             : 
     294         213 :         OGRWktOptions optsModified(opts);
     295         213 :         optsModified.variant = wkbVariantIso;
     296         213 :         wkt += baseGeom->wktTypeString(optsModified.variant);
     297             : 
     298         472 :         for (int i = 0; i < nCurveCount; ++i)
     299             :         {
     300         259 :             OGRGeometry *geom = papoCurves[i];
     301             : 
     302         259 :             OGRErr subgeomErr = OGRERR_NONE;
     303         259 :             std::string tempWkt = geom->exportToWkt(optsModified, &subgeomErr);
     304         259 :             if (subgeomErr != OGRERR_NONE)
     305             :             {
     306           0 :                 if (err)
     307           0 :                     *err = subgeomErr;
     308           0 :                 return std::string();
     309             :             }
     310             : 
     311             :             // A curve collection has a list of linestrings (OGRCompoundCurve),
     312             :             // which should have their leader removed, or a OGRCurvePolygon,
     313             :             // which has leaders for each of its sub-geometries that aren't
     314             :             // linestrings.
     315         259 :             if (tempWkt.compare(0, strlen("LINESTRING"), "LINESTRING") == 0)
     316             :             {
     317         123 :                 auto pos = tempWkt.find('(');
     318         123 :                 if (pos != std::string::npos)
     319         123 :                     tempWkt = tempWkt.substr(pos);
     320             :             }
     321             : 
     322         259 :             if (tempWkt.find("EMPTY") != std::string::npos)
     323           0 :                 continue;
     324             : 
     325         259 :             if (first)
     326         186 :                 wkt += '(';
     327             :             else
     328          73 :                 wkt += ',';
     329         259 :             first = false;
     330         259 :             wkt += tempWkt;
     331             :         }
     332             : 
     333         213 :         if (err)
     334         212 :             *err = OGRERR_NONE;
     335         213 :         if (first)
     336          27 :             wkt += "EMPTY";
     337             :         else
     338         186 :             wkt += ')';
     339         213 :         return wkt;
     340             :     }
     341           0 :     catch (const std::bad_alloc &e)
     342             :     {
     343           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
     344           0 :         if (err)
     345           0 :             *err = OGRERR_FAILURE;
     346           0 :         return std::string();
     347             :     }
     348             : }
     349             : 
     350             : /************************************************************************/
     351             : /*                            exportToWkb()                             */
     352             : /************************************************************************/
     353             : 
     354             : OGRErr
     355         911 : OGRCurveCollection::exportToWkb(const OGRGeometry *poGeom,
     356             :                                 unsigned char *pabyData,
     357             :                                 const OGRwkbExportOptions *psOptions) const
     358             : {
     359         911 :     if (psOptions == nullptr)
     360             :     {
     361             :         static const OGRwkbExportOptions defaultOptions;
     362           0 :         psOptions = &defaultOptions;
     363             :     }
     364             : 
     365             :     /* -------------------------------------------------------------------- */
     366             :     /*      Set the byte order.                                             */
     367             :     /* -------------------------------------------------------------------- */
     368         911 :     pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER(
     369             :         static_cast<unsigned char>(psOptions->eByteOrder));
     370             : 
     371             :     /* -------------------------------------------------------------------- */
     372             :     /*      Set the geometry feature type, ensuring that 3D flag is         */
     373             :     /*      preserved.                                                      */
     374             :     /* -------------------------------------------------------------------- */
     375         911 :     GUInt32 nGType = poGeom->getIsoGeometryType();
     376         911 :     if (psOptions->eWkbVariant == wkbVariantPostGIS1)
     377             :     {
     378           0 :         const bool bIs3D = wkbHasZ(static_cast<OGRwkbGeometryType>(nGType));
     379           0 :         nGType = wkbFlatten(nGType);
     380           0 :         if (nGType == wkbCurvePolygon)
     381           0 :             nGType = POSTGIS15_CURVEPOLYGON;
     382           0 :         if (bIs3D)
     383             :             // Explicitly set wkb25DBit.
     384           0 :             nGType =
     385           0 :                 static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse);
     386             :     }
     387             : 
     388         911 :     if (OGR_SWAP(psOptions->eByteOrder))
     389             :     {
     390           0 :         nGType = CPL_SWAP32(nGType);
     391             :     }
     392             : 
     393         911 :     memcpy(pabyData + 1, &nGType, 4);
     394             : 
     395             :     /* -------------------------------------------------------------------- */
     396             :     /*      Copy in the raw data.                                           */
     397             :     /* -------------------------------------------------------------------- */
     398         911 :     if (OGR_SWAP(psOptions->eByteOrder))
     399             :     {
     400           0 :         const int nCount = CPL_SWAP32(nCurveCount);
     401           0 :         memcpy(pabyData + 5, &nCount, 4);
     402             :     }
     403             :     else
     404             :     {
     405         911 :         memcpy(pabyData + 5, &nCurveCount, 4);
     406             :     }
     407             : 
     408             :     // TODO(schwehr): Where do these 9 values come from?
     409         911 :     size_t nOffset = 9;
     410             : 
     411             :     /* ==================================================================== */
     412             :     /*      Serialize each of the Geoms.                                    */
     413             :     /* ==================================================================== */
     414        1821 :     for (auto &&poSubGeom : *this)
     415             :     {
     416         910 :         poSubGeom->exportToWkb(pabyData + nOffset, psOptions);
     417             : 
     418         910 :         nOffset += poSubGeom->WkbSize();
     419             :     }
     420             : 
     421         911 :     return OGRERR_NONE;
     422             : }
     423             : 
     424             : /************************************************************************/
     425             : /*                               empty()                                */
     426             : /************************************************************************/
     427             : 
     428      341251 : void OGRCurveCollection::empty(OGRGeometry *poGeom)
     429             : {
     430      341251 :     if (papoCurves != nullptr)
     431             :     {
     432      557676 :         for (auto &&poSubGeom : *this)
     433             :         {
     434      280438 :             delete poSubGeom;
     435             :         }
     436      277236 :         CPLFree(papoCurves);
     437             :     }
     438             : 
     439      341250 :     nCurveCount = 0;
     440      341250 :     papoCurves = nullptr;
     441      341250 :     if (poGeom)
     442       60659 :         poGeom->setCoordinateDimension(2);
     443      341250 : }
     444             : 
     445             : /************************************************************************/
     446             : /*                            getEnvelope()                             */
     447             : /************************************************************************/
     448             : 
     449      187189 : void OGRCurveCollection::getEnvelope(OGREnvelope *psEnvelope) const
     450             : {
     451      187189 :     OGREnvelope3D oEnv3D;
     452      187189 :     getEnvelope(&oEnv3D);
     453      187189 :     psEnvelope->MinX = oEnv3D.MinX;
     454      187189 :     psEnvelope->MinY = oEnv3D.MinY;
     455      187189 :     psEnvelope->MaxX = oEnv3D.MaxX;
     456      187189 :     psEnvelope->MaxY = oEnv3D.MaxY;
     457      187189 : }
     458             : 
     459             : /************************************************************************/
     460             : /*                            getEnvelope()                             */
     461             : /************************************************************************/
     462             : 
     463      195109 : void OGRCurveCollection::getEnvelope(OGREnvelope3D *psEnvelope) const
     464             : {
     465      195109 :     OGREnvelope3D oGeomEnv;
     466      195109 :     bool bExtentSet = false;
     467             : 
     468      195109 :     *psEnvelope = OGREnvelope3D();
     469      391139 :     for (int iGeom = 0; iGeom < nCurveCount; iGeom++)
     470             :     {
     471      196030 :         if (!papoCurves[iGeom]->IsEmpty())
     472             :         {
     473      196030 :             bExtentSet = true;
     474      196030 :             papoCurves[iGeom]->getEnvelope(&oGeomEnv);
     475      196030 :             psEnvelope->Merge(oGeomEnv);
     476             :         }
     477             :     }
     478             : 
     479      195109 :     if (!bExtentSet)
     480             :     {
     481             :         // To be backward compatible when called on empty geom
     482           7 :         psEnvelope->MinX = 0.0;
     483           7 :         psEnvelope->MinY = 0.0;
     484           7 :         psEnvelope->MinZ = 0.0;
     485           7 :         psEnvelope->MaxX = 0.0;
     486           7 :         psEnvelope->MaxY = 0.0;
     487           7 :         psEnvelope->MaxZ = 0.0;
     488             :     }
     489      195109 : }
     490             : 
     491             : /************************************************************************/
     492             : /*                               IsEmpty()                              */
     493             : /************************************************************************/
     494             : 
     495      110758 : OGRBoolean OGRCurveCollection::IsEmpty() const
     496             : {
     497      110783 :     for (auto &&poSubGeom : *this)
     498             :     {
     499      110276 :         if (!poSubGeom->IsEmpty())
     500      110251 :             return FALSE;
     501             :     }
     502         507 :     return TRUE;
     503             : }
     504             : 
     505             : /************************************************************************/
     506             : /*                               Equals()                                */
     507             : /************************************************************************/
     508             : 
     509       42223 : OGRBoolean OGRCurveCollection::Equals(const OGRCurveCollection *poOCC) const
     510             : {
     511       42223 :     if (getNumCurves() != poOCC->getNumCurves())
     512           2 :         return FALSE;
     513             : 
     514             :     // Should eventually test the SRS.
     515             : 
     516       70506 :     for (int iGeom = 0; iGeom < nCurveCount; iGeom++)
     517             :     {
     518       42420 :         if (!getCurve(iGeom)->Equals(poOCC->getCurve(iGeom)))
     519       14135 :             return FALSE;
     520             :     }
     521             : 
     522       28086 :     return TRUE;
     523             : }
     524             : 
     525             : /************************************************************************/
     526             : /*                       setCoordinateDimension()                       */
     527             : /************************************************************************/
     528             : 
     529       61521 : void OGRCurveCollection::setCoordinateDimension(OGRGeometry *poGeom,
     530             :                                                 int nNewDimension)
     531             : {
     532       62413 :     for (auto &&poSubGeom : *this)
     533             :     {
     534         892 :         poSubGeom->setCoordinateDimension(nNewDimension);
     535             :     }
     536             : 
     537       61521 :     poGeom->OGRGeometry::setCoordinateDimension(nNewDimension);
     538       61520 : }
     539             : 
     540       80874 : void OGRCurveCollection::set3D(OGRGeometry *poGeom, OGRBoolean bIs3D)
     541             : {
     542       84746 :     for (auto &&poSubGeom : *this)
     543             :     {
     544        3872 :         poSubGeom->set3D(bIs3D);
     545             :     }
     546             : 
     547       80874 :     poGeom->OGRGeometry::set3D(bIs3D);
     548       80874 : }
     549             : 
     550      130225 : void OGRCurveCollection::setMeasured(OGRGeometry *poGeom,
     551             :                                      OGRBoolean bIsMeasured)
     552             : {
     553      134087 :     for (auto &&poSubGeom : *this)
     554             :     {
     555        3862 :         poSubGeom->setMeasured(bIsMeasured);
     556             :     }
     557             : 
     558      130225 :     poGeom->OGRGeometry::setMeasured(bIsMeasured);
     559      130226 : }
     560             : 
     561             : /************************************************************************/
     562             : /*                       assignSpatialReference()                       */
     563             : /************************************************************************/
     564             : 
     565      151361 : void OGRCurveCollection::assignSpatialReference(OGRGeometry *poGeom,
     566             :                                                 const OGRSpatialReference *poSR)
     567             : {
     568      304779 :     for (auto &&poSubGeom : *this)
     569             :     {
     570      153419 :         poSubGeom->assignSpatialReference(poSR);
     571             :     }
     572      151363 :     poGeom->OGRGeometry::assignSpatialReference(poSR);
     573      151363 : }
     574             : 
     575             : /************************************************************************/
     576             : /*                          getNumCurves()                              */
     577             : /************************************************************************/
     578             : 
     579       84446 : int OGRCurveCollection::getNumCurves() const
     580             : {
     581       84446 :     return nCurveCount;
     582             : }
     583             : 
     584             : /************************************************************************/
     585             : /*                           getCurve()                                 */
     586             : /************************************************************************/
     587             : 
     588        8655 : OGRCurve *OGRCurveCollection::getCurve(int i)
     589             : {
     590        8655 :     if (i < 0 || i >= nCurveCount)
     591         111 :         return nullptr;
     592        8544 :     return papoCurves[i];
     593             : }
     594             : 
     595             : /************************************************************************/
     596             : /*                           getCurve()                                 */
     597             : /************************************************************************/
     598             : 
     599       92769 : const OGRCurve *OGRCurveCollection::getCurve(int i) const
     600             : {
     601       92769 :     if (i < 0 || i >= nCurveCount)
     602           3 :         return nullptr;
     603       92766 :     return papoCurves[i];
     604             : }
     605             : 
     606             : /************************************************************************/
     607             : /*                           stealCurve()                               */
     608             : /************************************************************************/
     609             : 
     610           5 : OGRCurve *OGRCurveCollection::stealCurve(int i)
     611             : {
     612           5 :     if (i < 0 || i >= nCurveCount)
     613           0 :         return nullptr;
     614           5 :     OGRCurve *poRet = papoCurves[i];
     615           5 :     if (i < nCurveCount - 1)
     616             :     {
     617           2 :         memmove(papoCurves + i, papoCurves + i + 1,
     618           2 :                 (nCurveCount - i - 1) * sizeof(OGRCurve *));
     619             :     }
     620           5 :     nCurveCount--;
     621           5 :     return poRet;
     622             : }
     623             : 
     624             : /************************************************************************/
     625             : /*                             transform()                              */
     626             : /************************************************************************/
     627             : 
     628         507 : OGRErr OGRCurveCollection::transform(OGRGeometry *poGeom,
     629             :                                      OGRCoordinateTransformation *poCT)
     630             : {
     631        1113 :     for (int iGeom = 0; iGeom < nCurveCount; iGeom++)
     632             :     {
     633         606 :         const OGRErr eErr = papoCurves[iGeom]->transform(poCT);
     634         606 :         if (eErr != OGRERR_NONE)
     635             :         {
     636           0 :             if (iGeom != 0)
     637             :             {
     638           0 :                 CPLDebug("OGR", "OGRCurveCollection::transform() failed for a "
     639             :                                 "geometry other than the first, meaning some "
     640             :                                 "geometries are transformed and some are not!");
     641             : 
     642           0 :                 return OGRERR_FAILURE;
     643             :             }
     644             : 
     645           0 :             return eErr;
     646             :         }
     647             :     }
     648             : 
     649         507 :     poGeom->assignSpatialReference(poCT->GetTargetCS());
     650             : 
     651         507 :     return OGRERR_NONE;
     652             : }
     653             : 
     654             : /************************************************************************/
     655             : /*                            flattenTo2D()                             */
     656             : /************************************************************************/
     657             : 
     658         755 : void OGRCurveCollection::flattenTo2D(OGRGeometry *poGeom)
     659             : {
     660        1576 :     for (auto &&poSubGeom : *this)
     661             :     {
     662         821 :         poSubGeom->flattenTo2D();
     663             :     }
     664             : 
     665         755 :     poGeom->setCoordinateDimension(2);
     666         755 : }
     667             : 
     668             : /************************************************************************/
     669             : /*                              segmentize()                            */
     670             : /************************************************************************/
     671             : 
     672          37 : void OGRCurveCollection::segmentize(double dfMaxLength)
     673             : {
     674          74 :     for (auto &&poSubGeom : *this)
     675             :     {
     676          37 :         poSubGeom->segmentize(dfMaxLength);
     677             :     }
     678          37 : }
     679             : 
     680             : /************************************************************************/
     681             : /*                               swapXY()                               */
     682             : /************************************************************************/
     683             : 
     684          75 : void OGRCurveCollection::swapXY()
     685             : {
     686         150 :     for (auto &&poSubGeom : *this)
     687             :     {
     688          75 :         poSubGeom->swapXY();
     689             :     }
     690          75 : }
     691             : 
     692             : /************************************************************************/
     693             : /*                         hasCurveGeometry()                           */
     694             : /************************************************************************/
     695             : 
     696          94 : OGRBoolean OGRCurveCollection::hasCurveGeometry(int bLookForNonLinear) const
     697             : {
     698         133 :     for (auto &&poSubGeom : *this)
     699             :     {
     700         105 :         if (poSubGeom->hasCurveGeometry(bLookForNonLinear))
     701          66 :             return TRUE;
     702             :     }
     703          28 :     return FALSE;
     704             : }
     705             : 
     706             : /************************************************************************/
     707             : /*                           removeCurve()                              */
     708             : /************************************************************************/
     709             : 
     710             : /**
     711             :  * \brief Remove a geometry from the container.
     712             :  *
     713             :  * Removing a geometry will cause the geometry count to drop by one, and all
     714             :  * "higher" geometries will shuffle down one in index.
     715             :  *
     716             :  * @param iIndex the index of the geometry to delete.  A value of -1 is a
     717             :  * special flag meaning that all geometries should be removed.
     718             :  *
     719             :  * @param bDelete if true the geometry will be deallocated, otherwise it will
     720             :  * not.  The default is true as the container is considered to own the
     721             :  * geometries in it.
     722             :  *
     723             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
     724             :  * out of range.
     725             :  */
     726             : 
     727          18 : OGRErr OGRCurveCollection::removeCurve(int iIndex, bool bDelete)
     728             : 
     729             : {
     730          18 :     if (iIndex < -1 || iIndex >= nCurveCount)
     731           2 :         return OGRERR_FAILURE;
     732             : 
     733             :     // Special case.
     734          16 :     if (iIndex == -1)
     735             :     {
     736           3 :         while (nCurveCount > 0)
     737           2 :             removeCurve(nCurveCount - 1, bDelete);
     738           1 :         return OGRERR_NONE;
     739             :     }
     740             : 
     741          15 :     if (bDelete)
     742          11 :         delete papoCurves[iIndex];
     743             : 
     744          15 :     memmove(papoCurves + iIndex, papoCurves + iIndex + 1,
     745          15 :             sizeof(void *) * (nCurveCount - iIndex - 1));
     746             : 
     747          15 :     nCurveCount--;
     748             : 
     749          15 :     return OGRERR_NONE;
     750             : }
     751             : 
     752             : //! @endcond

Generated by: LCOV version 1.14