LCOV - code coverage report
Current view: top level - core/vectortile - qgsvectortilebasicrenderer.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 204 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :   qgsvectortilebasicrenderer.cpp
       3                 :            :   --------------------------------------
       4                 :            :   Date                 : March 2020
       5                 :            :   Copyright            : (C) 2020 by Martin Dobias
       6                 :            :   Email                : wonder dot sk at gmail dot com
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : 
      16                 :            : #include "qgsvectortilebasicrenderer.h"
      17                 :            : 
      18                 :            : #include "qgsapplication.h"
      19                 :            : #include "qgscolorschemeregistry.h"
      20                 :            : #include "qgsexpressioncontextutils.h"
      21                 :            : #include "qgsfillsymbollayer.h"
      22                 :            : #include "qgslinesymbollayer.h"
      23                 :            : #include "qgsmarkersymbollayer.h"
      24                 :            : #include "qgssymbollayerutils.h"
      25                 :            : #include "qgsvectortileutils.h"
      26                 :            : 
      27                 :          0 : QgsVectorTileBasicRendererStyle::QgsVectorTileBasicRendererStyle( const QString &stName, const QString &laName, QgsWkbTypes::GeometryType geomType )
      28                 :          0 :   : mStyleName( stName )
      29                 :          0 :   , mLayerName( laName )
      30                 :          0 :   , mGeometryType( geomType )
      31                 :            : {
      32                 :          0 : }
      33                 :            : 
      34                 :          0 : QgsVectorTileBasicRendererStyle::QgsVectorTileBasicRendererStyle( const QgsVectorTileBasicRendererStyle &other )
      35                 :            : {
      36                 :          0 :   operator=( other );
      37                 :          0 : }
      38                 :            : 
      39                 :          0 : QgsVectorTileBasicRendererStyle &QgsVectorTileBasicRendererStyle::operator=( const QgsVectorTileBasicRendererStyle &other )
      40                 :            : {
      41                 :          0 :   mStyleName = other.mStyleName;
      42                 :          0 :   mLayerName = other.mLayerName;
      43                 :          0 :   mGeometryType = other.mGeometryType;
      44                 :          0 :   mSymbol.reset( other.mSymbol ? other.mSymbol->clone() : nullptr );
      45                 :          0 :   mEnabled = other.mEnabled;
      46                 :          0 :   mExpression = other.mExpression;
      47                 :          0 :   mMinZoomLevel = other.mMinZoomLevel;
      48                 :          0 :   mMaxZoomLevel = other.mMaxZoomLevel;
      49                 :          0 :   return *this;
      50                 :            : }
      51                 :            : 
      52                 :          0 : QgsVectorTileBasicRendererStyle::~QgsVectorTileBasicRendererStyle() = default;
      53                 :            : 
      54                 :          0 : void QgsVectorTileBasicRendererStyle::setSymbol( QgsSymbol *sym )
      55                 :            : {
      56                 :          0 :   mSymbol.reset( sym );
      57                 :          0 : }
      58                 :            : 
      59                 :          0 : void QgsVectorTileBasicRendererStyle::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
      60                 :            : {
      61                 :          0 :   elem.setAttribute( QStringLiteral( "name" ), mStyleName );
      62                 :          0 :   elem.setAttribute( QStringLiteral( "layer" ), mLayerName );
      63                 :          0 :   elem.setAttribute( QStringLiteral( "geometry" ), mGeometryType );
      64                 :          0 :   elem.setAttribute( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
      65                 :          0 :   elem.setAttribute( QStringLiteral( "expression" ), mExpression );
      66                 :          0 :   elem.setAttribute( QStringLiteral( "min-zoom" ), mMinZoomLevel );
      67                 :          0 :   elem.setAttribute( QStringLiteral( "max-zoom" ), mMaxZoomLevel );
      68                 :            : 
      69                 :          0 :   QDomDocument doc = elem.ownerDocument();
      70                 :          0 :   QgsSymbolMap symbols;
      71                 :          0 :   symbols[QStringLiteral( "0" )] = mSymbol.get();
      72                 :          0 :   QDomElement symbolsElem = QgsSymbolLayerUtils::saveSymbols( symbols, QStringLiteral( "symbols" ), doc, context );
      73                 :          0 :   elem.appendChild( symbolsElem );
      74                 :          0 : }
      75                 :            : 
      76                 :          0 : void QgsVectorTileBasicRendererStyle::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
      77                 :            : {
      78                 :          0 :   mStyleName = elem.attribute( QStringLiteral( "name" ) );
      79                 :          0 :   mLayerName = elem.attribute( QStringLiteral( "layer" ) );
      80                 :          0 :   mGeometryType = static_cast<QgsWkbTypes::GeometryType>( elem.attribute( QStringLiteral( "geometry" ) ).toInt() );
      81                 :          0 :   mEnabled = elem.attribute( QStringLiteral( "enabled" ) ).toInt();
      82                 :          0 :   mExpression = elem.attribute( QStringLiteral( "expression" ) );
      83                 :          0 :   mMinZoomLevel = elem.attribute( QStringLiteral( "min-zoom" ) ).toInt();
      84                 :          0 :   mMaxZoomLevel = elem.attribute( QStringLiteral( "max-zoom" ) ).toInt();
      85                 :            : 
      86                 :          0 :   mSymbol.reset();
      87                 :          0 :   QDomElement symbolsElem = elem.firstChildElement( QStringLiteral( "symbols" ) );
      88                 :          0 :   if ( !symbolsElem.isNull() )
      89                 :            :   {
      90                 :          0 :     QgsSymbolMap symbolMap = QgsSymbolLayerUtils::loadSymbols( symbolsElem, context );
      91                 :          0 :     if ( symbolMap.contains( QStringLiteral( "0" ) ) )
      92                 :            :     {
      93                 :          0 :       mSymbol.reset( symbolMap.take( QStringLiteral( "0" ) ) );
      94                 :          0 :     }
      95                 :          0 :   }
      96                 :          0 : }
      97                 :            : 
      98                 :            : ////////
      99                 :            : 
     100                 :            : 
     101                 :          0 : QgsVectorTileBasicRenderer::QgsVectorTileBasicRenderer()
     102                 :          0 : {
     103                 :          0 : }
     104                 :            : 
     105                 :          0 : QString QgsVectorTileBasicRenderer::type() const
     106                 :            : {
     107                 :          0 :   return QStringLiteral( "basic" );
     108                 :            : }
     109                 :            : 
     110                 :          0 : QgsVectorTileBasicRenderer *QgsVectorTileBasicRenderer::clone() const
     111                 :            : {
     112                 :          0 :   QgsVectorTileBasicRenderer *r = new QgsVectorTileBasicRenderer;
     113                 :          0 :   r->mStyles = mStyles;
     114                 :          0 :   r->mStyles.detach();  // make a deep copy to make sure symbols get cloned
     115                 :          0 :   return r;
     116                 :          0 : }
     117                 :            : 
     118                 :          0 : void QgsVectorTileBasicRenderer::startRender( QgsRenderContext &context, int tileZoom, const QgsTileRange &tileRange )
     119                 :            : {
     120                 :          0 :   Q_UNUSED( context )
     121                 :          0 :   Q_UNUSED( tileRange )
     122                 :            :   // figure out required fields for different layers
     123                 :          0 :   for ( const QgsVectorTileBasicRendererStyle &layerStyle : std::as_const( mStyles ) )
     124                 :            :   {
     125                 :          0 :     if ( layerStyle.isActive( tileZoom ) )
     126                 :            :     {
     127                 :          0 :       if ( !layerStyle.filterExpression().isEmpty() )
     128                 :            :       {
     129                 :          0 :         QgsExpression expr( layerStyle.filterExpression() );
     130                 :          0 :         mRequiredFields[layerStyle.layerName()].unite( expr.referencedColumns() );
     131                 :          0 :       }
     132                 :          0 :       if ( auto *lSymbol = layerStyle.symbol() )
     133                 :            :       {
     134                 :          0 :         mRequiredFields[layerStyle.layerName()].unite( lSymbol->usedAttributes( context ) );
     135                 :          0 :       }
     136                 :          0 :     }
     137                 :            :   }
     138                 :          0 : }
     139                 :            : 
     140                 :          0 : QMap<QString, QSet<QString> > QgsVectorTileBasicRenderer::usedAttributes( const QgsRenderContext & )
     141                 :            : {
     142                 :          0 :   return mRequiredFields;
     143                 :            : }
     144                 :            : 
     145                 :          0 : QSet<QString> QgsVectorTileBasicRenderer::requiredLayers( QgsRenderContext &, int tileZoom ) const
     146                 :            : {
     147                 :          0 :   QSet< QString > res;
     148                 :          0 :   for ( const QgsVectorTileBasicRendererStyle &layerStyle : std::as_const( mStyles ) )
     149                 :            :   {
     150                 :          0 :     if ( layerStyle.isActive( tileZoom ) )
     151                 :            :     {
     152                 :          0 :       res.insert( layerStyle.layerName() );
     153                 :          0 :     }
     154                 :            :   }
     155                 :          0 :   return res;
     156                 :          0 : }
     157                 :            : 
     158                 :          0 : void QgsVectorTileBasicRenderer::stopRender( QgsRenderContext &context )
     159                 :            : {
     160                 :          0 :   Q_UNUSED( context )
     161                 :          0 : }
     162                 :            : 
     163                 :          0 : void QgsVectorTileBasicRenderer::renderTile( const QgsVectorTileRendererData &tile, QgsRenderContext &context )
     164                 :            : {
     165                 :          0 :   const QgsVectorTileFeatures tileData = tile.features();
     166                 :          0 :   int zoomLevel = tile.id().zoomLevel();
     167                 :            : 
     168                 :          0 :   for ( const QgsVectorTileBasicRendererStyle &layerStyle : std::as_const( mStyles ) )
     169                 :            :   {
     170                 :          0 :     if ( !layerStyle.isActive( zoomLevel ) )
     171                 :          0 :       continue;
     172                 :            : 
     173                 :          0 :     QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) ); // will be deleted by popper
     174                 :          0 :     scope->setFields( tile.fields()[layerStyle.layerName()] );
     175                 :          0 :     QgsExpressionContextScopePopper popper( context.expressionContext(), scope );
     176                 :            : 
     177                 :          0 :     QgsExpression filterExpression( layerStyle.filterExpression() );
     178                 :          0 :     filterExpression.prepare( &context.expressionContext() );
     179                 :            : 
     180                 :          0 :     QgsSymbol *sym = layerStyle.symbol();
     181                 :          0 :     sym->startRender( context, QgsFields() );
     182                 :          0 :     if ( layerStyle.layerName().isEmpty() )
     183                 :            :     {
     184                 :            :       // matching all layers
     185                 :          0 :       for ( QString layerName : tileData.keys() )
     186                 :            :       {
     187                 :          0 :         for ( const QgsFeature &f : tileData[layerName] )
     188                 :            :         {
     189                 :          0 :           scope->setFeature( f );
     190                 :          0 :           if ( filterExpression.isValid() && !filterExpression.evaluate( &context.expressionContext() ).toBool() )
     191                 :          0 :             continue;
     192                 :            : 
     193                 :          0 :           const QgsWkbTypes::GeometryType featureType = QgsWkbTypes::geometryType( f.geometry().wkbType() );
     194                 :          0 :           if ( featureType == layerStyle.geometryType() )
     195                 :            :           {
     196                 :          0 :             sym->renderFeature( f, context );
     197                 :          0 :           }
     198                 :          0 :           else if ( featureType == QgsWkbTypes::PolygonGeometry && layerStyle.geometryType() == QgsWkbTypes::LineGeometry )
     199                 :            :           {
     200                 :            :             // be tolerant and permit rendering polygons with a line layer style, as some style definitions use this approach
     201                 :            :             // to render the polygon borders only
     202                 :          0 :             QgsFeature exterior = f;
     203                 :          0 :             exterior.setGeometry( QgsGeometry( f.geometry().constGet()->boundary() ) );
     204                 :          0 :             sym->renderFeature( exterior, context );
     205                 :          0 :           }
     206                 :            :         }
     207                 :          0 :       }
     208                 :          0 :     }
     209                 :          0 :     else if ( tileData.contains( layerStyle.layerName() ) )
     210                 :            :     {
     211                 :            :       // matching one particular layer
     212                 :          0 :       for ( const QgsFeature &f : tileData[layerStyle.layerName()] )
     213                 :            :       {
     214                 :          0 :         scope->setFeature( f );
     215                 :          0 :         if ( filterExpression.isValid() && !filterExpression.evaluate( &context.expressionContext() ).toBool() )
     216                 :          0 :           continue;
     217                 :            : 
     218                 :          0 :         const QgsWkbTypes::GeometryType featureType = QgsWkbTypes::geometryType( f.geometry().wkbType() );
     219                 :          0 :         if ( featureType == layerStyle.geometryType() )
     220                 :            :         {
     221                 :          0 :           sym->renderFeature( f, context );
     222                 :          0 :         }
     223                 :          0 :         else if ( featureType == QgsWkbTypes::PolygonGeometry && layerStyle.geometryType() == QgsWkbTypes::LineGeometry )
     224                 :            :         {
     225                 :            :           // be tolerant and permit rendering polygons with a line layer style, as some style definitions use this approach
     226                 :            :           // to render the polygon borders only
     227                 :          0 :           QgsFeature exterior = f;
     228                 :          0 :           exterior.setGeometry( QgsGeometry( f.geometry().constGet()->boundary() ) );
     229                 :          0 :           sym->renderFeature( exterior, context );
     230                 :          0 :         }
     231                 :            :       }
     232                 :          0 :     }
     233                 :          0 :     sym->stopRender( context );
     234                 :          0 :   }
     235                 :          0 : }
     236                 :            : 
     237                 :          0 : void QgsVectorTileBasicRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
     238                 :            : {
     239                 :          0 :   QDomDocument doc = elem.ownerDocument();
     240                 :          0 :   QDomElement elemStyles = doc.createElement( QStringLiteral( "styles" ) );
     241                 :          0 :   for ( const QgsVectorTileBasicRendererStyle &layerStyle : mStyles )
     242                 :            :   {
     243                 :          0 :     QDomElement elemStyle = doc.createElement( QStringLiteral( "style" ) );
     244                 :          0 :     layerStyle.writeXml( elemStyle, context );
     245                 :          0 :     elemStyles.appendChild( elemStyle );
     246                 :          0 :   }
     247                 :          0 :   elem.appendChild( elemStyles );
     248                 :          0 : }
     249                 :            : 
     250                 :          0 : void QgsVectorTileBasicRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
     251                 :            : {
     252                 :          0 :   mStyles.clear();
     253                 :            : 
     254                 :          0 :   QDomElement elemStyles = elem.firstChildElement( QStringLiteral( "styles" ) );
     255                 :          0 :   QDomElement elemStyle = elemStyles.firstChildElement( QStringLiteral( "style" ) );
     256                 :          0 :   while ( !elemStyle.isNull() )
     257                 :            :   {
     258                 :          0 :     QgsVectorTileBasicRendererStyle layerStyle;
     259                 :          0 :     layerStyle.readXml( elemStyle, context );
     260                 :          0 :     mStyles.append( layerStyle );
     261                 :          0 :     elemStyle = elemStyle.nextSiblingElement( QStringLiteral( "style" ) );
     262                 :          0 :   }
     263                 :          0 : }
     264                 :            : 
     265                 :          0 : void QgsVectorTileBasicRenderer::setStyles( const QList<QgsVectorTileBasicRendererStyle> &styles )
     266                 :            : {
     267                 :          0 :   mStyles = styles;
     268                 :          0 : }
     269                 :            : 
     270                 :          0 : QList<QgsVectorTileBasicRendererStyle> QgsVectorTileBasicRenderer::styles() const
     271                 :            : {
     272                 :          0 :   return mStyles;
     273                 :            : }
     274                 :            : 
     275                 :          0 : QList<QgsVectorTileBasicRendererStyle> QgsVectorTileBasicRenderer::simpleStyleWithRandomColors()
     276                 :            : {
     277                 :          0 :   QColor polygonFillColor = QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor();
     278                 :          0 :   QColor polygonStrokeColor = polygonFillColor;
     279                 :          0 :   polygonFillColor.setAlpha( 100 );
     280                 :          0 :   double polygonStrokeWidth = DEFAULT_LINE_WIDTH;
     281                 :            : 
     282                 :          0 :   QColor lineStrokeColor = QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor();
     283                 :          0 :   double lineStrokeWidth = DEFAULT_LINE_WIDTH;
     284                 :            : 
     285                 :          0 :   QColor pointFillColor = QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor();
     286                 :          0 :   QColor pointStrokeColor = pointFillColor;
     287                 :          0 :   pointFillColor.setAlpha( 100 );
     288                 :          0 :   double pointSize = DEFAULT_POINT_SIZE;
     289                 :            : 
     290                 :          0 :   return simpleStyle( polygonFillColor, polygonStrokeColor, polygonStrokeWidth,
     291                 :          0 :                       lineStrokeColor, lineStrokeWidth,
     292                 :          0 :                       pointFillColor, pointStrokeColor, pointSize );
     293                 :            : }
     294                 :            : 
     295                 :          0 : QList<QgsVectorTileBasicRendererStyle> QgsVectorTileBasicRenderer::simpleStyle(
     296                 :            :   const QColor &polygonFillColor, const QColor &polygonStrokeColor, double polygonStrokeWidth,
     297                 :            :   const QColor &lineStrokeColor, double lineStrokeWidth,
     298                 :            :   const QColor &pointFillColor, const QColor &pointStrokeColor, double pointSize )
     299                 :            : {
     300                 :          0 :   QgsSimpleFillSymbolLayer *fillSymbolLayer = new QgsSimpleFillSymbolLayer();
     301                 :          0 :   fillSymbolLayer->setFillColor( polygonFillColor );
     302                 :          0 :   fillSymbolLayer->setStrokeColor( polygonStrokeColor );
     303                 :          0 :   fillSymbolLayer->setStrokeWidth( polygonStrokeWidth );
     304                 :          0 :   QgsFillSymbol *fillSymbol = new QgsFillSymbol( QgsSymbolLayerList() << fillSymbolLayer );
     305                 :            : 
     306                 :          0 :   QgsSimpleLineSymbolLayer *lineSymbolLayer = new QgsSimpleLineSymbolLayer;
     307                 :          0 :   lineSymbolLayer->setColor( lineStrokeColor );
     308                 :          0 :   lineSymbolLayer->setWidth( lineStrokeWidth );
     309                 :          0 :   QgsLineSymbol *lineSymbol = new QgsLineSymbol( QgsSymbolLayerList() << lineSymbolLayer );
     310                 :            : 
     311                 :          0 :   QgsSimpleMarkerSymbolLayer *markerSymbolLayer = new QgsSimpleMarkerSymbolLayer;
     312                 :          0 :   markerSymbolLayer->setFillColor( pointFillColor );
     313                 :          0 :   markerSymbolLayer->setStrokeColor( pointStrokeColor );
     314                 :          0 :   markerSymbolLayer->setSize( pointSize );
     315                 :          0 :   QgsMarkerSymbol *markerSymbol = new QgsMarkerSymbol( QgsSymbolLayerList() << markerSymbolLayer );
     316                 :            : 
     317                 :          0 :   QgsVectorTileBasicRendererStyle st1( QStringLiteral( "Polygons" ), QString(), QgsWkbTypes::PolygonGeometry );
     318                 :          0 :   st1.setSymbol( fillSymbol );
     319                 :            : 
     320                 :          0 :   QgsVectorTileBasicRendererStyle st2( QStringLiteral( "Lines" ), QString(), QgsWkbTypes::LineGeometry );
     321                 :          0 :   st2.setSymbol( lineSymbol );
     322                 :            : 
     323                 :          0 :   QgsVectorTileBasicRendererStyle st3( QStringLiteral( "Points" ), QString(), QgsWkbTypes::PointGeometry );
     324                 :          0 :   st3.setSymbol( markerSymbol );
     325                 :            : 
     326                 :          0 :   QList<QgsVectorTileBasicRendererStyle> lst;
     327                 :          0 :   lst << st1 << st2 << st3;
     328                 :          0 :   return lst;
     329                 :          0 : }

Generated by: LCOV version 1.14