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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "ogr_geometry.h"
      16             : 
      17             : #include <cstddef>
      18             : #include <cstdio>
      19             : #include <cstring>
      20             : #include <new>
      21             : 
      22             : #include "cpl_conv.h"
      23             : #include "cpl_error.h"
      24             : #include "cpl_vsi.h"
      25             : #include "ogr_core.h"
      26             : #include "ogr_p.h"
      27             : 
      28             : /************************************************************************/
      29             : /*                OGRMultiPoint( const OGRMultiPoint& )                 */
      30             : /************************************************************************/
      31             : 
      32             : /**
      33             :  * \brief Copy constructor.
      34             :  *
      35             :  * Note: before GDAL 2.1, only the default implementation of the constructor
      36             :  * existed, which could be unsafe to use.
      37             :  *
      38             :  * @since GDAL 2.1
      39             :  */
      40             : 
      41             : OGRMultiPoint::OGRMultiPoint(const OGRMultiPoint &) = default;
      42             : 
      43             : /************************************************************************/
      44             : /*                  operator=( const OGRMultiPoint&)                    */
      45             : /************************************************************************/
      46             : 
      47             : /**
      48             :  * \brief Assignment operator.
      49             :  *
      50             :  * Note: before GDAL 2.1, only the default implementation of the operator
      51             :  * existed, which could be unsafe to use.
      52             :  *
      53             :  * @since GDAL 2.1
      54             :  */
      55             : 
      56           5 : OGRMultiPoint &OGRMultiPoint::operator=(const OGRMultiPoint &other)
      57             : {
      58           5 :     if (this != &other)
      59             :     {
      60           4 :         OGRGeometryCollection::operator=(other);
      61             :     }
      62           5 :     return *this;
      63             : }
      64             : 
      65             : /************************************************************************/
      66             : /*                               clone()                                */
      67             : /************************************************************************/
      68             : 
      69         734 : OGRMultiPoint *OGRMultiPoint::clone() const
      70             : 
      71             : {
      72         734 :     return new (std::nothrow) OGRMultiPoint(*this);
      73             : }
      74             : 
      75             : /************************************************************************/
      76             : /*                          getGeometryType()                           */
      77             : /************************************************************************/
      78             : 
      79       14775 : OGRwkbGeometryType OGRMultiPoint::getGeometryType() const
      80             : 
      81             : {
      82       14775 :     if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
      83        3087 :         return wkbMultiPointZM;
      84       11688 :     else if (flags & OGR_G_MEASURED)
      85         324 :         return wkbMultiPointM;
      86       11364 :     else if (flags & OGR_G_3D)
      87        5536 :         return wkbMultiPoint25D;
      88             :     else
      89        5828 :         return wkbMultiPoint;
      90             : }
      91             : 
      92             : /************************************************************************/
      93             : /*                            getDimension()                            */
      94             : /************************************************************************/
      95             : 
      96           1 : int OGRMultiPoint::getDimension() const
      97             : 
      98             : {
      99           1 :     return 0;
     100             : }
     101             : 
     102             : /************************************************************************/
     103             : /*                          getGeometryName()                           */
     104             : /************************************************************************/
     105             : 
     106        1753 : const char *OGRMultiPoint::getGeometryName() const
     107             : 
     108             : {
     109        1753 :     return "MULTIPOINT";
     110             : }
     111             : 
     112             : /************************************************************************/
     113             : /*                          isCompatibleSubType()                       */
     114             : /************************************************************************/
     115             : 
     116             : OGRBoolean
     117        6689 : OGRMultiPoint::isCompatibleSubType(OGRwkbGeometryType eGeomType) const
     118             : {
     119        6689 :     return wkbFlatten(eGeomType) == wkbPoint;
     120             : }
     121             : 
     122             : /************************************************************************/
     123             : /*                            exportToWkt()                             */
     124             : /*                                                                      */
     125             : /*      Translate this structure into its well known text format        */
     126             : /*      equivalent.                                                     */
     127             : /************************************************************************/
     128             : 
     129         209 : std::string OGRMultiPoint::exportToWkt(const OGRWktOptions &opts,
     130             :                                        OGRErr *err) const
     131             : {
     132             :     try
     133             :     {
     134         418 :         std::string wkt = getGeometryName();
     135         209 :         wkt += wktTypeString(opts.variant);
     136             : 
     137         209 :         bool first(true);
     138             :         // OGRMultiPoint has a begin()/end().
     139         598 :         for (const OGRPoint *poPoint : this)
     140             :         {
     141         389 :             if (poPoint->IsEmpty())
     142          13 :                 continue;
     143             : 
     144         376 :             if (first)
     145         164 :                 wkt += '(';
     146             :             else
     147         212 :                 wkt += ',';
     148         376 :             first = false;
     149             : 
     150         376 :             if (opts.variant == wkbVariantIso)
     151         208 :                 wkt += '(';
     152             : 
     153         752 :             wkt += OGRMakeWktCoordinateM(
     154             :                 poPoint->getX(), poPoint->getY(), poPoint->getZ(),
     155             :                 poPoint->getM(), poPoint->Is3D(),
     156         752 :                 poPoint->IsMeasured() && (opts.variant == wkbVariantIso), opts);
     157             : 
     158         376 :             if (opts.variant == wkbVariantIso)
     159         208 :                 wkt += ')';
     160             :         }
     161             : 
     162         209 :         if (err)
     163         193 :             *err = OGRERR_NONE;
     164         209 :         if (first)
     165          45 :             wkt += "EMPTY";
     166             :         else
     167         164 :             wkt += ')';
     168         209 :         return wkt;
     169             :     }
     170           0 :     catch (const std::bad_alloc &e)
     171             :     {
     172           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
     173           0 :         if (err)
     174           0 :             *err = OGRERR_FAILURE;
     175           0 :         return std::string();
     176             :     }
     177             : }
     178             : 
     179             : /************************************************************************/
     180             : /*                           importFromWkt()                            */
     181             : /************************************************************************/
     182             : 
     183         617 : OGRErr OGRMultiPoint::importFromWkt(const char **ppszInput)
     184             : 
     185             : {
     186         617 :     const char *pszInputBefore = *ppszInput;
     187         617 :     int bHasZ = FALSE;
     188         617 :     int bHasM = FALSE;
     189         617 :     bool bIsEmpty = false;
     190         617 :     OGRErr eErr = importPreambleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     191         617 :     flags = 0;
     192         617 :     if (eErr != OGRERR_NONE)
     193           5 :         return eErr;
     194         612 :     if (bHasZ)
     195          85 :         flags |= OGR_G_3D;
     196         612 :     if (bHasM)
     197          62 :         flags |= OGR_G_MEASURED;
     198         612 :     if (bIsEmpty)
     199          62 :         return OGRERR_NONE;
     200             : 
     201         550 :     char szToken[OGR_WKT_TOKEN_MAX] = {};
     202         550 :     const char *pszInput = *ppszInput;
     203             : 
     204         550 :     const char *pszPreScan = OGRWktReadToken(pszInput, szToken);
     205         550 :     OGRWktReadToken(pszPreScan, szToken);
     206             : 
     207             :     // Do we have an inner bracket?
     208         550 :     if (EQUAL(szToken, "(") || EQUAL(szToken, "EMPTY"))
     209             :     {
     210         172 :         *ppszInput = pszInputBefore;
     211         172 :         return importFromWkt_Bracketed(ppszInput, bHasM, bHasZ);
     212             :     }
     213             : 
     214             :     /* -------------------------------------------------------------------- */
     215             :     /*      Read the point list.                                            */
     216             :     /* -------------------------------------------------------------------- */
     217         378 :     OGRRawPoint *paoPoints = nullptr;
     218         378 :     double *padfZ = nullptr;
     219         378 :     double *padfM = nullptr;
     220         378 :     int flagsFromInput = flags;
     221         378 :     int nMaxPoint = 0;
     222         378 :     int nPointCount = 0;
     223             : 
     224         378 :     pszInput = OGRWktReadPointsM(pszInput, &paoPoints, &padfZ, &padfM,
     225             :                                  &flagsFromInput, &nMaxPoint, &nPointCount);
     226         378 :     if (pszInput == nullptr)
     227             :     {
     228          11 :         CPLFree(paoPoints);
     229          11 :         CPLFree(padfZ);
     230          11 :         CPLFree(padfM);
     231          11 :         return OGRERR_CORRUPT_DATA;
     232             :     }
     233         367 :     if ((flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D))
     234             :     {
     235         174 :         flags |= OGR_G_3D;
     236         174 :         bHasZ = TRUE;
     237             :     }
     238         367 :     if ((flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED))
     239             :     {
     240           1 :         flags |= OGR_G_MEASURED;
     241           1 :         bHasM = TRUE;
     242             :     }
     243             : 
     244             :     /* -------------------------------------------------------------------- */
     245             :     /*      Transform raw points into point objects.                        */
     246             :     /* -------------------------------------------------------------------- */
     247        1014 :     for (int iGeom = 0; iGeom < nPointCount; iGeom++)
     248             :     {
     249             :         OGRPoint *poPoint =
     250         647 :             new OGRPoint(paoPoints[iGeom].x, paoPoints[iGeom].y);
     251         647 :         if (bHasM)
     252             :         {
     253           5 :             if (padfM != nullptr)
     254           5 :                 poPoint->setM(padfM[iGeom]);
     255             :             else
     256           0 :                 poPoint->setM(0.0);
     257             :         }
     258         647 :         if (bHasZ)
     259             :         {
     260         351 :             if (padfZ != nullptr)
     261         351 :                 poPoint->setZ(padfZ[iGeom]);
     262             :             else
     263           0 :                 poPoint->setZ(0.0);
     264             :         }
     265             : 
     266         647 :         eErr = addGeometryDirectly(poPoint);
     267         647 :         if (eErr != OGRERR_NONE)
     268             :         {
     269           0 :             CPLFree(paoPoints);
     270           0 :             CPLFree(padfZ);
     271           0 :             CPLFree(padfM);
     272           0 :             delete poPoint;
     273           0 :             return eErr;
     274             :         }
     275             :     }
     276             : 
     277         367 :     CPLFree(paoPoints);
     278         367 :     CPLFree(padfZ);
     279         367 :     CPLFree(padfM);
     280             : 
     281         367 :     *ppszInput = pszInput;
     282             : 
     283         367 :     return OGRERR_NONE;
     284             : }
     285             : 
     286             : /************************************************************************/
     287             : /*                      importFromWkt_Bracketed()                       */
     288             : /*                                                                      */
     289             : /*      This operates similar to importFromWkt(), but reads a format    */
     290             : /*      with brackets around each point.  This is the form defined      */
     291             : /*      in the BNF of the SFSQL spec.  It is called from                */
     292             : /*      importFromWkt().                                                */
     293             : /************************************************************************/
     294             : 
     295         172 : OGRErr OGRMultiPoint::importFromWkt_Bracketed(const char **ppszInput, int bHasM,
     296             :                                               int bHasZ)
     297             : 
     298             : {
     299             :     /* -------------------------------------------------------------------- */
     300             :     /*      Skip MULTIPOINT keyword.                                        */
     301             :     /* -------------------------------------------------------------------- */
     302         172 :     char szToken[OGR_WKT_TOKEN_MAX] = {};
     303         172 :     const char *pszInput = *ppszInput;
     304         172 :     pszInput = OGRWktReadToken(pszInput, szToken);
     305             : 
     306         172 :     if (bHasZ || bHasM)
     307             :     {
     308             :         // Skip Z, M or ZM.
     309          78 :         pszInput = OGRWktReadToken(pszInput, szToken);
     310             :     }
     311             : 
     312             :     /* -------------------------------------------------------------------- */
     313             :     /*      Read points till we get to the closing bracket.                 */
     314             :     /* -------------------------------------------------------------------- */
     315             : 
     316         172 :     OGRRawPoint *paoPoints = nullptr;
     317         172 :     double *padfZ = nullptr;
     318         172 :     double *padfM = nullptr;
     319             : 
     320        1044 :     while ((pszInput = OGRWktReadToken(pszInput, szToken)) != nullptr &&
     321         522 :            (EQUAL(szToken, "(") || EQUAL(szToken, ",")))
     322             :     {
     323         353 :         const char *pszNext = OGRWktReadToken(pszInput, szToken);
     324         353 :         if (EQUAL(szToken, "EMPTY"))
     325             :         {
     326          17 :             OGRPoint *poGeom = new OGRPoint(0.0, 0.0);
     327          17 :             poGeom->empty();
     328          17 :             const OGRErr eErr = addGeometryDirectly(poGeom);
     329          17 :             if (eErr != OGRERR_NONE)
     330             :             {
     331           0 :                 CPLFree(paoPoints);
     332           0 :                 delete poGeom;
     333           3 :                 return eErr;
     334             :             }
     335             : 
     336          17 :             pszInput = pszNext;
     337             : 
     338          17 :             continue;
     339             :         }
     340             : 
     341         336 :         int flagsFromInput = flags;
     342         336 :         int nMaxPoint = 0;
     343         336 :         int nPointCount = 0;
     344         336 :         pszInput = OGRWktReadPointsM(pszInput, &paoPoints, &padfZ, &padfM,
     345             :                                      &flagsFromInput, &nMaxPoint, &nPointCount);
     346             : 
     347         336 :         if (pszInput == nullptr || nPointCount != 1)
     348             :         {
     349           3 :             CPLFree(paoPoints);
     350           3 :             CPLFree(padfZ);
     351           3 :             CPLFree(padfM);
     352           3 :             return OGRERR_CORRUPT_DATA;
     353             :         }
     354         333 :         if ((flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D))
     355             :         {
     356           4 :             flags |= OGR_G_3D;
     357           4 :             bHasZ = TRUE;
     358             :         }
     359         333 :         if ((flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED))
     360             :         {
     361           0 :             flags |= OGR_G_MEASURED;
     362           0 :             bHasM = TRUE;
     363             :         }
     364             : 
     365         333 :         OGRPoint *poPoint = new OGRPoint(paoPoints[0].x, paoPoints[0].y);
     366         333 :         if (bHasM)
     367             :         {
     368          88 :             if (padfM != nullptr)
     369          88 :                 poPoint->setM(padfM[0]);
     370             :             else
     371           0 :                 poPoint->setM(0.0);
     372             :         }
     373         333 :         if (bHasZ)
     374             :         {
     375         113 :             if (padfZ != nullptr)
     376         113 :                 poPoint->setZ(padfZ[0]);
     377             :             else
     378           0 :                 poPoint->setZ(0.0);
     379             :         }
     380             : 
     381         333 :         const OGRErr eErr = addGeometryDirectly(poPoint);
     382         333 :         if (eErr != OGRERR_NONE)
     383             :         {
     384           0 :             CPLFree(paoPoints);
     385           0 :             CPLFree(padfZ);
     386           0 :             CPLFree(padfM);
     387           0 :             delete poPoint;
     388           0 :             return eErr;
     389             :         }
     390             :     }
     391             : 
     392             :     /* -------------------------------------------------------------------- */
     393             :     /*      Cleanup.                                                        */
     394             :     /* -------------------------------------------------------------------- */
     395         169 :     CPLFree(paoPoints);
     396         169 :     CPLFree(padfZ);
     397         169 :     CPLFree(padfM);
     398             : 
     399         169 :     if (!EQUAL(szToken, ")"))
     400           6 :         return OGRERR_CORRUPT_DATA;
     401             : 
     402         163 :     *ppszInput = pszInput;
     403             : 
     404         163 :     return OGRERR_NONE;
     405             : }
     406             : 
     407             : /************************************************************************/
     408             : /*                         hasCurveGeometry()                           */
     409             : /************************************************************************/
     410             : 
     411        2696 : OGRBoolean OGRMultiPoint::hasCurveGeometry(int /* bLookForNonLinear */) const
     412             : {
     413        2696 :     return FALSE;
     414             : }

Generated by: LCOV version 1.14