LCOV - code coverage report
Current view: top level - core/geometry - qgsgeometryfactory.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 147 173 85.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                            qgsgeometryfactory.cpp
       3                 :            :                          ------------------------
       4                 :            :     begin                : September 2014
       5                 :            :     copyright            : (C) 2014 by Marco Hugentobler
       6                 :            :     email                : marco at sourcepole dot ch
       7                 :            :  ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #include "qgsgeometryfactory.h"
      19                 :            : #include "qgscircularstring.h"
      20                 :            : #include "qgscompoundcurve.h"
      21                 :            : #include "qgscurvepolygon.h"
      22                 :            : #include "qgspoint.h"
      23                 :            : #include "qgspolygon.h"
      24                 :            : #include "qgslinestring.h"
      25                 :            : #include "qgsmulticurve.h"
      26                 :            : #include "qgsmultilinestring.h"
      27                 :            : #include "qgsmultipoint.h"
      28                 :            : #include "qgsmultipolygon.h"
      29                 :            : #include "qgsmultisurface.h"
      30                 :            : #include "qgstriangle.h"
      31                 :            : #include "qgswkbtypes.h"
      32                 :            : #include "qgslogger.h"
      33                 :            : 
      34                 :         53 : std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr &wkbPtr )
      35                 :            : {
      36                 :         53 :   if ( !wkbPtr )
      37                 :          0 :     return nullptr;
      38                 :            : 
      39                 :            :   //find out type (bytes 2-5)
      40                 :         53 :   QgsWkbTypes::Type type = QgsWkbTypes::Unknown;
      41                 :            :   try
      42                 :            :   {
      43                 :         53 :     type = wkbPtr.readHeader();
      44                 :         53 :   }
      45                 :            :   catch ( const QgsWkbException &e )
      46                 :            :   {
      47                 :          1 :     Q_UNUSED( e )
      48                 :          1 :     QgsDebugMsg( "WKB exception while reading header: " + e.what() );
      49                 :          1 :     return nullptr;
      50                 :          1 :   }
      51                 :         52 :   wkbPtr -= 1 + sizeof( int );
      52                 :            : 
      53                 :         52 :   std::unique_ptr< QgsAbstractGeometry > geom = geomFromWkbType( type );
      54                 :            : 
      55                 :         52 :   if ( geom )
      56                 :            :   {
      57                 :            :     try
      58                 :            :     {
      59                 :         52 :       geom->fromWkb( wkbPtr );  // also updates wkbPtr
      60                 :         52 :     }
      61                 :            :     catch ( const QgsWkbException &e )
      62                 :            :     {
      63                 :          1 :       Q_UNUSED( e )
      64                 :          1 :       QgsDebugMsg( "WKB exception: " + e.what() );
      65                 :          1 :       geom.reset();
      66                 :          1 :     }
      67                 :         52 :   }
      68                 :            : 
      69                 :         52 :   return geom;
      70                 :         55 : }
      71                 :            : 
      72                 :       2627 : std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkt( const QString &text )
      73                 :            : {
      74                 :       2627 :   QString trimmed = text.trimmed();
      75                 :       2627 :   std::unique_ptr< QgsAbstractGeometry> geom;
      76                 :       2627 :   if ( trimmed.startsWith( QLatin1String( "Point" ), Qt::CaseInsensitive ) )
      77                 :            :   {
      78                 :        232 :     geom = std::make_unique< QgsPoint >();
      79                 :        232 :   }
      80                 :       2395 :   else if ( trimmed.startsWith( QLatin1String( "LineString" ), Qt::CaseInsensitive ) )
      81                 :            :   {
      82                 :        306 :     geom = std::make_unique< QgsLineString >();
      83                 :        306 :   }
      84                 :       2089 :   else if ( trimmed.startsWith( QLatin1String( "CircularString" ), Qt::CaseInsensitive ) )
      85                 :            :   {
      86                 :        204 :     geom = std::make_unique< QgsCircularString >();
      87                 :        204 :   }
      88                 :       1885 :   else if ( trimmed.startsWith( QLatin1String( "CompoundCurve" ), Qt::CaseInsensitive ) )
      89                 :            :   {
      90                 :        202 :     geom = std::make_unique< QgsCompoundCurve>();
      91                 :        202 :   }
      92                 :       1683 :   else if ( trimmed.startsWith( QLatin1String( "Polygon" ), Qt::CaseInsensitive ) )
      93                 :            :   {
      94                 :        252 :     geom = std::make_unique< QgsPolygon >();
      95                 :        252 :   }
      96                 :       1431 :   else if ( trimmed.startsWith( QLatin1String( "Triangle" ), Qt::CaseInsensitive ) )
      97                 :            :   {
      98                 :        200 :     geom = std::make_unique< QgsTriangle >();
      99                 :        200 :   }
     100                 :       1231 :   else if ( trimmed.startsWith( QLatin1String( "CurvePolygon" ), Qt::CaseInsensitive ) )
     101                 :            :   {
     102                 :        202 :     geom = std::make_unique< QgsCurvePolygon >();
     103                 :        202 :   }
     104                 :       1029 :   else if ( trimmed.startsWith( QLatin1String( "MultiPoint" ), Qt::CaseInsensitive ) )
     105                 :            :   {
     106                 :        208 :     geom = std::make_unique< QgsMultiPoint >();
     107                 :        208 :   }
     108                 :        821 :   else if ( trimmed.startsWith( QLatin1String( "MultiCurve" ), Qt::CaseInsensitive ) )
     109                 :            :   {
     110                 :        200 :     geom = std::make_unique< QgsMultiCurve >();
     111                 :        200 :   }
     112                 :        621 :   else if ( trimmed.startsWith( QLatin1String( "MultiLineString" ), Qt::CaseInsensitive ) )
     113                 :            :   {
     114                 :        208 :     geom = std::make_unique< QgsMultiLineString >();
     115                 :        208 :   }
     116                 :        413 :   else if ( trimmed.startsWith( QLatin1String( "MultiSurface" ), Qt::CaseInsensitive ) )
     117                 :            :   {
     118                 :        200 :     geom = std::make_unique< QgsMultiSurface >();
     119                 :        200 :   }
     120                 :        213 :   else if ( trimmed.startsWith( QLatin1String( "MultiPolygon" ), Qt::CaseInsensitive ) )
     121                 :            :   {
     122                 :          9 :     geom = std::make_unique< QgsMultiPolygon >();
     123                 :          9 :   }
     124                 :        204 :   else if ( trimmed.startsWith( QLatin1String( "GeometryCollection" ), Qt::CaseInsensitive ) )
     125                 :            :   {
     126                 :        204 :     geom = std::make_unique< QgsGeometryCollection >();
     127                 :        204 :   }
     128                 :            : 
     129                 :       2627 :   if ( geom )
     130                 :            :   {
     131                 :       2627 :     if ( !geom->fromWkt( text ) )
     132                 :            :     {
     133                 :          1 :       return nullptr;
     134                 :            :     }
     135                 :       2626 :   }
     136                 :       2626 :   return geom;
     137                 :       2627 : }
     138                 :            : 
     139                 :      30028 : std::unique_ptr< QgsAbstractGeometry > QgsGeometryFactory::fromPointXY( const QgsPointXY &point )
     140                 :            : {
     141                 :      30028 :   return std::make_unique< QgsPoint >( point.x(), point.y() );
     142                 :            : }
     143                 :            : 
     144                 :          7 : std::unique_ptr<QgsMultiPoint> QgsGeometryFactory::fromMultiPointXY( const QgsMultiPointXY &multipoint )
     145                 :            : {
     146                 :          7 :   std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
     147                 :          7 :   QgsMultiPointXY::const_iterator ptIt = multipoint.constBegin();
     148                 :          7 :   mp->reserve( multipoint.size() );
     149                 :         32 :   for ( ; ptIt != multipoint.constEnd(); ++ptIt )
     150                 :            :   {
     151                 :         25 :     QgsPoint *pt = new QgsPoint( ptIt->x(), ptIt->y() );
     152                 :         25 :     mp->addGeometry( pt );
     153                 :         25 :   }
     154                 :          7 :   return mp;
     155                 :          7 : }
     156                 :            : 
     157                 :          2 : std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::fromPolylineXY( const QgsPolylineXY &polyline )
     158                 :            : {
     159                 :          2 :   return linestringFromPolyline( polyline );
     160                 :            : }
     161                 :            : 
     162                 :          0 : std::unique_ptr<QgsMultiLineString> QgsGeometryFactory::fromMultiPolylineXY( const QgsMultiPolylineXY &multiline )
     163                 :            : {
     164                 :          0 :   std::unique_ptr< QgsMultiLineString > mLine = std::make_unique< QgsMultiLineString >();
     165                 :          0 :   mLine->reserve( multiline.size() );
     166                 :          0 :   for ( int i = 0; i < multiline.size(); ++i )
     167                 :            :   {
     168                 :          0 :     mLine->addGeometry( fromPolylineXY( multiline.at( i ) ).release() );
     169                 :          0 :   }
     170                 :          0 :   return mLine;
     171                 :          0 : }
     172                 :            : 
     173                 :         19 : std::unique_ptr<QgsPolygon> QgsGeometryFactory::fromPolygonXY( const QgsPolygonXY &polygon )
     174                 :            : {
     175                 :         19 :   std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
     176                 :            : 
     177                 :         19 :   QVector<QgsCurve *> holes;
     178                 :         19 :   holes.reserve( polygon.size() );
     179                 :         38 :   for ( int i = 0; i < polygon.size(); ++i )
     180                 :            :   {
     181                 :         19 :     std::unique_ptr< QgsLineString > l = linestringFromPolyline( polygon.at( i ) );
     182                 :         19 :     l->close();
     183                 :            : 
     184                 :         19 :     if ( i == 0 )
     185                 :            :     {
     186                 :         19 :       poly->setExteriorRing( l.release() );
     187                 :         19 :     }
     188                 :            :     else
     189                 :            :     {
     190                 :          0 :       holes.push_back( l.release() );
     191                 :            :     }
     192                 :         19 :   }
     193                 :         19 :   poly->setInteriorRings( holes );
     194                 :         19 :   return poly;
     195                 :         19 : }
     196                 :            : 
     197                 :          0 : std::unique_ptr< QgsMultiPolygon > QgsGeometryFactory::fromMultiPolygonXY( const QgsMultiPolygonXY &multipoly )
     198                 :            : {
     199                 :          0 :   std::unique_ptr< QgsMultiPolygon > mp = std::make_unique< QgsMultiPolygon >();
     200                 :          0 :   mp->reserve( multipoly.size() );
     201                 :          0 :   for ( int i = 0; i < multipoly.size(); ++i )
     202                 :            :   {
     203                 :          0 :     mp->addGeometry( fromPolygonXY( multipoly.at( i ) ).release() );
     204                 :          0 :   }
     205                 :          0 :   return mp;
     206                 :          0 : }
     207                 :            : 
     208                 :         21 : std::unique_ptr<QgsLineString> QgsGeometryFactory::linestringFromPolyline( const QgsPolylineXY &polyline )
     209                 :            : {
     210                 :         21 :   const int size = polyline.size();
     211                 :         21 :   QVector< double > x;
     212                 :         21 :   x.resize( size );
     213                 :         21 :   QVector< double > y;
     214                 :         21 :   y.resize( size );
     215                 :         21 :   double *destX = x.data();
     216                 :         21 :   double *destY = y.data();
     217                 :         21 :   const QgsPointXY *src = polyline.data();
     218                 :        121 :   for ( int i = 0; i < size; ++i )
     219                 :            :   {
     220                 :        100 :     *destX++ = src->x();
     221                 :        100 :     *destY++ = src->y();
     222                 :        100 :     src++;
     223                 :        100 :   }
     224                 :         21 :   std::unique_ptr< QgsLineString > line = std::make_unique< QgsLineString >( x, y );
     225                 :         21 :   return line;
     226                 :         21 : }
     227                 :            : 
     228                 :        975 : std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkbType( QgsWkbTypes::Type t )
     229                 :            : {
     230                 :        975 :   QgsWkbTypes::Type type = QgsWkbTypes::flatType( t );
     231                 :        975 :   switch ( type )
     232                 :            :   {
     233                 :            :     case QgsWkbTypes::Point:
     234                 :         10 :       return std::make_unique< QgsPoint >();
     235                 :            :     case QgsWkbTypes::LineString:
     236                 :         18 :       return std::make_unique< QgsLineString >();
     237                 :            :     case QgsWkbTypes::CircularString:
     238                 :          8 :       return std::make_unique< QgsCircularString >();
     239                 :            :     case QgsWkbTypes::CompoundCurve:
     240                 :          0 :       return std::make_unique< QgsCompoundCurve >();
     241                 :            :     case QgsWkbTypes::Polygon:
     242                 :          8 :       return std::make_unique< QgsPolygon >();
     243                 :            :     case QgsWkbTypes::CurvePolygon:
     244                 :          8 :       return std::make_unique< QgsCurvePolygon >();
     245                 :            :     case QgsWkbTypes::MultiLineString:
     246                 :        154 :       return std::make_unique< QgsMultiLineString >();
     247                 :            :     case QgsWkbTypes::MultiPolygon:
     248                 :        768 :       return std::make_unique< QgsMultiPolygon >();
     249                 :            :     case QgsWkbTypes::MultiPoint:
     250                 :          0 :       return std::make_unique< QgsMultiPoint >();
     251                 :            :     case QgsWkbTypes::MultiCurve:
     252                 :          0 :       return std::make_unique< QgsMultiCurve >();
     253                 :            :     case QgsWkbTypes::MultiSurface:
     254                 :          0 :       return std::make_unique< QgsMultiSurface >();
     255                 :            :     case QgsWkbTypes::GeometryCollection:
     256                 :          1 :       return std::make_unique< QgsGeometryCollection >();
     257                 :            :     case QgsWkbTypes::Triangle:
     258                 :          0 :       return std::make_unique< QgsTriangle >();
     259                 :            :     default:
     260                 :          0 :       return nullptr;
     261                 :            :   }
     262                 :        975 : }
     263                 :            : 
     264                 :         10 : std::unique_ptr<QgsGeometryCollection> QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::Type t )
     265                 :            : {
     266                 :         10 :   QgsWkbTypes::Type type = QgsWkbTypes::flatType( QgsWkbTypes::multiType( t ) );
     267                 :         10 :   std::unique_ptr< QgsGeometryCollection > collect;
     268                 :         10 :   switch ( type )
     269                 :            :   {
     270                 :            :     case QgsWkbTypes::MultiPoint:
     271                 :          5 :       collect = std::make_unique< QgsMultiPoint >();
     272                 :          5 :       break;
     273                 :            :     case QgsWkbTypes::MultiLineString:
     274                 :          1 :       collect = std::make_unique< QgsMultiLineString >();
     275                 :          1 :       break;
     276                 :            :     case QgsWkbTypes::MultiCurve:
     277                 :          0 :       collect = std::make_unique< QgsMultiCurve >();
     278                 :          0 :       break;
     279                 :            :     case QgsWkbTypes::MultiPolygon:
     280                 :          1 :       collect = std::make_unique< QgsMultiPolygon >();
     281                 :          1 :       break;
     282                 :            :     case QgsWkbTypes::MultiSurface:
     283                 :          1 :       collect = std::make_unique< QgsMultiSurface >();
     284                 :          1 :       break;
     285                 :            :     case QgsWkbTypes::GeometryCollection:
     286                 :          1 :       collect = std::make_unique< QgsGeometryCollection >();
     287                 :          1 :       break;
     288                 :            :     default:
     289                 :            :       // should not be possible
     290                 :          1 :       return nullptr;
     291                 :            :   }
     292                 :          9 :   if ( QgsWkbTypes::hasM( t ) )
     293                 :          4 :     collect->addMValue();
     294                 :          9 :   if ( QgsWkbTypes::hasZ( t ) )
     295                 :          4 :     collect->addZValue();
     296                 :            : 
     297                 :          9 :   return collect;
     298                 :         10 : }

Generated by: LCOV version 1.14