LCOV - code coverage report
Current view: top level - ogr - ogrcurvepolygon.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 212 227 93.4 %
Date: 2024-05-04 12:52:34 Functions: 49 51 96.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRCurvePolygon geometry 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             : 
      34             : #include "cpl_error.h"
      35             : #include "ogr_api.h"
      36             : #include "ogr_core.h"
      37             : #include "ogr_geos.h"
      38             : #include "ogr_sfcgal.h"
      39             : #include "ogr_p.h"
      40             : #include "ogr_spatialref.h"
      41             : 
      42             : /************************************************************************/
      43             : /*                            OGRCurvePolygon()                         */
      44             : /************************************************************************/
      45             : 
      46             : /**
      47             :  * \brief Create an empty curve polygon.
      48             :  */
      49             : 
      50             : OGRCurvePolygon::OGRCurvePolygon() = default;
      51             : 
      52             : /************************************************************************/
      53             : /*               OGRCurvePolygon( const OGRCurvePolygon& )              */
      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             : OGRCurvePolygon::OGRCurvePolygon(const OGRCurvePolygon &) = default;
      66             : 
      67             : /************************************************************************/
      68             : /*                           ~OGRCurvePolygon()                         */
      69             : /************************************************************************/
      70             : 
      71             : OGRCurvePolygon::~OGRCurvePolygon() = default;
      72             : 
      73             : /************************************************************************/
      74             : /*                 operator=( const OGRCurvePolygon&)                  */
      75             : /************************************************************************/
      76             : 
      77             : /**
      78             :  * \brief Assignment operator.
      79             :  *
      80             :  * Note: before GDAL 2.1, only the default implementation of the operator
      81             :  * existed, which could be unsafe to use.
      82             :  *
      83             :  * @since GDAL 2.1
      84             :  */
      85             : 
      86          13 : OGRCurvePolygon &OGRCurvePolygon::operator=(const OGRCurvePolygon &other)
      87             : {
      88          13 :     if (this != &other)
      89             :     {
      90          12 :         OGRSurface::operator=(other);
      91             : 
      92          12 :         oCC = other.oCC;
      93             :     }
      94          13 :     return *this;
      95             : }
      96             : 
      97             : /************************************************************************/
      98             : /*                               clone()                                */
      99             : /************************************************************************/
     100             : 
     101         255 : OGRCurvePolygon *OGRCurvePolygon::clone() const
     102             : 
     103             : {
     104         255 :     return new (std::nothrow) OGRCurvePolygon(*this);
     105             : }
     106             : 
     107             : /************************************************************************/
     108             : /*                               empty()                                */
     109             : /************************************************************************/
     110             : 
     111       58396 : void OGRCurvePolygon::empty()
     112             : 
     113             : {
     114       58396 :     oCC.empty(this);
     115       58396 : }
     116             : 
     117             : /************************************************************************/
     118             : /*                          getGeometryType()                           */
     119             : /************************************************************************/
     120             : 
     121        1375 : OGRwkbGeometryType OGRCurvePolygon::getGeometryType() const
     122             : 
     123             : {
     124        1375 :     if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
     125         180 :         return wkbCurvePolygonZM;
     126        1195 :     else if (flags & OGR_G_MEASURED)
     127          11 :         return wkbCurvePolygonM;
     128        1184 :     else if (flags & OGR_G_3D)
     129         106 :         return wkbCurvePolygonZ;
     130             :     else
     131        1078 :         return wkbCurvePolygon;
     132             : }
     133             : 
     134             : /************************************************************************/
     135             : /*                            getDimension()                            */
     136             : /************************************************************************/
     137             : 
     138         132 : int OGRCurvePolygon::getDimension() const
     139             : 
     140             : {
     141         132 :     return 2;
     142             : }
     143             : 
     144             : /************************************************************************/
     145             : /*                            flattenTo2D()                             */
     146             : /************************************************************************/
     147             : 
     148         753 : void OGRCurvePolygon::flattenTo2D()
     149             : 
     150             : {
     151         753 :     oCC.flattenTo2D(this);
     152         753 : }
     153             : 
     154             : /************************************************************************/
     155             : /*                          getGeometryName()                           */
     156             : /************************************************************************/
     157             : 
     158         675 : const char *OGRCurvePolygon::getGeometryName() const
     159             : 
     160             : {
     161         675 :     return "CURVEPOLYGON";
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                         getExteriorRingCurve()                       */
     166             : /************************************************************************/
     167             : 
     168             : /**
     169             :  * \brief Fetch reference to external polygon ring.
     170             :  *
     171             :  * Note that the returned ring pointer is to an internal data object of the
     172             :  * OGRCurvePolygon.  It should not be modified or deleted by the application,
     173             :  * and the pointer is only valid till the polygon is next modified.  Use the
     174             :  * OGRGeometry::clone() method to make a separate copy within the application.
     175             :  *
     176             :  * Relates to the Simple Features for COM (SFCOM) IPolygon::get_ExteriorRing()
     177             :  * method.
     178             :  * TODO(rouault): What does that mean?
     179             :  *
     180             :  * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is
     181             :  * empty.
     182             :  */
     183             : 
     184        8333 : OGRCurve *OGRCurvePolygon::getExteriorRingCurve()
     185             : 
     186             : {
     187        8333 :     return oCC.getCurve(0);
     188             : }
     189             : 
     190             : /**
     191             :  * \brief Fetch reference to external polygon ring.
     192             :  *
     193             :  * Note that the returned ring pointer is to an internal data object of the
     194             :  * OGRCurvePolygon.  It should not be modified or deleted by the application,
     195             :  * and the pointer is only valid till the polygon is next modified.  Use the
     196             :  * OGRGeometry::clone() method to make a separate copy within the application.
     197             :  *
     198             :  * Relates to the SFCOM IPolygon::get_ExteriorRing() method.
     199             :  *
     200             :  * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is
     201             :  * empty.
     202             :  */
     203        7683 : const OGRCurve *OGRCurvePolygon::getExteriorRingCurve() const
     204             : 
     205             : {
     206        7683 :     return oCC.getCurve(0);
     207             : }
     208             : 
     209             : /************************************************************************/
     210             : /*                        getNumInteriorRings()                         */
     211             : /************************************************************************/
     212             : 
     213             : /**
     214             :  * \brief Fetch the number of internal rings.
     215             :  *
     216             :  * Relates to the SFCOM IPolygon::get_NumInteriorRings() method.
     217             :  *
     218             :  * @return count of internal rings, zero or more.
     219             :  */
     220             : 
     221      162052 : int OGRCurvePolygon::getNumInteriorRings() const
     222             : 
     223             : {
     224      162052 :     if (oCC.nCurveCount > 0)
     225      162041 :         return oCC.nCurveCount - 1;
     226             :     else
     227          11 :         return 0;
     228             : }
     229             : 
     230             : /************************************************************************/
     231             : /*                       getInteriorRingCurve()                         */
     232             : /************************************************************************/
     233             : 
     234             : /**
     235             :  * \brief Fetch reference to indicated internal ring.
     236             :  *
     237             :  * Note that the returned ring pointer is to an internal data object of the
     238             :  * OGRCurvePolygon.  It should not be modified or deleted by the application,
     239             :  * and the pointer is only valid till the polygon is next modified.  Use the
     240             :  * OGRGeometry::clone() method to make a separate copy within the application.
     241             :  *
     242             :  * Relates to the SFCOM IPolygon::get_InternalRing() method.
     243             :  *
     244             :  * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
     245             :  *
     246             :  * @return pointer to interior ring.  May be NULL.
     247             :  */
     248             : 
     249          78 : OGRCurve *OGRCurvePolygon::getInteriorRingCurve(int iRing)
     250             : 
     251             : {
     252          78 :     return oCC.getCurve(iRing + 1);
     253             : }
     254             : 
     255             : /**
     256             :  * \brief Fetch reference to indicated internal ring.
     257             :  *
     258             :  * Note that the returned ring pointer is to an internal data object of the
     259             :  * OGRCurvePolygon.  It should not be modified or deleted by the application,
     260             :  * and the pointer is only valid till the polygon is next modified.  Use the
     261             :  * OGRGeometry::clone() method to make a separate copy within the application.
     262             :  *
     263             :  * Relates to the SFCOM IPolygon::get_InternalRing() method.
     264             :  *
     265             :  * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
     266             :  *
     267             :  * @return pointer to interior ring.  May be NULL.
     268             :  */
     269             : 
     270          17 : const OGRCurve *OGRCurvePolygon::getInteriorRingCurve(int iRing) const
     271             : 
     272             : {
     273          17 :     return oCC.getCurve(iRing + 1);
     274             : }
     275             : 
     276             : /************************************************************************/
     277             : /*                        stealExteriorRingCurve()                      */
     278             : /************************************************************************/
     279             : 
     280             : /**
     281             :  * \brief "Steal" reference to external ring.
     282             :  *
     283             :  * After the call to that function, only call to stealInteriorRing() or
     284             :  * destruction of the OGRCurvePolygon is valid. Other operations may crash.
     285             :  *
     286             :  * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is
     287             :  * empty.
     288             :  */
     289             : 
     290         858 : OGRCurve *OGRCurvePolygon::stealExteriorRingCurve()
     291             : {
     292         858 :     if (oCC.nCurveCount == 0)
     293           2 :         return nullptr;
     294         856 :     OGRCurve *poRet = oCC.papoCurves[0];
     295         856 :     oCC.papoCurves[0] = nullptr;
     296         856 :     return poRet;
     297             : }
     298             : 
     299             : /************************************************************************/
     300             : /*                            removeRing()                              */
     301             : /************************************************************************/
     302             : 
     303             : /**
     304             :  * \brief Remove a geometry from the container.
     305             :  *
     306             :  * Removing a geometry will cause the geometry count to drop by one, and all
     307             :  * "higher" geometries will shuffle down one in index.
     308             :  *
     309             :  * There is no SFCOM analog to this method.
     310             :  *
     311             :  * @param iIndex the index of the geometry to delete.  A value of -1 is a
     312             :  * special flag meaning that all geometries should be removed.
     313             :  *
     314             :  * @param bDelete if true the geometry will be deallocated, otherwise it will
     315             :  * not.  The default is true as the container is considered to own the
     316             :  * geometries in it.
     317             :  *
     318             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
     319             :  * out of range.
     320             :  */
     321             : 
     322          16 : OGRErr OGRCurvePolygon::removeRing(int iIndex, bool bDelete)
     323             : {
     324          16 :     return oCC.removeCurve(iIndex, bDelete);
     325             : }
     326             : 
     327             : /************************************************************************/
     328             : /*                              addRing()                               */
     329             : /************************************************************************/
     330             : 
     331             : /**
     332             :  * \brief Add a ring to a polygon.
     333             :  *
     334             :  * If the polygon has no external ring (it is empty) this will be used as
     335             :  * the external ring, otherwise it is used as an internal ring.  The passed
     336             :  * OGRCurve remains the responsibility of the caller (an internal copy
     337             :  * is made).
     338             :  *
     339             :  * This method has no SFCOM analog.
     340             :  *
     341             :  * @param poNewRing ring to be added to the polygon.
     342             :  * @return OGRERR_NONE in case of success
     343             :  */
     344             : 
     345       49884 : OGRErr OGRCurvePolygon::addRing(OGRCurve *poNewRing)
     346             : 
     347             : {
     348       49884 :     OGRCurve *poNewRingCloned = poNewRing->clone();
     349       49883 :     OGRErr eErr = addRingDirectly(poNewRingCloned);
     350       49884 :     if (eErr != OGRERR_NONE)
     351           0 :         delete poNewRingCloned;
     352       49883 :     return eErr;
     353             : }
     354             : 
     355             : /************************************************************************/
     356             : /*                            checkRing()                               */
     357             : /************************************************************************/
     358             : 
     359         625 : int OGRCurvePolygon::checkRing(OGRCurve *poNewRing) const
     360             : {
     361         625 :     if (!poNewRing->IsEmpty() && !poNewRing->get_IsClosed())
     362             :     {
     363             :         // This configuration option name must be the same as in
     364             :         // OGRPolygon::checkRing()
     365             :         const char *pszEnvVar =
     366           7 :             CPLGetConfigOption("OGR_GEOMETRY_ACCEPT_UNCLOSED_RING", nullptr);
     367           7 :         if (pszEnvVar != nullptr && !CPLTestBool(pszEnvVar))
     368             :         {
     369           1 :             CPLError(CE_Failure, CPLE_AppDefined, "Non closed ring detected.");
     370           1 :             return FALSE;
     371             :         }
     372             :         else
     373             :         {
     374           6 :             CPLError(CE_Warning, CPLE_AppDefined, "Non closed ring detected.%s",
     375             :                      pszEnvVar == nullptr
     376             :                          ? " To avoid accepting it, set the "
     377             :                            "OGR_GEOMETRY_ACCEPT_UNCLOSED_RING configuration "
     378             :                            "option to NO"
     379             :                          : "");
     380             :         }
     381             :     }
     382             : 
     383         624 :     if (wkbFlatten(poNewRing->getGeometryType()) == wkbLineString)
     384             :     {
     385         202 :         if (poNewRing->getNumPoints() < 4)
     386             :         {
     387           8 :             return FALSE;
     388             :         }
     389             : 
     390         194 :         if (EQUAL(poNewRing->getGeometryName(), "LINEARRING"))
     391             :         {
     392           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Linearring not allowed.");
     393           0 :             return FALSE;
     394             :         }
     395             :     }
     396             : 
     397         616 :     return TRUE;
     398             : }
     399             : 
     400             : /************************************************************************/
     401             : /*                          addRingDirectly()                           */
     402             : /************************************************************************/
     403             : 
     404             : /**
     405             :  * \brief Add a ring to a polygon.
     406             :  *
     407             :  * If the polygon has no external ring (it is empty) this will be used as
     408             :  * the external ring, otherwise it is used as an internal ring.  Ownership
     409             :  * of the passed ring is assumed by the OGRCurvePolygon, but otherwise this
     410             :  * method operates the same as OGRCurvePolygon::AddRing().
     411             :  *
     412             :  * This method has no SFCOM analog.
     413             :  *
     414             :  * @param poNewRing ring to be added to the polygon.
     415             :  * @return OGRERR_NONE in case of success
     416             :  */
     417             : 
     418      109444 : OGRErr OGRCurvePolygon::addRingDirectly(OGRCurve *poNewRing)
     419             : {
     420      109444 :     return addRingDirectlyInternal(poNewRing, TRUE);
     421             : }
     422             : 
     423      110353 : OGRErr OGRCurvePolygon::addRingDirectlyInternal(OGRCurve *poNewRing,
     424             :                                                 int bNeedRealloc)
     425             : {
     426      110353 :     if (!checkRing(poNewRing))
     427           9 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     428             : 
     429      110343 :     HomogenizeDimensionalityWith(poNewRing);
     430             : 
     431      110343 :     return oCC.addCurveDirectly(this, poNewRing, bNeedRealloc);
     432             : }
     433             : 
     434             : /************************************************************************/
     435             : /*                             addRing()                                */
     436             : /************************************************************************/
     437             : 
     438             : /**
     439             :  * \brief Add a ring to a polygon.
     440             :  *
     441             :  * If the polygon has no external ring (it is empty) this will be used as
     442             :  * the external ring, otherwise it is used as an internal ring.
     443             :  *
     444             :  * This method has no SFCOM analog.
     445             :  *
     446             :  * @param poNewRing ring to be added to the polygon.
     447             :  * @return OGRERR_NONE in case of success
     448             :  */
     449         873 : OGRErr OGRCurvePolygon::addRing(std::unique_ptr<OGRCurve> poNewRing)
     450             : {
     451         873 :     OGRCurve *poNewRingPtr = poNewRing.release();
     452         873 :     OGRErr eErr = addRingDirectlyInternal(poNewRingPtr, TRUE);
     453         873 :     if (eErr != OGRERR_NONE)
     454           0 :         delete poNewRingPtr;
     455         873 :     return eErr;
     456             : }
     457             : 
     458             : /************************************************************************/
     459             : /*                              WkbSize()                               */
     460             : /*                                                                      */
     461             : /*      Return the size of this object in well known binary             */
     462             : /*      representation including the byte order, and type information.  */
     463             : /************************************************************************/
     464             : 
     465          48 : size_t OGRCurvePolygon::WkbSize() const
     466             : 
     467             : {
     468          48 :     return oCC.WkbSize();
     469             : }
     470             : 
     471             : /************************************************************************/
     472             : /*                       addCurveDirectlyFromWkb()                      */
     473             : /************************************************************************/
     474             : 
     475          21 : OGRErr OGRCurvePolygon::addCurveDirectlyFromWkb(OGRGeometry *poSelf,
     476             :                                                 OGRCurve *poCurve)
     477             : {
     478          21 :     OGRCurvePolygon *poCP = poSelf->toCurvePolygon();
     479          21 :     return poCP->addRingDirectlyInternal(poCurve, FALSE);
     480             : }
     481             : 
     482             : /************************************************************************/
     483             : /*                           importFromWkb()                            */
     484             : /*                                                                      */
     485             : /*      Initialize from serialized stream in well known binary          */
     486             : /*      format.                                                         */
     487             : /************************************************************************/
     488             : 
     489          23 : OGRErr OGRCurvePolygon::importFromWkb(const unsigned char *pabyData,
     490             :                                       size_t nSize, OGRwkbVariant eWkbVariant,
     491             :                                       size_t &nBytesConsumedOut)
     492             : 
     493             : {
     494          23 :     nBytesConsumedOut = 0;
     495             :     OGRwkbByteOrder eByteOrder;
     496          23 :     size_t nDataOffset = 0;
     497             :     // coverity[tainted_data]
     498          23 :     OGRErr eErr = oCC.importPreambleFromWkb(this, pabyData, nSize, nDataOffset,
     499             :                                             eByteOrder, 9, eWkbVariant);
     500          23 :     if (eErr != OGRERR_NONE)
     501           0 :         return eErr;
     502             : 
     503          23 :     eErr = oCC.importBodyFromWkb(this, pabyData + nDataOffset, nSize,
     504             :                                  true,  // bAcceptCompoundCurve
     505             :                                  addCurveDirectlyFromWkb, eWkbVariant,
     506             :                                  nBytesConsumedOut);
     507          23 :     if (eErr == OGRERR_NONE)
     508          23 :         nBytesConsumedOut += nDataOffset;
     509          23 :     return eErr;
     510             : }
     511             : 
     512             : /************************************************************************/
     513             : /*                            exportToWkb()                             */
     514             : /*                                                                      */
     515             : /*      Build a well known binary representation of this object.        */
     516             : /************************************************************************/
     517             : 
     518          32 : OGRErr OGRCurvePolygon::exportToWkb(unsigned char *pabyData,
     519             :                                     const OGRwkbExportOptions *psOptions) const
     520             : {
     521             :     OGRwkbExportOptions sOptions(psOptions ? *psOptions
     522          32 :                                            : OGRwkbExportOptions());
     523             : 
     524             :     // Does not make sense for new geometries, so patch it.
     525          32 :     if (sOptions.eWkbVariant == wkbVariantOldOgc)
     526          14 :         sOptions.eWkbVariant = wkbVariantIso;
     527          64 :     return oCC.exportToWkb(this, pabyData, &sOptions);
     528             : }
     529             : 
     530             : /************************************************************************/
     531             : /*                       addCurveDirectlyFromWkt()                      */
     532             : /************************************************************************/
     533             : 
     534         341 : OGRErr OGRCurvePolygon::addCurveDirectlyFromWkt(OGRGeometry *poSelf,
     535             :                                                 OGRCurve *poCurve)
     536             : {
     537         341 :     OGRCurvePolygon *poCP = poSelf->toCurvePolygon();
     538         341 :     return poCP->addRingDirectly(poCurve);
     539             : }
     540             : 
     541             : /************************************************************************/
     542             : /*                           importFromWkt()                            */
     543             : /*                                                                      */
     544             : /*      Instantiate from well known text format.                        */
     545             : /************************************************************************/
     546             : 
     547         319 : OGRErr OGRCurvePolygon::importFromWkt(const char **ppszInput)
     548             : 
     549             : {
     550         319 :     return importCurveCollectionFromWkt(ppszInput,
     551             :                                         FALSE,  // bAllowEmptyComponent
     552             :                                         TRUE,   // bAllowLineString
     553             :                                         TRUE,   // bAllowCurve
     554             :                                         TRUE,   // bAllowCompoundCurve
     555         319 :                                         addCurveDirectlyFromWkt);
     556             : }
     557             : 
     558             : /************************************************************************/
     559             : /*                            exportToWkt()                             */
     560             : /************************************************************************/
     561             : 
     562         112 : std::string OGRCurvePolygon::exportToWkt(const OGRWktOptions &opts,
     563             :                                          OGRErr *err) const
     564             : {
     565         112 :     return oCC.exportToWkt(this, opts, err);
     566             : }
     567             : 
     568             : /************************************************************************/
     569             : /*                           CurvePolyToPoly()                          */
     570             : /************************************************************************/
     571             : 
     572             : /**
     573             :  * \brief Return a polygon from a curve polygon.
     574             :  *
     575             :  * This method is the same as C function OGR_G_CurvePolyToPoly().
     576             :  *
     577             :  * The returned geometry is a new instance whose ownership belongs to
     578             :  * the caller.
     579             :  *
     580             :  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
     581             :  * arc, zero to use the default setting.
     582             :  * @param papszOptions options as a null-terminated list of strings.
     583             :  *                     Unused for now. Must be set to NULL.
     584             :  *
     585             :  * @return a linestring
     586             :  *
     587             :  * @since OGR 2.0
     588             :  */
     589             : 
     590             : OGRPolygon *
     591         405 : OGRCurvePolygon::CurvePolyToPoly(double dfMaxAngleStepSizeDegrees,
     592             :                                  const char *const *papszOptions) const
     593             : {
     594         405 :     OGRPolygon *poPoly = new OGRPolygon();
     595         405 :     poPoly->assignSpatialReference(getSpatialReference());
     596         867 :     for (int iRing = 0; iRing < oCC.nCurveCount; iRing++)
     597             :     {
     598         924 :         OGRLineString *poLS = oCC.papoCurves[iRing]->CurveToLine(
     599         462 :             dfMaxAngleStepSizeDegrees, papszOptions);
     600         462 :         OGRLinearRing *poRing = OGRCurve::CastToLinearRing(poLS);
     601         462 :         if (poRing == nullptr)
     602             :         {
     603           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     604             :                      "OGRCurve::CastToLinearRing failed");
     605           0 :             break;
     606             :         }
     607         462 :         poPoly->addRingDirectly(poRing);
     608             :     }
     609         405 :     return poPoly;
     610             : }
     611             : 
     612             : /************************************************************************/
     613             : /*                         hasCurveGeometry()                           */
     614             : /************************************************************************/
     615             : 
     616         593 : OGRBoolean OGRCurvePolygon::hasCurveGeometry(int bLookForNonLinear) const
     617             : {
     618         593 :     if (bLookForNonLinear)
     619             :     {
     620          57 :         return oCC.hasCurveGeometry(bLookForNonLinear);
     621             :     }
     622             : 
     623         536 :     return TRUE;
     624             : }
     625             : 
     626             : /************************************************************************/
     627             : /*                         getLinearGeometry()                        */
     628             : /************************************************************************/
     629             : 
     630             : OGRGeometry *
     631         376 : OGRCurvePolygon::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
     632             :                                    const char *const *papszOptions) const
     633             : {
     634         376 :     return CurvePolyToPoly(dfMaxAngleStepSizeDegrees, papszOptions);
     635             : }
     636             : 
     637             : /************************************************************************/
     638             : /*                            getEnvelope()                             */
     639             : /************************************************************************/
     640             : 
     641      187171 : void OGRCurvePolygon::getEnvelope(OGREnvelope *psEnvelope) const
     642             : 
     643             : {
     644      187171 :     oCC.getEnvelope(psEnvelope);
     645      187171 : }
     646             : 
     647             : /************************************************************************/
     648             : /*                            getEnvelope()                             */
     649             : /************************************************************************/
     650             : 
     651        7876 : void OGRCurvePolygon::getEnvelope(OGREnvelope3D *psEnvelope) const
     652             : 
     653             : {
     654        7876 :     oCC.getEnvelope(psEnvelope);
     655        7876 : }
     656             : 
     657             : /************************************************************************/
     658             : /*                               Equals()                               */
     659             : /************************************************************************/
     660             : 
     661       41363 : OGRBoolean OGRCurvePolygon::Equals(const OGRGeometry *poOther) const
     662             : 
     663             : {
     664       41363 :     if (poOther == this)
     665           1 :         return TRUE;
     666             : 
     667       41362 :     if (poOther->getGeometryType() != getGeometryType())
     668           1 :         return FALSE;
     669             : 
     670       41361 :     if (IsEmpty() && poOther->IsEmpty())
     671           6 :         return TRUE;
     672             : 
     673       41355 :     return oCC.Equals(&(poOther->toCurvePolygon()->oCC));
     674             : }
     675             : 
     676             : /************************************************************************/
     677             : /*                             transform()                              */
     678             : /************************************************************************/
     679             : 
     680         504 : OGRErr OGRCurvePolygon::transform(OGRCoordinateTransformation *poCT)
     681             : 
     682             : {
     683         504 :     return oCC.transform(this, poCT);
     684             : }
     685             : 
     686             : /************************************************************************/
     687             : /*                              get_Area()                              */
     688             : /************************************************************************/
     689             : 
     690        3726 : double OGRCurvePolygon::get_Area() const
     691             : 
     692             : {
     693        3726 :     if (getExteriorRingCurve() == nullptr)
     694           2 :         return 0.0;
     695             : 
     696        3724 :     double dfArea = getExteriorRingCurve()->get_Area();
     697             : 
     698        3736 :     for (int iRing = 0; iRing < getNumInteriorRings(); iRing++)
     699             :     {
     700          12 :         dfArea -= getInteriorRingCurve(iRing)->get_Area();
     701             :     }
     702             : 
     703        3724 :     return dfArea;
     704             : }
     705             : 
     706             : /************************************************************************/
     707             : /*                        get_GeodesicArea()                            */
     708             : /************************************************************************/
     709             : 
     710          17 : double OGRCurvePolygon::get_GeodesicArea(
     711             :     const OGRSpatialReference *poSRSOverride) const
     712             : 
     713             : {
     714          17 :     if (getExteriorRingCurve() == nullptr)
     715           1 :         return 0.0;
     716             : 
     717          16 :     if (!poSRSOverride)
     718          13 :         poSRSOverride = getSpatialReference();
     719             : 
     720          16 :     double dfArea = getExteriorRingCurve()->get_GeodesicArea(poSRSOverride);
     721          16 :     if (dfArea > 0)
     722             :     {
     723          15 :         for (int iRing = 0; iRing < getNumInteriorRings(); iRing++)
     724             :         {
     725           1 :             dfArea -=
     726           1 :                 getInteriorRingCurve(iRing)->get_GeodesicArea(poSRSOverride);
     727             :         }
     728             :     }
     729             : 
     730          16 :     return dfArea;
     731             : }
     732             : 
     733             : /************************************************************************/
     734             : /*                       setCoordinateDimension()                       */
     735             : /************************************************************************/
     736             : 
     737       59252 : void OGRCurvePolygon::setCoordinateDimension(int nNewDimension)
     738             : 
     739             : {
     740       59252 :     oCC.setCoordinateDimension(this, nNewDimension);
     741       59252 : }
     742             : 
     743       76783 : void OGRCurvePolygon::set3D(OGRBoolean bIs3D)
     744             : {
     745       76783 :     oCC.set3D(this, bIs3D);
     746       76783 : }
     747             : 
     748      123963 : void OGRCurvePolygon::setMeasured(OGRBoolean bIsMeasured)
     749             : {
     750      123963 :     oCC.setMeasured(this, bIsMeasured);
     751      123962 : }
     752             : 
     753             : /************************************************************************/
     754             : /*                       assignSpatialReference()                       */
     755             : /************************************************************************/
     756             : 
     757      148923 : void OGRCurvePolygon::assignSpatialReference(const OGRSpatialReference *poSR)
     758             : {
     759      148923 :     oCC.assignSpatialReference(this, poSR);
     760      148923 : }
     761             : 
     762             : /************************************************************************/
     763             : /*                               IsEmpty()                              */
     764             : /************************************************************************/
     765             : 
     766      110031 : OGRBoolean OGRCurvePolygon::IsEmpty() const
     767             : {
     768      110031 :     return oCC.IsEmpty();
     769             : }
     770             : 
     771             : /************************************************************************/
     772             : /*                              segmentize()                            */
     773             : /************************************************************************/
     774             : 
     775          36 : void OGRCurvePolygon::segmentize(double dfMaxLength)
     776             : {
     777          36 :     if (EQUAL(getGeometryName(), "TRIANGLE"))
     778             :     {
     779           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     780             :                  "segmentize() is not valid for Triangle");
     781           0 :         return;
     782             :     }
     783          36 :     oCC.segmentize(dfMaxLength);
     784             : }
     785             : 
     786             : /************************************************************************/
     787             : /*                               swapXY()                               */
     788             : /************************************************************************/
     789             : 
     790          74 : void OGRCurvePolygon::swapXY()
     791             : {
     792          74 :     oCC.swapXY();
     793          74 : }
     794             : 
     795             : /************************************************************************/
     796             : /*                           ContainsPoint()                             */
     797             : /************************************************************************/
     798             : 
     799          15 : OGRBoolean OGRCurvePolygon::ContainsPoint(const OGRPoint *p) const
     800             : {
     801          15 :     if (getExteriorRingCurve() != nullptr && getNumInteriorRings() == 0)
     802             :     {
     803          15 :         const int nRet = getExteriorRingCurve()->ContainsPoint(p);
     804          15 :         if (nRet >= 0)
     805           5 :             return nRet;
     806             :     }
     807             : 
     808          10 :     return OGRGeometry::Contains(p);
     809             : }
     810             : 
     811             : /************************************************************************/
     812             : /*                          IntersectsPoint()                           */
     813             : /************************************************************************/
     814             : 
     815           3 : OGRBoolean OGRCurvePolygon::IntersectsPoint(const OGRPoint *p) const
     816             : {
     817           3 :     if (getExteriorRingCurve() != nullptr && getNumInteriorRings() == 0)
     818             :     {
     819           3 :         const int nRet = getExteriorRingCurve()->IntersectsPoint(p);
     820           3 :         if (nRet >= 0)
     821           2 :             return nRet;
     822             :     }
     823             : 
     824           1 :     return OGRGeometry::Intersects(p);
     825             : }
     826             : 
     827             : /************************************************************************/
     828             : /*                               Contains()                             */
     829             : /************************************************************************/
     830             : 
     831          29 : OGRBoolean OGRCurvePolygon::Contains(const OGRGeometry *poOtherGeom) const
     832             : 
     833             : {
     834          58 :     if (!IsEmpty() && poOtherGeom != nullptr &&
     835          29 :         wkbFlatten(poOtherGeom->getGeometryType()) == wkbPoint)
     836             :     {
     837          15 :         return ContainsPoint(poOtherGeom->toPoint());
     838             :     }
     839             : 
     840          14 :     return OGRGeometry::Contains(poOtherGeom);
     841             : }
     842             : 
     843             : /************************************************************************/
     844             : /*                              Intersects()                            */
     845             : /************************************************************************/
     846             : 
     847          10 : OGRBoolean OGRCurvePolygon::Intersects(const OGRGeometry *poOtherGeom) const
     848             : 
     849             : {
     850          20 :     if (!IsEmpty() && poOtherGeom != nullptr &&
     851          10 :         wkbFlatten(poOtherGeom->getGeometryType()) == wkbPoint)
     852             :     {
     853           3 :         return IntersectsPoint(poOtherGeom->toPoint());
     854             :     }
     855             : 
     856           7 :     return OGRGeometry::Intersects(poOtherGeom);
     857             : }
     858             : 
     859             : /************************************************************************/
     860             : /*                           CastToPolygon()                            */
     861             : /************************************************************************/
     862             : 
     863             : /**
     864             :  * \brief Convert to polygon.
     865             :  *
     866             :  * This method should only be called if the curve polygon actually only contains
     867             :  * instances of OGRLineString. This can be verified if hasCurveGeometry(TRUE)
     868             :  * returns FALSE. It is not intended to approximate curve polygons. For that
     869             :  * use getLinearGeometry().
     870             :  *
     871             :  * The passed in geometry is consumed and a new one returned (or NULL in case
     872             :  * of failure).
     873             :  *
     874             :  * @param poCP the input geometry - ownership is passed to the method.
     875             :  * @return new geometry.
     876             :  */
     877             : 
     878          15 : OGRPolygon *OGRCurvePolygon::CastToPolygon(OGRCurvePolygon *poCP)
     879             : {
     880          29 :     for (int i = 0; i < poCP->oCC.nCurveCount; i++)
     881             :     {
     882          28 :         poCP->oCC.papoCurves[i] =
     883          14 :             OGRCurve::CastToLinearRing(poCP->oCC.papoCurves[i]);
     884          14 :         if (poCP->oCC.papoCurves[i] == nullptr)
     885             :         {
     886           0 :             delete poCP;
     887           0 :             return nullptr;
     888             :         }
     889             :     }
     890          15 :     OGRPolygon *poPoly = new OGRPolygon();
     891          15 :     poPoly->setCoordinateDimension(poCP->getCoordinateDimension());
     892          15 :     poPoly->assignSpatialReference(poCP->getSpatialReference());
     893          15 :     poPoly->oCC.nCurveCount = poCP->oCC.nCurveCount;
     894          15 :     poPoly->oCC.papoCurves = poCP->oCC.papoCurves;
     895          15 :     poCP->oCC.nCurveCount = 0;
     896          15 :     poCP->oCC.papoCurves = nullptr;
     897          15 :     delete poCP;
     898          15 :     return poPoly;
     899             : }
     900             : 
     901             : //! @cond Doxygen_Suppress
     902             : /************************************************************************/
     903             : /*                      GetCasterToPolygon()                            */
     904             : /************************************************************************/
     905             : 
     906          15 : OGRPolygon *OGRCurvePolygon::CasterToPolygon(OGRSurface *poSurface)
     907             : {
     908          15 :     OGRCurvePolygon *poCurvePoly = poSurface->toCurvePolygon();
     909          15 :     return OGRCurvePolygon::CastToPolygon(poCurvePoly);
     910             : }
     911             : 
     912          15 : OGRSurfaceCasterToPolygon OGRCurvePolygon::GetCasterToPolygon() const
     913             : {
     914          15 :     return OGRCurvePolygon::CasterToPolygon;
     915             : }
     916             : 
     917             : /************************************************************************/
     918             : /*                      GetCasterToCurvePolygon()                       */
     919             : /************************************************************************/
     920             : 
     921           0 : static OGRCurvePolygon *CasterToCurvePolygon(OGRSurface *poSurface)
     922             : {
     923           0 :     return poSurface->toCurvePolygon();
     924             : }
     925             : 
     926           0 : OGRSurfaceCasterToCurvePolygon OGRCurvePolygon::GetCasterToCurvePolygon() const
     927             : {
     928           0 :     return ::CasterToCurvePolygon;
     929             : }
     930             : 
     931             : //! @endcond

Generated by: LCOV version 1.14