QGIS API Documentation  3.24.2-Tisler (13c1a02865)
qgsmergedfeaturerenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmergedfeaturerenderer.h
3  ---------------------
4  begin : December 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson 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 
17 
18 #include "qgssymbol.h"
19 #include "qgssymbollayerutils.h"
20 
21 #include "qgslogger.h"
22 #include "qgsfeature.h"
23 #include "qgsvectorlayer.h"
24 #include "qgssymbollayer.h"
25 #include "qgsogcutils.h"
26 #include "qgspainteffect.h"
27 #include "qgspainteffectregistry.h"
28 #include "qgsstyleentityvisitor.h"
29 
30 #include <QDomDocument>
31 #include <QDomElement>
32 
34  : QgsMergedFeatureRenderer( QStringLiteral( "mergedFeatureRenderer" ), subRenderer )
35 {
36 
37 }
38 
40  : QgsFeatureRenderer( type )
41 {
42  if ( subRenderer )
43  {
44  mSubRenderer.reset( subRenderer );
45  }
46 }
47 
49 {
50  mSubRenderer.reset( subRenderer );
51 }
52 
54 {
55  return mSubRenderer.get();
56 }
57 
58 void QgsMergedFeatureRenderer::setLegendSymbolItem( const QString &key, QgsSymbol *symbol )
59 {
60  if ( !mSubRenderer )
61  return;
62 
63  mSubRenderer->setLegendSymbolItem( key, symbol );
64 }
65 
67 {
68  if ( !mSubRenderer )
69  return false;
70 
71  return mSubRenderer->legendSymbolItemsCheckable();
72 }
73 
75 {
76  if ( !mSubRenderer )
77  return false;
78 
79  return mSubRenderer->legendSymbolItemChecked( key );
80 }
81 
82 void QgsMergedFeatureRenderer::checkLegendSymbolItem( const QString &key, bool state )
83 {
84  if ( !mSubRenderer )
85  return;
86 
87  mSubRenderer->checkLegendSymbolItem( key, state );
88 }
89 
91 {
92  if ( !mSubRenderer )
93  return true;
94 
95  return mSubRenderer->accept( visitor );
96 }
97 
99 {
100  QgsFeatureRenderer::startRender( context, fields );
101 
102  if ( !mSubRenderer )
103  {
104  return;
105  }
106 
107  // first call start render on the sub renderer
108  mSubRenderer->startRender( context, fields );
109 
110  mFeaturesCategories.clear();
111  mSymbolCategories.clear();
112  mFeatureDecorations.clear();
113  mFields = fields;
114 
115  // We compute coordinates of the extent which will serve as exterior ring
116  // for the final polygon
117  // It must be computed in the destination CRS if reprojection is enabled.
118 
119  if ( !context.painter() )
120  {
121  return;
122  }
123 
124  // copy the rendering context
125  mContext = context;
126 
127  // If reprojection is enabled, we must reproject during renderFeature
128  // and act as if there is no reprojection
129  // If we don't do that, there is no need to have a simple rectangular extent
130  // that covers the whole screen
131  // (a rectangle in the destCRS cannot be expressed as valid coordinates in the sourceCRS in general)
132  if ( context.coordinateTransform().isValid() )
133  {
134  // disable projection
136  // recompute extent so that polygon clipping is correct
137  mContext.setExtent( context.mapExtent() );
138  // do we have to recompute the MapToPixel ?
139  }
140 
141  switch ( mOperation )
142  {
143  case InvertOnly:
144  case MergeAndInvert:
145  {
146  // convert viewport to dest CRS
147  // add some space to hide borders and tend to infinity
148  const double buffer = std::max( context.mapExtent().width(), context.mapExtent().height() ) * 0.1;
149  const QRectF outer = context.mapExtent().buffered( buffer ).toRectF();
150  QgsPolylineXY exteriorRing;
151  exteriorRing.reserve( 5 );
152  exteriorRing << outer.topLeft();
153  exteriorRing << outer.topRight();
154  exteriorRing << outer.bottomRight();
155  exteriorRing << outer.bottomLeft();
156  exteriorRing << outer.topLeft();
157 
158  mExtentPolygon.clear();
159  mExtentPolygon.append( exteriorRing );
160  break;
161  }
162 
163  case Merge:
164  break;
165  }
166 }
167 
168 bool QgsMergedFeatureRenderer::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
169 {
170  if ( !context.painter() || !mSubRenderer )
171  {
172  return false;
173  }
174 
175  // store this feature as a feature to render with decoration if needed
176  if ( selected || drawVertexMarker )
177  {
178  mFeatureDecorations.append( FeatureDecoration( feature, selected, drawVertexMarker, layer ) );
179  }
180 
181  // Features are grouped by category of symbols (returned by symbol(s)ForFeature)
182  // This way, users can have multiple inverted polygon fills for a layer,
183  // for instance, with rule based renderer and different symbols
184  // that have transparency.
185  //
186  // In order to assign a unique category to a set of symbols
187  // during each rendering session (between startRender() and stopRender()),
188  // we build an unique id as a QByteArray that is the concatenation
189  // of each symbol's memory address.
190  // The only assumption made here is that symbol(s)ForFeature will
191  // always return the same address for the same symbol(s) shared amongst
192  // different features.
193  // This QByteArray can then be used as a key for a QMap where the list of
194  // features for this category is stored
195  QByteArray catId;
197  {
198  const QgsSymbolList syms( mSubRenderer->symbolsForFeature( feature, context ) );
199  for ( QgsSymbol *sym : syms )
200  {
201  // append the memory address
202  catId.append( reinterpret_cast<const char *>( &sym ), sizeof( sym ) );
203  }
204  }
205  else
206  {
207  if ( QgsSymbol *sym = mSubRenderer->symbolForFeature( feature, context ) )
208  {
209  catId.append( reinterpret_cast<const char *>( &sym ), sizeof( sym ) );
210  }
211  }
212 
213  if ( catId.isEmpty() )
214  {
215  return false;
216  }
217 
218  if ( ! mSymbolCategories.contains( catId ) )
219  {
220  CombinedFeature cFeat;
221  // store the first feature
222  cFeat.feature = feature;
223  mSymbolCategories.insert( catId, mSymbolCategories.count() );
224  mFeaturesCategories.append( cFeat );
225  }
226 
227  // update the geometry
228  CombinedFeature &cFeat = mFeaturesCategories[ mSymbolCategories[catId] ];
229  if ( !feature.hasGeometry() )
230  {
231  return false;
232  }
233  QgsGeometry geom = feature.geometry();
234 
236  if ( xform.isValid() )
237  {
238  geom.transform( xform );
239  }
240 
241  switch ( mOperation )
242  {
244  // fix the polygon if it is not valid
245  if ( ! geom.isGeosValid() )
246  {
247  geom = geom.buffer( 0, 0 );
248  }
249  break;
250 
252  case QgsMergedFeatureRenderer::Merge: // maybe we should also fix for this? not sure if the fixing step was only required for the differencing operation...
253  break;
254  }
255 
256  if ( geom.isNull() )
257  return false; // do not let invalid geometries sneak in!
258 
259  // add the geometry to the list of geometries for this feature
260  cFeat.geometries.append( geom );
261 
262  return true;
263 }
264 
266 {
268  if ( context.renderingStopped() )
269  {
270  if ( mSubRenderer )
271  mSubRenderer->stopRender( mContext );
272  return;
273  }
274 
275  if ( !mSubRenderer )
276  {
277  return;
278  }
279  if ( !context.painter() )
280  {
281  return;
282  }
283 
284  QgsMultiPolygonXY finalMulti; //avoid expensive allocation for list for every feature
285  QgsPolygonXY newPoly;
286 
287  for ( const CombinedFeature &cit : std::as_const( mFeaturesCategories ) )
288  {
289  finalMulti.resize( 0 ); //preserve capacity - don't use clear!
290  QgsFeature feat = cit.feature; // just a copy, so that we do not accumulate geometries again
291 
292  switch ( mOperation )
293  {
295  {
296  QgsGeometry unioned( QgsGeometry::unaryUnion( cit.geometries ) );
297  if ( unioned.type() == QgsWkbTypes::LineGeometry )
298  unioned = unioned.mergeLines();
299  feat.setGeometry( unioned );
300  break;
301  }
302 
304  {
305  // compute the unary union on the polygons
306  const QgsGeometry unioned( QgsGeometry::unaryUnion( cit.geometries ) );
307  // compute the difference with the extent
308  const QgsGeometry rect = QgsGeometry::fromPolygonXY( mExtentPolygon );
309  const QgsGeometry final = rect.difference( unioned );
310  feat.setGeometry( final );
311  break;
312  }
313 
315  {
316  // No preprocessing involved.
317  // We build here a "reversed" geometry of all the polygons
318  //
319  // The final geometry is a multipolygon F, with :
320  // * the first polygon of F having the current extent as its exterior ring
321  // * each polygon's exterior ring is added as interior ring of the first polygon of F
322  // * each polygon's interior ring is added as new polygons in F
323  //
324  // No validity check is done, on purpose, it will be very slow and painting
325  // operations do not need geometries to be valid
326 
327  finalMulti.append( mExtentPolygon );
328  for ( const QgsGeometry &geom : std::as_const( cit.geometries ) )
329  {
330  QgsMultiPolygonXY multi;
331  QgsWkbTypes::Type type = QgsWkbTypes::flatType( geom.constGet()->wkbType() );
332 
334  {
335  multi.append( geom.asPolygon() );
336  }
337  else if ( ( type == QgsWkbTypes::MultiPolygon ) || ( type == QgsWkbTypes::MultiSurface ) )
338  {
339  multi = geom.asMultiPolygon();
340  }
341 
342  for ( int i = 0; i < multi.size(); i++ )
343  {
344  const QgsPolylineXY &exterior = multi[i][0];
345  // add the exterior ring as interior ring to the first polygon
346  // make sure it satisfies at least very basic requirements of GEOS
347  // (otherwise the creation of GEOS geometry will fail)
348  if ( exterior.count() < 4 || exterior[0] != exterior[exterior.count() - 1] )
349  continue;
350  finalMulti[0].append( exterior );
351 
352  // add interior rings as new polygons
353  for ( int j = 1; j < multi[i].size(); j++ )
354  {
355  newPoly.resize( 0 ); //preserve capacity - don't use clear!
356  newPoly.append( multi[i][j] );
357  finalMulti.append( newPoly );
358  }
359  }
360  }
361  feat.setGeometry( QgsGeometry::fromMultiPolygonXY( finalMulti ) );
362  break;
363  }
364  }
365 
366  if ( feat.hasGeometry() )
367  {
368  mContext.expressionContext().setFeature( feat );
369  mSubRenderer->renderFeature( feat, mContext );
370  }
371  }
372 
373  // when no features are visible, we still have to draw the exterior rectangle
374  // warning: when sub renderers have more than one possible symbols,
375  // there is no way to choose a correct one, because there is no attribute here
376  // in that case, nothing will be rendered
377  switch ( mOperation )
378  {
380  break;
383  if ( mFeaturesCategories.isEmpty() )
384  {
385  // empty feature with default attributes
386  QgsFeature feat( mFields );
387  feat.setGeometry( QgsGeometry::fromPolygonXY( mExtentPolygon ) );
388  mSubRenderer->renderFeature( feat, mContext );
389  }
390  break;
391  }
392 
393  // draw feature decorations
394  for ( FeatureDecoration deco : std::as_const( mFeatureDecorations ) )
395  {
396  mSubRenderer->renderFeature( deco.feature, mContext, deco.layer, deco.selected, deco.drawMarkers );
397  }
398 
399  mSubRenderer->stopRender( mContext );
400 }
401 
403 {
404  if ( !mSubRenderer )
405  {
406  return QStringLiteral( "MERGED FEATURES: NULL" );
407  }
408  return "MERGED FEATURES [" + mSubRenderer->dump() + ']';
409 }
410 
412 {
413  QgsMergedFeatureRenderer *newRenderer = nullptr;
414  if ( !mSubRenderer )
415  {
416  newRenderer = new QgsMergedFeatureRenderer( nullptr );
417  }
418  else
419  {
420  newRenderer = new QgsMergedFeatureRenderer( mSubRenderer->clone() );
421  }
422  copyRendererData( newRenderer );
423  return newRenderer;
424 }
425 
427 {
429  //look for an embedded renderer <renderer-v2>
430  QDomElement embeddedRendererElem = element.firstChildElement( QStringLiteral( "renderer-v2" ) );
431  if ( !embeddedRendererElem.isNull() )
432  {
433  QgsFeatureRenderer *renderer = QgsFeatureRenderer::load( embeddedRendererElem, context );
434  r->setEmbeddedRenderer( renderer );
435  }
436  return r;
437 }
438 
439 QDomElement QgsMergedFeatureRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
440 {
441  // clazy:skip
442 
443  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
444  rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "mergedFeatureRenderer" ) );
445 
446  if ( mSubRenderer )
447  {
448  QDomElement embeddedRendererElem = mSubRenderer->save( doc, context );
449  rendererElem.appendChild( embeddedRendererElem );
450  }
451 
452  saveRendererData( doc, rendererElem, context );
453 
454  return rendererElem;
455 }
456 
458 {
459  if ( !mSubRenderer )
460  {
461  return nullptr;
462  }
463  return mSubRenderer->symbolForFeature( feature, context );
464 }
465 
467 {
468  if ( !mSubRenderer )
469  return nullptr;
470  return mSubRenderer->originalSymbolForFeature( feature, context );
471 }
472 
474 {
475  if ( !mSubRenderer )
476  {
477  return QgsSymbolList();
478  }
479  return mSubRenderer->symbolsForFeature( feature, context );
480 }
481 
483 {
484  if ( !mSubRenderer )
485  return QgsSymbolList();
486  return mSubRenderer->originalSymbolsForFeature( feature, context );
487 }
488 
489 QSet<QString> QgsMergedFeatureRenderer::legendKeysForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
490 {
491  if ( !mSubRenderer )
492  return QSet<QString>();
493  return mSubRenderer->legendKeysForFeature( feature, context );
494 }
495 
497 {
498  if ( !mSubRenderer )
499  {
500  return QgsSymbolList();
501  }
502  return mSubRenderer->symbols( context );
503 }
504 
505 QgsFeatureRenderer::Capabilities QgsMergedFeatureRenderer::capabilities()
506 {
507  if ( !mSubRenderer )
508  {
509  return Capabilities();
510  }
511  return mSubRenderer->capabilities();
512 }
513 
514 QSet<QString> QgsMergedFeatureRenderer::usedAttributes( const QgsRenderContext &context ) const
515 {
516  if ( !mSubRenderer )
517  {
518  return QSet<QString>();
519  }
520  return mSubRenderer->usedAttributes( context );
521 }
522 
524 {
525  return mSubRenderer ? mSubRenderer->filterNeedsGeometry() : false;
526 }
527 
529 {
530  if ( !mSubRenderer )
531  {
532  return QgsLegendSymbolList();
533  }
534  return mSubRenderer->legendSymbolItems();
535 }
536 
538 {
539  if ( !mSubRenderer )
540  {
541  return false;
542  }
543  return mSubRenderer->willRenderFeature( feature, context );
544 }
545 
547 {
548  if ( renderer->type() == QLatin1String( "mergedFeatureRenderer" ) )
549  {
550  return dynamic_cast<QgsMergedFeatureRenderer *>( renderer->clone() );
551  }
552 
553  if ( renderer->type() == QLatin1String( "singleSymbol" ) ||
554  renderer->type() == QLatin1String( "categorizedSymbol" ) ||
555  renderer->type() == QLatin1String( "graduatedSymbol" ) ||
556  renderer->type() == QLatin1String( "RuleRenderer" ) )
557  {
558  std::unique_ptr< QgsMergedFeatureRenderer > res = std::make_unique< QgsMergedFeatureRenderer >( renderer->clone() );
559  renderer->copyRendererData( res.get() );
560  return res.release();
561  }
562  else if ( renderer->type() == QLatin1String( "invertedPolygonRenderer" ) )
563  {
564  std::unique_ptr< QgsMergedFeatureRenderer > res = std::make_unique< QgsMergedFeatureRenderer >( renderer->embeddedRenderer() ? renderer->embeddedRenderer()->clone() : nullptr );
565  renderer->copyRendererData( res.get() );
566  return res.release();
567  }
568  return nullptr;
569 }
570 
Class for doing transforms between two map coordinate systems.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QString type() const
Definition: qgsrenderer.h:142
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:52
@ MoreSymbolsPerFeature
May use more than one symbol to render a feature: symbolsForFeature() will return them.
Definition: qgsrenderer.h:264
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
void saveRendererData(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context)
Saves generic renderer data into the specified element.
virtual const QgsFeatureRenderer * embeddedRenderer() const
Returns the current embedded renderer (subrenderer) for this feature renderer.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
Definition: qgsrenderer.cpp:96
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:223
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:163
Container of fields for a vector layer.
Definition: qgsfields.h:45
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
Q_GADGET bool isNull
Definition: qgsgeometry.h:127
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
QgsMergedFeatureRenderer is a polygon or line-only feature renderer used to renderer a set of feature...
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a renderer out of an XML, for loading.
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
void stopRender(QgsRenderContext &context) override
The actual rendering will take place here.
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns list of symbols used for rendering the feature.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
QgsSymbol * originalSymbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns symbol for feature.
QString dump() const override
Returns debug information about this renderer.
QgsMergedFeatureRenderer(QgsFeatureRenderer *embeddedRenderer)
Constructor for QgsMergedFeatureRenderer.
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
QgsSymbolList originalSymbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
Stores renderer properties to an XML element.
@ Merge
Merge features (union/dissolve)
@ InvertOnly
Invert features only (polygons only)
@ MergeAndInvert
Merge and invert features (polygons only)
GeometryOperation mOperation
Operation to apply to collected geometries.
void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
void setEmbeddedRenderer(QgsFeatureRenderer *subRenderer) override
Sets an embedded renderer (subrenderer) for this feature renderer.
std::unique_ptr< QgsFeatureRenderer > mSubRenderer
Embedded renderer.
QgsFeatureRenderer::Capabilities capabilities() override
Returns details about internals of this renderer.
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
bool willRenderFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns whether the renderer will render a feature or not.
static QgsMergedFeatureRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsMergedFeatureRenderer by a conversion from an existing renderer.
bool renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override SIP_THROW(QgsCsException)
Renders a given feature.
QgsMergedFeatureRenderer * clone() const override
Create a deep copy of this renderer.
The class is used as a container of context for various read/write operations on other objects.
QRectF toRectF() const
Returns a QRectF with same coordinates as the rectangle.
Definition: qgsrectangle.h:500
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
QgsRectangle buffered(double width) const
Gets rectangle enlarged by buffer.
Definition: qgsrectangle.h:325
Contains information about the context of a rendering operation.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
An interface for classes which can visit style entity (e.g.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:38
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
Definition: qgsgeometry.h:76
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:52
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:93
QList< QgsLegendSymbolItem > QgsLegendSymbolList
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:44