LCOV - code coverage report
Current view: top level - ogr - ogrcurvepolygon.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 239 253 94.5 %
Date: 2024-11-21 22:18:42 Functions: 54 56 96.4 %

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

Generated by: LCOV version 1.14