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

Generated by: LCOV version 1.14