LCOV - code coverage report
Current view: top level - ogr - ogrmultisurface.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 100 106 94.3 %
Date: 2025-01-18 12:42:00 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRMultiSurface 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_conv.h"
      19             : #include "cpl_error.h"
      20             : #include "ogr_api.h"
      21             : #include "ogr_core.h"
      22             : #include "ogr_p.h"
      23             : 
      24             : /************************************************************************/
      25             : /*              OGRMultiSurface( const OGRMultiSurface& )               */
      26             : /************************************************************************/
      27             : 
      28             : /**
      29             :  * \brief Copy constructor.
      30             :  *
      31             :  * Note: before GDAL 2.1, only the default implementation of the constructor
      32             :  * existed, which could be unsafe to use.
      33             :  *
      34             :  * @since GDAL 2.1
      35             :  */
      36             : 
      37             : OGRMultiSurface::OGRMultiSurface(const OGRMultiSurface &) = default;
      38             : 
      39             : /************************************************************************/
      40             : /*                  operator=( const OGRMultiCurve&)                    */
      41             : /************************************************************************/
      42             : 
      43             : /**
      44             :  * \brief Assignment operator.
      45             :  *
      46             :  * Note: before GDAL 2.1, only the default implementation of the operator
      47             :  * existed, which could be unsafe to use.
      48             :  *
      49             :  * @since GDAL 2.1
      50             :  */
      51             : 
      52          13 : OGRMultiSurface &OGRMultiSurface::operator=(const OGRMultiSurface &other)
      53             : {
      54          13 :     if (this != &other)
      55             :     {
      56          12 :         OGRGeometryCollection::operator=(other);
      57             :     }
      58          13 :     return *this;
      59             : }
      60             : 
      61             : /************************************************************************/
      62             : /*                               clone()                                */
      63             : /************************************************************************/
      64             : 
      65         125 : OGRMultiSurface *OGRMultiSurface::clone() const
      66             : 
      67             : {
      68         125 :     auto ret = new (std::nothrow) OGRMultiSurface(*this);
      69         125 :     if (ret)
      70             :     {
      71         125 :         if (ret->WkbSize() != WkbSize())
      72             :         {
      73           0 :             delete ret;
      74           0 :             ret = nullptr;
      75             :         }
      76             :     }
      77         125 :     return ret;
      78             : }
      79             : 
      80             : /************************************************************************/
      81             : /*                          getGeometryType()                           */
      82             : /************************************************************************/
      83             : 
      84        3790 : OGRwkbGeometryType OGRMultiSurface::getGeometryType() const
      85             : 
      86             : {
      87        3790 :     if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
      88        3031 :         return wkbMultiSurfaceZM;
      89         759 :     else if (flags & OGR_G_MEASURED)
      90          13 :         return wkbMultiSurfaceM;
      91         746 :     else if (flags & OGR_G_3D)
      92          97 :         return wkbMultiSurfaceZ;
      93             :     else
      94         649 :         return wkbMultiSurface;
      95             : }
      96             : 
      97             : /************************************************************************/
      98             : /*                            getDimension()                            */
      99             : /************************************************************************/
     100             : 
     101           8 : int OGRMultiSurface::getDimension() const
     102             : 
     103             : {
     104           8 :     return 2;
     105             : }
     106             : 
     107             : /************************************************************************/
     108             : /*                          getGeometryName()                           */
     109             : /************************************************************************/
     110             : 
     111         406 : const char *OGRMultiSurface::getGeometryName() const
     112             : 
     113             : {
     114         406 :     return "MULTISURFACE";
     115             : }
     116             : 
     117             : /************************************************************************/
     118             : /*                          isCompatibleSubType()                       */
     119             : /************************************************************************/
     120             : 
     121             : OGRBoolean
     122        1388 : OGRMultiSurface::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
     123             : {
     124        1388 :     OGRwkbGeometryType eFlattenGeomType = wkbFlatten(eGeomType);
     125        1388 :     return eFlattenGeomType == wkbPolygon ||
     126        1388 :            eFlattenGeomType == wkbCurvePolygon;
     127             : }
     128             : 
     129             : /************************************************************************/
     130             : /*                           importFromWkt()                            */
     131             : /*                                                                      */
     132             : /*      Instantiate from well known text format.                        */
     133             : /************************************************************************/
     134             : 
     135        1139 : OGRErr OGRMultiSurface::importFromWkt(const char **ppszInput)
     136             : 
     137             : {
     138        1139 :     int bHasZ = FALSE;
     139        1139 :     int bHasM = FALSE;
     140        1139 :     bool bIsEmpty = false;
     141        1139 :     OGRErr eErr = importPreambleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     142        1139 :     flags = 0;
     143        1139 :     if (eErr != OGRERR_NONE)
     144           5 :         return eErr;
     145        1134 :     if (bHasZ)
     146         190 :         flags |= OGR_G_3D;
     147        1134 :     if (bHasM)
     148         111 :         flags |= OGR_G_MEASURED;
     149        1134 :     if (bIsEmpty)
     150          73 :         return OGRERR_NONE;
     151             : 
     152        1061 :     char szToken[OGR_WKT_TOKEN_MAX] = {};
     153        1061 :     const char *pszInput = *ppszInput;
     154        1061 :     eErr = OGRERR_NONE;
     155             : 
     156             :     // Skip first '('.
     157        1061 :     pszInput = OGRWktReadToken(pszInput, szToken);
     158             : 
     159             :     /* ==================================================================== */
     160             :     /*      Read each surface in turn.  Note that we try to reuse the same  */
     161             :     /*      point list buffer from ring to ring to cut down on              */
     162             :     /*      allocate/deallocate overhead.                                   */
     163             :     /* ==================================================================== */
     164        1061 :     OGRRawPoint *paoPoints = nullptr;
     165        1061 :     int nMaxPoints = 0;
     166        1061 :     double *padfZ = nullptr;
     167             : 
     168         332 :     do
     169             :     {
     170             :         /* --------------------------------------------------------------------
     171             :          */
     172             :         /*      Get the first token, which should be the geometry type. */
     173             :         /* --------------------------------------------------------------------
     174             :          */
     175        1393 :         const char *pszInputBefore = pszInput;
     176        1393 :         pszInput = OGRWktReadToken(pszInput, szToken);
     177             : 
     178        1393 :         OGRSurface *poSurface = nullptr;
     179             : 
     180             :         /* --------------------------------------------------------------------
     181             :          */
     182             :         /*      Do the import. */
     183             :         /* --------------------------------------------------------------------
     184             :          */
     185        1393 :         if (EQUAL(szToken, "("))
     186             :         {
     187        1275 :             OGRPolygon *poPolygon = new OGRPolygon();
     188        1275 :             poSurface = poPolygon;
     189        1275 :             pszInput = pszInputBefore;
     190        1275 :             eErr = poPolygon->importFromWKTListOnly(
     191        1275 :                 &pszInput, bHasZ, bHasM, paoPoints, nMaxPoints, padfZ);
     192             :         }
     193         118 :         else if (EQUAL(szToken, "EMPTY"))
     194             :         {
     195          12 :             poSurface = new OGRPolygon();
     196             :         }
     197             :         // We accept POLYGON() but this is an extension to the BNF, also
     198             :         // accepted by PostGIS.
     199         106 :         else if (STARTS_WITH_CI(szToken, "POLYGON") ||
     200         102 :                  STARTS_WITH_CI(szToken, "CURVEPOLYGON"))
     201             :         {
     202          91 :             OGRGeometry *poGeom = nullptr;
     203          91 :             pszInput = pszInputBefore;
     204             :             eErr =
     205          91 :                 OGRGeometryFactory::createFromWkt(&pszInput, nullptr, &poGeom);
     206          91 :             if (poGeom == nullptr)
     207             :             {
     208           1 :                 eErr = OGRERR_CORRUPT_DATA;
     209           1 :                 break;
     210             :             }
     211          90 :             poSurface = poGeom->toSurface();
     212             :         }
     213             :         else
     214             :         {
     215          15 :             CPLError(CE_Failure, CPLE_AppDefined, "Unexpected token : %s",
     216             :                      szToken);
     217          15 :             eErr = OGRERR_CORRUPT_DATA;
     218          15 :             break;
     219             :         }
     220             : 
     221        1377 :         if (eErr == OGRERR_NONE)
     222        1363 :             eErr = addGeometryDirectly(poSurface);
     223        1377 :         if (eErr != OGRERR_NONE)
     224             :         {
     225          14 :             delete poSurface;
     226          14 :             break;
     227             :         }
     228             : 
     229             :         /* --------------------------------------------------------------------
     230             :          */
     231             :         /*      Read the delimiter following the surface. */
     232             :         /* --------------------------------------------------------------------
     233             :          */
     234        1363 :         pszInput = OGRWktReadToken(pszInput, szToken);
     235        1363 :     } while (szToken[0] == ',' && eErr == OGRERR_NONE);
     236             : 
     237        1061 :     CPLFree(paoPoints);
     238        1061 :     CPLFree(padfZ);
     239             : 
     240             :     /* -------------------------------------------------------------------- */
     241             :     /*      freak if we don't get a closing bracket.                        */
     242             :     /* -------------------------------------------------------------------- */
     243             : 
     244        1061 :     if (eErr != OGRERR_NONE)
     245          30 :         return eErr;
     246             : 
     247        1031 :     if (szToken[0] != ')')
     248           3 :         return OGRERR_CORRUPT_DATA;
     249             : 
     250        1028 :     *ppszInput = pszInput;
     251        1028 :     return OGRERR_NONE;
     252             : }
     253             : 
     254             : /************************************************************************/
     255             : /*                            exportToWkt()                             */
     256             : /************************************************************************/
     257             : 
     258          77 : std::string OGRMultiSurface::exportToWkt(const OGRWktOptions &opts,
     259             :                                          OGRErr *err) const
     260             : {
     261          77 :     OGRWktOptions optsModified(opts);
     262          77 :     optsModified.variant = wkbVariantIso;
     263          77 :     return exportToWktInternal(optsModified, err, "POLYGON");
     264             : }
     265             : 
     266             : /************************************************************************/
     267             : /*                         hasCurveGeometry()                           */
     268             : /************************************************************************/
     269             : 
     270        1197 : OGRBoolean OGRMultiSurface::hasCurveGeometry(int bLookForNonLinear) const
     271             : {
     272        1197 :     if (bLookForNonLinear)
     273          11 :         return OGRGeometryCollection::hasCurveGeometry(TRUE);
     274        1186 :     return TRUE;
     275             : }
     276             : 
     277             : /************************************************************************/
     278             : /*                            PointOnSurface()                          */
     279             : /************************************************************************/
     280             : 
     281             : /** \brief This method relates to the SFCOM
     282             :  * IMultiSurface::get_PointOnSurface() method.
     283             :  *
     284             :  * NOTE: Only implemented when GEOS included in build.
     285             :  *
     286             :  * @param poPoint point to be set with an internal point.
     287             :  *
     288             :  * @return OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
     289             :  */
     290             : 
     291           0 : OGRErr OGRMultiSurface::PointOnSurface(OGRPoint *poPoint) const
     292             : {
     293           0 :     return PointOnSurfaceInternal(poPoint);
     294             : }
     295             : 
     296             : /************************************************************************/
     297             : /*                         CastToMultiPolygon()                         */
     298             : /************************************************************************/
     299             : 
     300             : /**
     301             :  * \brief Cast to multipolygon.
     302             :  *
     303             :  * This method should only be called if the multisurface actually only contains
     304             :  * instances of OGRPolygon. This can be verified if hasCurveGeometry(TRUE)
     305             :  * returns FALSE. It is not intended to approximate curve polygons. For that
     306             :  * use getLinearGeometry().
     307             :  *
     308             :  * The passed in geometry is consumed and a new one returned (or NULL in case
     309             :  * of failure).
     310             :  *
     311             :  * @param poMS the input geometry - ownership is passed to the method.
     312             :  * @return new geometry.
     313             :  */
     314             : 
     315          62 : OGRMultiPolygon *OGRMultiSurface::CastToMultiPolygon(OGRMultiSurface *poMS)
     316             : {
     317         128 :     for (auto &&poSubGeom : *poMS)
     318             :     {
     319          66 :         poSubGeom = OGRSurface::CastToPolygon(poSubGeom);
     320          66 :         if (poSubGeom == nullptr)
     321             :         {
     322           0 :             delete poMS;
     323           0 :             return nullptr;
     324             :         }
     325             :     }
     326             : 
     327          62 :     OGRMultiPolygon *poMP = new OGRMultiPolygon();
     328          62 :     TransferMembersAndDestroy(poMS, poMP);
     329          62 :     return poMP;
     330             : }

Generated by: LCOV version 1.14