LCOV - code coverage report
Current view: top level - ogr - ogrmultipoint.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 149 172 86.6 %
Date: 2024-05-04 12:52:34 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRMultiPoint class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_port.h"
      31             : #include "ogr_geometry.h"
      32             : 
      33             : #include <cstddef>
      34             : #include <cstdio>
      35             : #include <cstring>
      36             : #include <new>
      37             : 
      38             : #include "cpl_conv.h"
      39             : #include "cpl_error.h"
      40             : #include "cpl_vsi.h"
      41             : #include "ogr_core.h"
      42             : #include "ogr_p.h"
      43             : 
      44             : /************************************************************************/
      45             : /*                           OGRMultiPoint()                            */
      46             : /************************************************************************/
      47             : 
      48             : /**
      49             :  * \brief Create an empty multi point collection.
      50             :  */
      51             : 
      52             : OGRMultiPoint::OGRMultiPoint() = default;
      53             : 
      54             : /************************************************************************/
      55             : /*                OGRMultiPoint( const OGRMultiPoint& )                 */
      56             : /************************************************************************/
      57             : 
      58             : /**
      59             :  * \brief Copy constructor.
      60             :  *
      61             :  * Note: before GDAL 2.1, only the default implementation of the constructor
      62             :  * existed, which could be unsafe to use.
      63             :  *
      64             :  * @since GDAL 2.1
      65             :  */
      66             : 
      67             : OGRMultiPoint::OGRMultiPoint(const OGRMultiPoint &) = default;
      68             : 
      69             : /************************************************************************/
      70             : /*                          ~OGRMultiPoint()                            */
      71             : /************************************************************************/
      72             : 
      73             : OGRMultiPoint::~OGRMultiPoint() = default;
      74             : 
      75             : /************************************************************************/
      76             : /*                  operator=( const OGRMultiPoint&)                    */
      77             : /************************************************************************/
      78             : 
      79             : /**
      80             :  * \brief Assignment operator.
      81             :  *
      82             :  * Note: before GDAL 2.1, only the default implementation of the operator
      83             :  * existed, which could be unsafe to use.
      84             :  *
      85             :  * @since GDAL 2.1
      86             :  */
      87             : 
      88           5 : OGRMultiPoint &OGRMultiPoint::operator=(const OGRMultiPoint &other)
      89             : {
      90           5 :     if (this != &other)
      91             :     {
      92           4 :         OGRGeometryCollection::operator=(other);
      93             :     }
      94           5 :     return *this;
      95             : }
      96             : 
      97             : /************************************************************************/
      98             : /*                               clone()                                */
      99             : /************************************************************************/
     100             : 
     101         649 : OGRMultiPoint *OGRMultiPoint::clone() const
     102             : 
     103             : {
     104         649 :     return new (std::nothrow) OGRMultiPoint(*this);
     105             : }
     106             : 
     107             : /************************************************************************/
     108             : /*                          getGeometryType()                           */
     109             : /************************************************************************/
     110             : 
     111       12491 : OGRwkbGeometryType OGRMultiPoint::getGeometryType() const
     112             : 
     113             : {
     114       12491 :     if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
     115        3084 :         return wkbMultiPointZM;
     116        9407 :     else if (flags & OGR_G_MEASURED)
     117         321 :         return wkbMultiPointM;
     118        9086 :     else if (flags & OGR_G_3D)
     119        4374 :         return wkbMultiPoint25D;
     120             :     else
     121        4712 :         return wkbMultiPoint;
     122             : }
     123             : 
     124             : /************************************************************************/
     125             : /*                            getDimension()                            */
     126             : /************************************************************************/
     127             : 
     128           1 : int OGRMultiPoint::getDimension() const
     129             : 
     130             : {
     131           1 :     return 0;
     132             : }
     133             : 
     134             : /************************************************************************/
     135             : /*                          getGeometryName()                           */
     136             : /************************************************************************/
     137             : 
     138        1434 : const char *OGRMultiPoint::getGeometryName() const
     139             : 
     140             : {
     141        1434 :     return "MULTIPOINT";
     142             : }
     143             : 
     144             : /************************************************************************/
     145             : /*                          isCompatibleSubType()                       */
     146             : /************************************************************************/
     147             : 
     148             : OGRBoolean
     149        6395 : OGRMultiPoint::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
     150             : {
     151        6395 :     return wkbFlatten(eGeomType) == wkbPoint;
     152             : }
     153             : 
     154             : /************************************************************************/
     155             : /*                            exportToWkt()                             */
     156             : /*                                                                      */
     157             : /*      Translate this structure into its well known text format        */
     158             : /*      equivalent.                                                     */
     159             : /************************************************************************/
     160             : 
     161         184 : std::string OGRMultiPoint::exportToWkt(const OGRWktOptions &opts,
     162             :                                        OGRErr *err) const
     163             : {
     164             :     try
     165             :     {
     166         368 :         std::string wkt = getGeometryName();
     167         184 :         wkt += wktTypeString(opts.variant);
     168             : 
     169         184 :         bool first(true);
     170             :         // OGRMultiPoint has a begin()/end().
     171         543 :         for (const OGRPoint *poPoint : this)
     172             :         {
     173         359 :             if (poPoint->IsEmpty())
     174           8 :                 continue;
     175             : 
     176         351 :             if (first)
     177         149 :                 wkt += '(';
     178             :             else
     179         202 :                 wkt += ',';
     180         351 :             first = false;
     181             : 
     182         351 :             if (opts.variant == wkbVariantIso)
     183         172 :                 wkt += '(';
     184             : 
     185         702 :             wkt += OGRMakeWktCoordinateM(
     186             :                 poPoint->getX(), poPoint->getY(), poPoint->getZ(),
     187             :                 poPoint->getM(), poPoint->Is3D(),
     188         702 :                 poPoint->IsMeasured() && (opts.variant == wkbVariantIso), opts);
     189             : 
     190         351 :             if (opts.variant == wkbVariantIso)
     191         172 :                 wkt += ')';
     192             :         }
     193             : 
     194         184 :         if (err)
     195         168 :             *err = OGRERR_NONE;
     196         184 :         if (first)
     197          35 :             wkt += "EMPTY";
     198             :         else
     199         149 :             wkt += ')';
     200         184 :         return wkt;
     201             :     }
     202           0 :     catch (const std::bad_alloc &e)
     203             :     {
     204           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
     205           0 :         if (err)
     206           0 :             *err = OGRERR_FAILURE;
     207           0 :         return std::string();
     208             :     }
     209             : }
     210             : 
     211             : /************************************************************************/
     212             : /*                           importFromWkt()                            */
     213             : /************************************************************************/
     214             : 
     215         579 : OGRErr OGRMultiPoint::importFromWkt(const char **ppszInput)
     216             : 
     217             : {
     218         579 :     const char *pszInputBefore = *ppszInput;
     219         579 :     int bHasZ = FALSE;
     220         579 :     int bHasM = FALSE;
     221         579 :     bool bIsEmpty = false;
     222         579 :     OGRErr eErr = importPreambleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     223         579 :     flags = 0;
     224         579 :     if (eErr != OGRERR_NONE)
     225           5 :         return eErr;
     226         574 :     if (bHasZ)
     227          72 :         flags |= OGR_G_3D;
     228         574 :     if (bHasM)
     229          56 :         flags |= OGR_G_MEASURED;
     230         574 :     if (bIsEmpty)
     231          49 :         return OGRERR_NONE;
     232             : 
     233         525 :     char szToken[OGR_WKT_TOKEN_MAX] = {};
     234         525 :     const char *pszInput = *ppszInput;
     235             : 
     236         525 :     const char *pszPreScan = OGRWktReadToken(pszInput, szToken);
     237         525 :     OGRWktReadToken(pszPreScan, szToken);
     238             : 
     239             :     // Do we have an inner bracket?
     240         525 :     if (EQUAL(szToken, "(") || EQUAL(szToken, "EMPTY"))
     241             :     {
     242         150 :         *ppszInput = pszInputBefore;
     243         150 :         return importFromWkt_Bracketed(ppszInput, bHasM, bHasZ);
     244             :     }
     245             : 
     246             :     /* -------------------------------------------------------------------- */
     247             :     /*      Read the point list.                                            */
     248             :     /* -------------------------------------------------------------------- */
     249         375 :     OGRRawPoint *paoPoints = nullptr;
     250         375 :     double *padfZ = nullptr;
     251         375 :     double *padfM = nullptr;
     252         375 :     int flagsFromInput = flags;
     253         375 :     int nMaxPoint = 0;
     254         375 :     int nPointCount = 0;
     255             : 
     256         375 :     pszInput = OGRWktReadPointsM(pszInput, &paoPoints, &padfZ, &padfM,
     257             :                                  &flagsFromInput, &nMaxPoint, &nPointCount);
     258         375 :     if (pszInput == nullptr)
     259             :     {
     260          11 :         CPLFree(paoPoints);
     261          11 :         CPLFree(padfZ);
     262          11 :         CPLFree(padfM);
     263          11 :         return OGRERR_CORRUPT_DATA;
     264             :     }
     265         364 :     if ((flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D))
     266             :     {
     267         174 :         flags |= OGR_G_3D;
     268         174 :         bHasZ = TRUE;
     269             :     }
     270         364 :     if ((flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED))
     271             :     {
     272           1 :         flags |= OGR_G_MEASURED;
     273           1 :         bHasM = TRUE;
     274             :     }
     275             : 
     276             :     /* -------------------------------------------------------------------- */
     277             :     /*      Transform raw points into point objects.                        */
     278             :     /* -------------------------------------------------------------------- */
     279        1005 :     for (int iGeom = 0; iGeom < nPointCount; iGeom++)
     280             :     {
     281             :         OGRPoint *poPoint =
     282         641 :             new OGRPoint(paoPoints[iGeom].x, paoPoints[iGeom].y);
     283         641 :         if (bHasM)
     284             :         {
     285           5 :             if (padfM != nullptr)
     286           5 :                 poPoint->setM(padfM[iGeom]);
     287             :             else
     288           0 :                 poPoint->setM(0.0);
     289             :         }
     290         641 :         if (bHasZ)
     291             :         {
     292         351 :             if (padfZ != nullptr)
     293         351 :                 poPoint->setZ(padfZ[iGeom]);
     294             :             else
     295           0 :                 poPoint->setZ(0.0);
     296             :         }
     297             : 
     298         641 :         eErr = addGeometryDirectly(poPoint);
     299         641 :         if (eErr != OGRERR_NONE)
     300             :         {
     301           0 :             CPLFree(paoPoints);
     302           0 :             CPLFree(padfZ);
     303           0 :             CPLFree(padfM);
     304           0 :             delete poPoint;
     305           0 :             return eErr;
     306             :         }
     307             :     }
     308             : 
     309         364 :     CPLFree(paoPoints);
     310         364 :     CPLFree(padfZ);
     311         364 :     CPLFree(padfM);
     312             : 
     313         364 :     *ppszInput = pszInput;
     314             : 
     315         364 :     return OGRERR_NONE;
     316             : }
     317             : 
     318             : /************************************************************************/
     319             : /*                      importFromWkt_Bracketed()                       */
     320             : /*                                                                      */
     321             : /*      This operates similar to importFromWkt(), but reads a format    */
     322             : /*      with brackets around each point.  This is the form defined      */
     323             : /*      in the BNF of the SFSQL spec.  It is called from                */
     324             : /*      importFromWkt().                                                */
     325             : /************************************************************************/
     326             : 
     327         150 : OGRErr OGRMultiPoint::importFromWkt_Bracketed(const char **ppszInput, int bHasM,
     328             :                                               int bHasZ)
     329             : 
     330             : {
     331             :     /* -------------------------------------------------------------------- */
     332             :     /*      Skip MULTIPOINT keyword.                                        */
     333             :     /* -------------------------------------------------------------------- */
     334         150 :     char szToken[OGR_WKT_TOKEN_MAX] = {};
     335         150 :     const char *pszInput = *ppszInput;
     336         150 :     pszInput = OGRWktReadToken(pszInput, szToken);
     337             : 
     338         150 :     if (bHasZ || bHasM)
     339             :     {
     340             :         // Skip Z, M or ZM.
     341          69 :         pszInput = OGRWktReadToken(pszInput, szToken);
     342             :     }
     343             : 
     344             :     /* -------------------------------------------------------------------- */
     345             :     /*      Read points till we get to the closing bracket.                 */
     346             :     /* -------------------------------------------------------------------- */
     347             : 
     348         150 :     OGRRawPoint *paoPoints = nullptr;
     349         150 :     double *padfZ = nullptr;
     350         150 :     double *padfM = nullptr;
     351             : 
     352         916 :     while ((pszInput = OGRWktReadToken(pszInput, szToken)) != nullptr &&
     353         458 :            (EQUAL(szToken, "(") || EQUAL(szToken, ",")))
     354             :     {
     355         311 :         const char *pszNext = OGRWktReadToken(pszInput, szToken);
     356         311 :         if (EQUAL(szToken, "EMPTY"))
     357             :         {
     358          12 :             OGRPoint *poGeom = new OGRPoint(0.0, 0.0);
     359          12 :             poGeom->empty();
     360          12 :             const OGRErr eErr = addGeometryDirectly(poGeom);
     361          12 :             if (eErr != OGRERR_NONE)
     362             :             {
     363           0 :                 CPLFree(paoPoints);
     364           0 :                 delete poGeom;
     365           3 :                 return eErr;
     366             :             }
     367             : 
     368          12 :             pszInput = pszNext;
     369             : 
     370          12 :             continue;
     371             :         }
     372             : 
     373         299 :         int flagsFromInput = flags;
     374         299 :         int nMaxPoint = 0;
     375         299 :         int nPointCount = 0;
     376         299 :         pszInput = OGRWktReadPointsM(pszInput, &paoPoints, &padfZ, &padfM,
     377             :                                      &flagsFromInput, &nMaxPoint, &nPointCount);
     378             : 
     379         299 :         if (pszInput == nullptr || nPointCount != 1)
     380             :         {
     381           3 :             CPLFree(paoPoints);
     382           3 :             CPLFree(padfZ);
     383           3 :             CPLFree(padfM);
     384           3 :             return OGRERR_CORRUPT_DATA;
     385             :         }
     386         296 :         if ((flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D))
     387             :         {
     388           4 :             flags |= OGR_G_3D;
     389           4 :             bHasZ = TRUE;
     390             :         }
     391         296 :         if ((flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED))
     392             :         {
     393           0 :             flags |= OGR_G_MEASURED;
     394           0 :             bHasM = TRUE;
     395             :         }
     396             : 
     397         296 :         OGRPoint *poPoint = new OGRPoint(paoPoints[0].x, paoPoints[0].y);
     398         296 :         if (bHasM)
     399             :         {
     400          84 :             if (padfM != nullptr)
     401          84 :                 poPoint->setM(padfM[0]);
     402             :             else
     403           0 :                 poPoint->setM(0.0);
     404             :         }
     405         296 :         if (bHasZ)
     406             :         {
     407          99 :             if (padfZ != nullptr)
     408          99 :                 poPoint->setZ(padfZ[0]);
     409             :             else
     410           0 :                 poPoint->setZ(0.0);
     411             :         }
     412             : 
     413         296 :         const OGRErr eErr = addGeometryDirectly(poPoint);
     414         296 :         if (eErr != OGRERR_NONE)
     415             :         {
     416           0 :             CPLFree(paoPoints);
     417           0 :             CPLFree(padfZ);
     418           0 :             CPLFree(padfM);
     419           0 :             delete poPoint;
     420           0 :             return eErr;
     421             :         }
     422             :     }
     423             : 
     424             :     /* -------------------------------------------------------------------- */
     425             :     /*      Cleanup.                                                        */
     426             :     /* -------------------------------------------------------------------- */
     427         147 :     CPLFree(paoPoints);
     428         147 :     CPLFree(padfZ);
     429         147 :     CPLFree(padfM);
     430             : 
     431         147 :     if (!EQUAL(szToken, ")"))
     432           6 :         return OGRERR_CORRUPT_DATA;
     433             : 
     434         141 :     *ppszInput = pszInput;
     435             : 
     436         141 :     return OGRERR_NONE;
     437             : }
     438             : 
     439             : /************************************************************************/
     440             : /*                         hasCurveGeometry()                           */
     441             : /************************************************************************/
     442             : 
     443        2314 : OGRBoolean OGRMultiPoint::hasCurveGeometry(int /* bLookForNonLinear */) const
     444             : {
     445        2314 :     return FALSE;
     446             : }

Generated by: LCOV version 1.14