QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgspointdistancerenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointdistancerenderer.cpp
3  ----------------------------
4  begin : January 26, 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco at hugis dot net
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 
19 #include "qgsgeometry.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgsspatialindex.h"
22 #include "qgsmultipoint.h"
23 #include "qgslogger.h"
24 
25 #include <QDomElement>
26 #include <QPainter>
27 
28 #include <cmath>
29 
30 QgsPointDistanceRenderer::QgsPointDistanceRenderer( const QString &rendererName, const QString &labelAttributeName )
31  : QgsFeatureRenderer( rendererName )
32  , mLabelAttributeName( labelAttributeName )
33  , mLabelIndex( -1 )
34  , mTolerance( 3 )
35  , mToleranceUnit( QgsUnitTypes::RenderMillimeters )
36  , mDrawLabels( true )
37 
38 {
40 }
41 
42 void QgsPointDistanceRenderer::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
43 {
44  mRenderer->toSld( doc, element, props );
45 }
46 
47 
48 bool QgsPointDistanceRenderer::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
49 {
50  Q_UNUSED( drawVertexMarker );
51  Q_UNUSED( context );
52  Q_UNUSED( layer );
53 
54  /*
55  * IMPORTANT: This algorithm is ported to Python in the processing "Points Displacement" algorithm.
56  * Please port any changes/improvements to that algorithm too!
57  */
58 
59  //check if there is already a point at that position
60  if ( !feature.hasGeometry() )
61  return false;
62 
63  QgsMarkerSymbol *symbol = firstSymbolForFeature( feature, context );
64 
65  //if the feature has no symbol (e.g., no matching rule in a rule-based renderer), skip it
66  if ( !symbol )
67  return false;
68 
69  //point position in screen coords
70  QgsGeometry geom = feature.geometry();
71  QgsWkbTypes::Type geomType = geom.wkbType();
72  if ( QgsWkbTypes::flatType( geomType ) != QgsWkbTypes::Point )
73  {
74  //can only render point type
75  return false;
76  }
77 
78  QString label;
79  if ( mDrawLabels )
80  {
81  label = getLabel( feature );
82  }
83 
85  QgsFeature transformedFeature = feature;
86  if ( xform.isValid() )
87  {
88  geom.transform( xform );
89  transformedFeature.setGeometry( geom );
90  }
91 
92  double searchDistance = context.convertToMapUnits( mTolerance, mToleranceUnit, mToleranceMapUnitScale );
93  QgsPointXY point = transformedFeature.geometry().asPoint();
94  QList<QgsFeatureId> intersectList = mSpatialIndex->intersects( searchRect( point, searchDistance ) );
95  if ( intersectList.empty() )
96  {
97  mSpatialIndex->addFeature( transformedFeature );
98  // create new group
99  ClusteredGroup newGroup;
100  newGroup << GroupedFeature( transformedFeature, symbol->clone(), selected, label );
101  mClusteredGroups.push_back( newGroup );
102  // add to group index
103  mGroupIndex.insert( transformedFeature.id(), mClusteredGroups.count() - 1 );
104  mGroupLocations.insert( transformedFeature.id(), point );
105  }
106  else
107  {
108  // find group with closest location to this point (may be more than one within search tolerance)
109  QgsFeatureId minDistFeatureId = intersectList.at( 0 );
110  double minDist = mGroupLocations.value( minDistFeatureId ).distance( point );
111  for ( int i = 1; i < intersectList.count(); ++i )
112  {
113  QgsFeatureId candidateId = intersectList.at( i );
114  double newDist = mGroupLocations.value( candidateId ).distance( point );
115  if ( newDist < minDist )
116  {
117  minDist = newDist;
118  minDistFeatureId = candidateId;
119  }
120  }
121 
122  int groupIdx = mGroupIndex[ minDistFeatureId ];
123  ClusteredGroup &group = mClusteredGroups[groupIdx];
124 
125  // calculate new centroid of group
126  QgsPointXY oldCenter = mGroupLocations.value( minDistFeatureId );
127  mGroupLocations[ minDistFeatureId ] = QgsPointXY( ( oldCenter.x() * group.size() + point.x() ) / ( group.size() + 1.0 ),
128  ( oldCenter.y() * group.size() + point.y() ) / ( group.size() + 1.0 ) );
129 
130  // add to a group
131  group << GroupedFeature( transformedFeature, symbol->clone(), selected, label );
132  // add to group index
133  mGroupIndex.insert( transformedFeature.id(), groupIdx );
134  }
135 
136  return true;
137 }
138 
139 void QgsPointDistanceRenderer::drawGroup( const ClusteredGroup &group, QgsRenderContext &context )
140 {
141  //calculate centroid of all points, this will be center of group
142  QgsMultiPoint *groupMultiPoint = new QgsMultiPoint();
143  Q_FOREACH ( const GroupedFeature &f, group )
144  {
145  groupMultiPoint->addGeometry( f.feature.geometry().constGet()->clone() );
146  }
147  QgsGeometry groupGeom( groupMultiPoint );
148  QgsGeometry centroid = groupGeom.centroid();
149  QPointF pt = centroid.asQPointF();
150  context.mapToPixel().transformInPlace( pt.rx(), pt.ry() );
151 
152  context.expressionContext().appendScope( createGroupScope( group ) );
153  drawGroup( pt, context, group );
154  delete context.expressionContext().popScope();
155 }
156 
158 {
159  mRenderer.reset( r );
160 }
161 
163 {
164  return mRenderer.get();
165 }
166 
167 void QgsPointDistanceRenderer::setLegendSymbolItem( const QString &key, QgsSymbol *symbol )
168 {
169  if ( !mRenderer )
170  return;
171 
172  mRenderer->setLegendSymbolItem( key, symbol );
173 }
174 
176 {
177  if ( !mRenderer )
178  return false;
179 
180  return mRenderer->legendSymbolItemsCheckable();
181 }
182 
184 {
185  if ( !mRenderer )
186  return false;
187 
188  return mRenderer->legendSymbolItemChecked( key );
189 }
190 
191 void QgsPointDistanceRenderer::checkLegendSymbolItem( const QString &key, bool state )
192 {
193  if ( !mRenderer )
194  return;
195 
196  mRenderer->checkLegendSymbolItem( key, state );
197 }
198 
200 {
201  if ( !mRenderer )
202  return QgsFeatureRenderer::filter( fields );
203  else
204  return mRenderer->filter( fields );
205 }
206 
207 QSet<QString> QgsPointDistanceRenderer::usedAttributes( const QgsRenderContext &context ) const
208 {
209  QSet<QString> attributeList;
210  if ( !mLabelAttributeName.isEmpty() )
211  {
212  attributeList.insert( mLabelAttributeName );
213  }
214  if ( mRenderer )
215  {
216  attributeList += mRenderer->usedAttributes( context );
217  }
218  return attributeList;
219 }
220 
222 {
223  return mRenderer ? mRenderer->filterNeedsGeometry() : false;
224 }
225 
226 QgsFeatureRenderer::Capabilities QgsPointDistanceRenderer::capabilities()
227 {
228  if ( !mRenderer )
229  {
230  return nullptr;
231  }
232  return mRenderer->capabilities();
233 }
234 
236 {
237  if ( !mRenderer )
238  {
239  return QgsSymbolList();
240  }
241  return mRenderer->symbols( context );
242 }
243 
245 {
246  if ( !mRenderer )
247  {
248  return nullptr;
249  }
250  return mRenderer->symbolForFeature( feature, context );
251 }
252 
254 {
255  if ( !mRenderer )
256  return nullptr;
257  return mRenderer->originalSymbolForFeature( feature, context );
258 }
259 
261 {
262  if ( !mRenderer )
263  {
264  return QgsSymbolList();
265  }
266  return mRenderer->symbolsForFeature( feature, context );
267 }
268 
270 {
271  if ( !mRenderer )
272  return QgsSymbolList();
273  return mRenderer->originalSymbolsForFeature( feature, context );
274 }
275 
276 QSet< QString > QgsPointDistanceRenderer::legendKeysForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
277 {
278  if ( !mRenderer )
279  return QSet< QString >() << QString();
280  return mRenderer->legendKeysForFeature( feature, context );
281 }
282 
284 {
285  if ( !mRenderer )
286  {
287  return false;
288  }
289  return mRenderer->willRenderFeature( feature, context );
290 }
291 
292 
294 {
295  QgsFeatureRenderer::startRender( context, fields );
296 
297  mRenderer->startRender( context, fields );
298 
299  mClusteredGroups.clear();
300  mGroupIndex.clear();
301  mGroupLocations.clear();
303 
304  if ( mLabelAttributeName.isEmpty() )
305  {
306  mLabelIndex = -1;
307  }
308  else
309  {
311  }
312 
313  if ( mMinLabelScale <= 0 || context.rendererScale() < mMinLabelScale )
314  {
315  mDrawLabels = true;
316  }
317  else
318  {
319  mDrawLabels = false;
320  }
321 }
322 
324 {
326 
327  //printInfoDisplacementGroups(); //just for debugging
328 
329  if ( !context.renderingStopped() )
330  {
331  Q_FOREACH ( const ClusteredGroup &group, mClusteredGroups )
332  {
333  drawGroup( group, context );
334  }
335  }
336 
337  mClusteredGroups.clear();
338  mGroupIndex.clear();
339  mGroupLocations.clear();
340  delete mSpatialIndex;
341  mSpatialIndex = nullptr;
342 
343  mRenderer->stopRender( context );
344 }
345 
347 {
348  if ( mRenderer )
349  {
350  return mRenderer->legendSymbolItems();
351  }
352  return QgsLegendSymbolList();
353 }
354 
355 QgsRectangle QgsPointDistanceRenderer::searchRect( const QgsPointXY &p, double distance ) const
356 {
357  return QgsRectangle( p.x() - distance, p.y() - distance, p.x() + distance, p.y() + distance );
358 }
359 
360 void QgsPointDistanceRenderer::printGroupInfo() const
361 {
362 #ifdef QGISDEBUG
363  int nGroups = mClusteredGroups.size();
364  QgsDebugMsg( "number of displacement groups:" + QString::number( nGroups ) );
365  for ( int i = 0; i < nGroups; ++i )
366  {
367  QgsDebugMsg( "***************displacement group " + QString::number( i ) );
368  Q_FOREACH ( const GroupedFeature &feature, mClusteredGroups.at( i ) )
369  {
370  QgsDebugMsg( FID_TO_STRING( feature.feature.id() ) );
371  }
372  }
373 #endif
374 }
375 
376 QString QgsPointDistanceRenderer::getLabel( const QgsFeature &feature ) const
377 {
378  QString attribute;
379  QgsAttributes attrs = feature.attributes();
380  if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() )
381  {
382  attribute = attrs.at( mLabelIndex ).toString();
383  }
384  return attribute;
385 }
386 
387 void QgsPointDistanceRenderer::drawLabels( QPointF centerPoint, QgsSymbolRenderContext &context, const QList<QPointF> &labelShifts, const ClusteredGroup &group )
388 {
389  QPainter *p = context.renderContext().painter();
390  if ( !p )
391  {
392  return;
393  }
394 
395  QPen labelPen( mLabelColor );
396  p->setPen( labelPen );
397 
398  //scale font (for printing)
399  QFont pixelSizeFont = mLabelFont;
400  pixelSizeFont.setPixelSize( context.outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) );
401  QFont scaledFont = pixelSizeFont;
402  scaledFont.setPixelSize( pixelSizeFont.pixelSize() );
403  p->setFont( scaledFont );
404 
405  QFontMetricsF fontMetrics( pixelSizeFont );
406  QPointF currentLabelShift; //considers the signs to determine the label position
407 
408  QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin();
409  ClusteredGroup::const_iterator groupIt = group.constBegin();
410 
411  for ( ; labelPosIt != labelShifts.constEnd() && groupIt != group.constEnd(); ++labelPosIt, ++groupIt )
412  {
413  currentLabelShift = *labelPosIt;
414  if ( currentLabelShift.x() < 0 )
415  {
416  currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( groupIt->label ) );
417  }
418  if ( currentLabelShift.y() > 0 )
419  {
420  currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() );
421  }
422 
423  QPointF drawingPoint( centerPoint + currentLabelShift );
424  p->save();
425  p->translate( drawingPoint.x(), drawingPoint.y() );
426  p->drawText( QPointF( 0, 0 ), groupIt->label );
427  p->restore();
428  }
429 }
430 
431 QgsExpressionContextScope *QgsPointDistanceRenderer::createGroupScope( const ClusteredGroup &group ) const
432 {
434  if ( group.size() > 1 )
435  {
436  //scan through symbols to check color, e.g., if all clustered symbols are same color
437  QColor groupColor;
438  ClusteredGroup::const_iterator groupIt = group.constBegin();
439  for ( ; groupIt != group.constEnd(); ++groupIt )
440  {
441  if ( !groupIt->symbol() )
442  continue;
443 
444  if ( !groupColor.isValid() )
445  {
446  groupColor = groupIt->symbol()->color();
447  }
448  else
449  {
450  if ( groupColor != groupIt->symbol()->color() )
451  {
452  groupColor = QColor();
453  break;
454  }
455  }
456  }
457 
458  if ( groupColor.isValid() )
459  {
461  }
462  else
463  {
464  //mixed colors
466  }
467 
469  }
470  if ( !group.empty() )
471  {
472  // data defined properties may require a feature in the expression context, so just use first feature in group
473  clusterScope->setFeature( group.at( 0 ).feature );
474  }
475  return clusterScope;
476 }
477 
478 QgsMarkerSymbol *QgsPointDistanceRenderer::firstSymbolForFeature( const QgsFeature &feature, QgsRenderContext &context )
479 {
480  if ( !mRenderer )
481  {
482  return nullptr;
483  }
484 
485  QgsSymbolList symbolList = mRenderer->symbolsForFeature( feature, context );
486  if ( symbolList.isEmpty() )
487  {
488  return nullptr;
489  }
490 
491  return dynamic_cast< QgsMarkerSymbol * >( symbolList.at( 0 ) );
492 }
QgsSpatialIndex * mSpatialIndex
Spatial index for fast lookup of nearby points.
QgsFeatureId id
Definition: qgsfeature.h:64
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
Single variable definition for use within a QgsExpressionContextScope.
A rectangle specified with double values.
Definition: qgsrectangle.h:40
QString mLabelAttributeName
Attribute name for labeling. An empty string indicates that no labels should be rendered.
QList< QgsLegendSymbolItem > QgsLegendSymbolList
QgsUnitTypes::RenderUnit mToleranceUnit
Unit for distance tolerance.
QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns list of symbols used for rendering the feature.
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsPointDistanceRenderer(const QString &rendererName, const QString &labelAttributeName=QString())
Constructor for QgsPointDistanceRenderer.
Multi point geometry collection.
Definition: qgsmultipoint.h:29
QgsFeatureRenderer::Capabilities capabilities() override
Returns details about internals of this renderer.
void checkLegendSymbolItem(const QString &key, bool state) override
item in symbology was checked
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
double y
Definition: qgspointxy.h:48
double rendererScale() const
Returns the renderer map scale.
A class to represent a 2D point.
Definition: qgspointxy.h:43
QPointF asQPointF() const
Returns contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPoint...
Helper functions for various unit types.
Definition: qgsunittypes.h:37
double convertToMapUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
virtual QString filter(const QgsFields &fields=QgsFields())
If a renderer does not require all the features this method may be overridden and return an expressio...
Definition: qgsrenderer.h:193
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Container of fields for a vector layer.
Definition: qgsfields.h:42
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
QgsSymbol * originalSymbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns symbol for feature.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
QMap< QgsFeatureId, int > mGroupIndex
Mapping of feature ID to the feature&#39;s group index.
double outputLineWidth(double width) const
Definition: qgssymbol.cpp:1096
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:577
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:732
bool mDrawLabels
Whether labels should be drawn for points. This is set internally from startRender() depending on sca...
double mMinLabelScale
Maximum scale denominator for label display. A zero value indicates no scale limitation.
void drawLabels(QPointF centerPoint, QgsSymbolRenderContext &context, const QList< QPointF > &labelShifts, const ClusteredGroup &group)
Renders the labels for a group.
static QString encodeColor(const QColor &color)
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:43
double mTolerance
Distance tolerance. Points that are closer together than this distance are considered clustered...
bool renderingStopped() const
Returns TRUE if the rendering operation has been stopped and any ongoing rendering should be canceled...
QMap< QgsFeatureId, QgsPointXY > mGroupLocations
Mapping of feature ID to approximate group location.
bool willRenderFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns whether the renderer will render a feature or not.
QgsSymbolList originalSymbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
QColor mLabelColor
Label text color.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:320
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:572
QgsMapUnitScale mToleranceMapUnitScale
Map unit scale for distance tolerance.
double x
Definition: qgspointxy.h:47
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
QgsExpressionContext & expressionContext()
Gets the expression context.
Contains properties for a feature within a clustered group.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
QString filter(const QgsFields &fields=QgsFields()) override
If a renderer does not require all the features this method may be overridden and return an expressio...
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Contains information about the context of a rendering operation.
A spatial index for QgsFeature objects.
QPainter * painter()
Returns the destination QPainter for the render operation.
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:30
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
Definition: qgsrenderer.cpp:92
std::unique_ptr< QgsFeatureRenderer > mRenderer
Embedded base renderer. This can be used for rendering individual, isolated points.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
Class for doing transforms between two map coordinate systems.
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
const QgsMapToPixel & mapToPixel() const
Returns the context&#39;s map to pixel transform, which transforms between map coordinates and device coo...
QList< QgsPointDistanceRenderer::GroupedFeature > ClusteredGroup
A group of clustered points (ie features within the distance tolerance).
bool renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override SIP_THROW(QgsCsException)
Render a feature using this renderer in the given context.
QgsGeometry geometry
Definition: qgsfeature.h:67
QList< ClusteredGroup > mClusteredGroups
Groups of features that are considered clustered together.
int mLabelIndex
Label attribute index (or -1 if none). This index is not stored, it is requested in the startRender()...
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a feature to the index.
void setEmbeddedRenderer(QgsFeatureRenderer *r) override
Sets an embedded renderer (subrenderer) for this feature renderer.
static QgsFeatureRenderer * defaultRenderer(QgsWkbTypes::GeometryType geomType)
Returns a new renderer - used by default in vector layers.
Definition: qgsrenderer.cpp:75
A vector of attributes.
Definition: qgsattributes.h:57
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:565
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1590
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.