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-05-03 15:49:35 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_port.h"
      30             : #include "ogr_geometry.h"
      31             : 
      32             : #include <cstddef>
      33             : 
      34             : #include "cpl_conv.h"
      35             : #include "cpl_error.h"
      36             : #include "ogr_api.h"
      37             : #include "ogr_core.h"
      38             : #include "ogr_p.h"
      39             : 
      40             : /************************************************************************/
      41             : /*                          OGRMultiSurface()                           */
      42             : /************************************************************************/
      43             : 
      44             : /**
      45             :  * \brief Create an empty multi surface collection.
      46             :  */
      47             : 
      48             : OGRMultiSurface::OGRMultiSurface() = default;
      49             : 
      50             : /************************************************************************/
      51             : /*                         ~OGRMultiSurface()                           */
      52             : /************************************************************************/
      53             : 
      54             : OGRMultiSurface::~OGRMultiSurface() = default;
      55             : 
      56             : /************************************************************************/
      57             : /*              OGRMultiSurface( const OGRMultiSurface& )               */
      58             : /************************************************************************/
      59             : 
      60             : /**
      61             :  * \brief Copy constructor.
      62             :  *
      63             :  * Note: before GDAL 2.1, only the default implementation of the constructor
      64             :  * existed, which could be unsafe to use.
      65             :  *
      66             :  * @since GDAL 2.1
      67             :  */
      68             : 
      69             : OGRMultiSurface::OGRMultiSurface(const OGRMultiSurface &) = default;
      70             : 
      71             : /************************************************************************/
      72             : /*                  operator=( const OGRMultiCurve&)                    */
      73             : /************************************************************************/
      74             : 
      75             : /**
      76             :  * \brief Assignment operator.
      77             :  *
      78             :  * Note: before GDAL 2.1, only the default implementation of the operator
      79             :  * existed, which could be unsafe to use.
      80             :  *
      81             :  * @since GDAL 2.1
      82             :  */
      83             : 
      84          13 : OGRMultiSurface &OGRMultiSurface::operator=(const OGRMultiSurface &other)
      85             : {
      86          13 :     if (this != &other)
      87             :     {
      88          12 :         OGRGeometryCollection::operator=(other);
      89             :     }
      90          13 :     return *this;
      91             : }
      92             : 
      93             : /************************************************************************/
      94             : /*                               clone()                                */
      95             : /************************************************************************/
      96             : 
      97         123 : OGRMultiSurface *OGRMultiSurface::clone() const
      98             : 
      99             : {
     100         123 :     return new (std::nothrow) OGRMultiSurface(*this);
     101             : }
     102             : 
     103             : /************************************************************************/
     104             : /*                          getGeometryType()                           */
     105             : /************************************************************************/
     106             : 
     107        3776 : OGRwkbGeometryType OGRMultiSurface::getGeometryType() const
     108             : 
     109             : {
     110        3776 :     if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
     111        3031 :         return wkbMultiSurfaceZM;
     112         745 :     else if (flags & OGR_G_MEASURED)
     113          13 :         return wkbMultiSurfaceM;
     114         732 :     else if (flags & OGR_G_3D)
     115          93 :         return wkbMultiSurfaceZ;
     116             :     else
     117         639 :         return wkbMultiSurface;
     118             : }
     119             : 
     120             : /************************************************************************/
     121             : /*                            getDimension()                            */
     122             : /************************************************************************/
     123             : 
     124           8 : int OGRMultiSurface::getDimension() const
     125             : 
     126             : {
     127           8 :     return 2;
     128             : }
     129             : 
     130             : /************************************************************************/
     131             : /*                          getGeometryName()                           */
     132             : /************************************************************************/
     133             : 
     134         399 : const char *OGRMultiSurface::getGeometryName() const
     135             : 
     136             : {
     137         399 :     return "MULTISURFACE";
     138             : }
     139             : 
     140             : /************************************************************************/
     141             : /*                          isCompatibleSubType()                       */
     142             : /************************************************************************/
     143             : 
     144             : OGRBoolean
     145        1378 : OGRMultiSurface::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
     146             : {
     147        1378 :     OGRwkbGeometryType eFlattenGeomType = wkbFlatten(eGeomType);
     148        1378 :     return eFlattenGeomType == wkbPolygon ||
     149        1378 :            eFlattenGeomType == wkbCurvePolygon;
     150             : }
     151             : 
     152             : /************************************************************************/
     153             : /*                           importFromWkt()                            */
     154             : /*                                                                      */
     155             : /*      Instantiate from well known text format.                        */
     156             : /************************************************************************/
     157             : 
     158        1091 : OGRErr OGRMultiSurface::importFromWkt(const char **ppszInput)
     159             : 
     160             : {
     161        1091 :     int bHasZ = FALSE;
     162        1091 :     int bHasM = FALSE;
     163        1091 :     bool bIsEmpty = false;
     164        1091 :     OGRErr eErr = importPreambleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     165        1091 :     flags = 0;
     166        1091 :     if (eErr != OGRERR_NONE)
     167           5 :         return eErr;
     168        1086 :     if (bHasZ)
     169         179 :         flags |= OGR_G_3D;
     170        1086 :     if (bHasM)
     171         107 :         flags |= OGR_G_MEASURED;
     172        1086 :     if (bIsEmpty)
     173          61 :         return OGRERR_NONE;
     174             : 
     175        1025 :     char szToken[OGR_WKT_TOKEN_MAX] = {};
     176        1025 :     const char *pszInput = *ppszInput;
     177        1025 :     eErr = OGRERR_NONE;
     178             : 
     179             :     // Skip first '('.
     180        1025 :     pszInput = OGRWktReadToken(pszInput, szToken);
     181             : 
     182             :     /* ==================================================================== */
     183             :     /*      Read each surface in turn.  Note that we try to reuse the same  */
     184             :     /*      point list buffer from ring to ring to cut down on              */
     185             :     /*      allocate/deallocate overhead.                                   */
     186             :     /* ==================================================================== */
     187        1025 :     OGRRawPoint *paoPoints = nullptr;
     188        1025 :     int nMaxPoints = 0;
     189        1025 :     double *padfZ = nullptr;
     190             : 
     191         315 :     do
     192             :     {
     193             :         /* --------------------------------------------------------------------
     194             :          */
     195             :         /*      Get the first token, which should be the geometry type. */
     196             :         /* --------------------------------------------------------------------
     197             :          */
     198        1340 :         const char *pszInputBefore = pszInput;
     199        1340 :         pszInput = OGRWktReadToken(pszInput, szToken);
     200             : 
     201        1340 :         OGRSurface *poSurface = nullptr;
     202             : 
     203             :         /* --------------------------------------------------------------------
     204             :          */
     205             :         /*      Do the import. */
     206             :         /* --------------------------------------------------------------------
     207             :          */
     208        1340 :         if (EQUAL(szToken, "("))
     209             :         {
     210        1226 :             OGRPolygon *poPolygon = new OGRPolygon();
     211        1226 :             poSurface = poPolygon;
     212        1226 :             pszInput = pszInputBefore;
     213        1226 :             eErr = poPolygon->importFromWKTListOnly(
     214        1226 :                 &pszInput, bHasZ, bHasM, paoPoints, nMaxPoints, padfZ);
     215             :         }
     216         114 :         else if (EQUAL(szToken, "EMPTY"))
     217             :         {
     218           8 :             poSurface = new OGRPolygon();
     219             :         }
     220             :         // We accept POLYGON() but this is an extension to the BNF, also
     221             :         // accepted by PostGIS.
     222         106 :         else if (STARTS_WITH_CI(szToken, "POLYGON") ||
     223         102 :                  STARTS_WITH_CI(szToken, "CURVEPOLYGON"))
     224             :         {
     225          91 :             OGRGeometry *poGeom = nullptr;
     226          91 :             pszInput = pszInputBefore;
     227             :             eErr =
     228          91 :                 OGRGeometryFactory::createFromWkt(&pszInput, nullptr, &poGeom);
     229          91 :             if (poGeom == nullptr)
     230             :             {
     231           1 :                 eErr = OGRERR_CORRUPT_DATA;
     232           1 :                 break;
     233             :             }
     234          90 :             poSurface = poGeom->toSurface();
     235             :         }
     236             :         else
     237             :         {
     238          15 :             CPLError(CE_Failure, CPLE_AppDefined, "Unexpected token : %s",
     239             :                      szToken);
     240          15 :             eErr = OGRERR_CORRUPT_DATA;
     241          15 :             break;
     242             :         }
     243             : 
     244        1324 :         if (eErr == OGRERR_NONE)
     245        1310 :             eErr = addGeometryDirectly(poSurface);
     246        1324 :         if (eErr != OGRERR_NONE)
     247             :         {
     248          14 :             delete poSurface;
     249          14 :             break;
     250             :         }
     251             : 
     252             :         /* --------------------------------------------------------------------
     253             :          */
     254             :         /*      Read the delimiter following the surface. */
     255             :         /* --------------------------------------------------------------------
     256             :          */
     257        1310 :         pszInput = OGRWktReadToken(pszInput, szToken);
     258        1310 :     } while (szToken[0] == ',' && eErr == OGRERR_NONE);
     259             : 
     260        1025 :     CPLFree(paoPoints);
     261        1025 :     CPLFree(padfZ);
     262             : 
     263             :     /* -------------------------------------------------------------------- */
     264             :     /*      freak if we don't get a closing bracket.                        */
     265             :     /* -------------------------------------------------------------------- */
     266             : 
     267        1025 :     if (eErr != OGRERR_NONE)
     268          30 :         return eErr;
     269             : 
     270         995 :     if (szToken[0] != ')')
     271           3 :         return OGRERR_CORRUPT_DATA;
     272             : 
     273         992 :     *ppszInput = pszInput;
     274         992 :     return OGRERR_NONE;
     275             : }
     276             : 
     277             : /************************************************************************/
     278             : /*                            exportToWkt()                             */
     279             : /************************************************************************/
     280             : 
     281          74 : std::string OGRMultiSurface::exportToWkt(const OGRWktOptions &opts,
     282             :                                          OGRErr *err) const
     283             : {
     284          74 :     OGRWktOptions optsModified(opts);
     285          74 :     optsModified.variant = wkbVariantIso;
     286          74 :     return exportToWktInternal(optsModified, err, "POLYGON");
     287             : }
     288             : 
     289             : /************************************************************************/
     290             : /*                         hasCurveGeometry()                           */
     291             : /************************************************************************/
     292             : 
     293        1192 : OGRBoolean OGRMultiSurface::hasCurveGeometry(int bLookForNonLinear) const
     294             : {
     295        1192 :     if (bLookForNonLinear)
     296          11 :         return OGRGeometryCollection::hasCurveGeometry(TRUE);
     297        1181 :     return TRUE;
     298             : }
     299             : 
     300             : /************************************************************************/
     301             : /*                            PointOnSurface()                          */
     302             : /************************************************************************/
     303             : 
     304             : /** \brief This method relates to the SFCOM
     305             :  * IMultiSurface::get_PointOnSurface() method.
     306             :  *
     307             :  * NOTE: Only implemented when GEOS included in build.
     308             :  *
     309             :  * @param poPoint point to be set with an internal point.
     310             :  *
     311             :  * @return OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
     312             :  */
     313             : 
     314           0 : OGRErr OGRMultiSurface::PointOnSurface(OGRPoint *poPoint) const
     315             : {
     316           0 :     return PointOnSurfaceInternal(poPoint);
     317             : }
     318             : 
     319             : /************************************************************************/
     320             : /*                         CastToMultiPolygon()                         */
     321             : /************************************************************************/
     322             : 
     323             : /**
     324             :  * \brief Cast to multipolygon.
     325             :  *
     326             :  * This method should only be called if the multisurface actually only contains
     327             :  * instances of OGRPolygon. This can be verified if hasCurveGeometry(TRUE)
     328             :  * returns FALSE. It is not intended to approximate curve polygons. For that
     329             :  * use getLinearGeometry().
     330             :  *
     331             :  * The passed in geometry is consumed and a new one returned (or NULL in case
     332             :  * of failure).
     333             :  *
     334             :  * @param poMS the input geometry - ownership is passed to the method.
     335             :  * @return new geometry.
     336             :  */
     337             : 
     338          58 : OGRMultiPolygon *OGRMultiSurface::CastToMultiPolygon(OGRMultiSurface *poMS)
     339             : {
     340         118 :     for (auto &&poSubGeom : *poMS)
     341             :     {
     342          60 :         poSubGeom = OGRSurface::CastToPolygon(poSubGeom);
     343          60 :         if (poSubGeom == nullptr)
     344             :         {
     345           0 :             delete poMS;
     346           0 :             return nullptr;
     347             :         }
     348             :     }
     349             : 
     350          58 :     OGRMultiPolygon *poMP = new OGRMultiPolygon();
     351          58 :     TransferMembersAndDestroy(poMS, poMP);
     352          58 :     return poMP;
     353             : }

Generated by: LCOV version 1.14