QGIS API Documentation  2.99.0-Master (cd0ba91)
qgspointdisplacementrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointdisplacementrenderer.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 "qgssymbollayerutils.h"
20 #include "qgsfontutils.h"
21 #include "qgspainteffectregistry.h"
22 #include "qgspainteffect.h"
24 
25 #include <QPainter>
26 #include <cmath>
27 
29  : QgsPointDistanceRenderer( QStringLiteral( "pointDisplacement" ), labelAttributeName )
30  , mCircleColor( QColor( 125, 125, 125 ) )
31 {
32  mCenterSymbol.reset( new QgsMarkerSymbol() );
33 }
34 
36 {
38  if ( mRenderer )
39  r->setEmbeddedRenderer( mRenderer->clone() );
40  r->setCircleWidth( mCircleWidth );
41  r->setCircleColor( mCircleColor );
44  r->setPlacement( mPlacement );
45  r->setCircleRadiusAddition( mCircleRadiusAddition );
50  if ( mCenterSymbol )
51  {
52  r->setCenterSymbol( mCenterSymbol->clone() );
53  }
54  copyRendererData( r );
55  return r;
56 }
57 
58 void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group )
59 {
60 
61  //calculate max diagonal size from all symbols in group
62  double diagonal = 0;
63 
64  Q_FOREACH ( const GroupedFeature &feature, group )
65  {
66  if ( QgsMarkerSymbol *symbol = feature.symbol() )
67  {
68  diagonal = std::max( diagonal, context.convertToPainterUnits( M_SQRT2 * symbol->size(),
69  symbol->sizeUnit(), symbol->sizeMapUnitScale() ) );
70  }
71  }
72 
73  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false );
74 
75  QList<QPointF> symbolPositions;
76  QList<QPointF> labelPositions;
77  double circleRadius = -1.0;
78  double gridRadius = -1.0;
79  int gridSize = -1;
80 
81  calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize );
82 
83  //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids
84  if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 )
85  {
86  //draw circle
87  if ( circleRadius > 0 )
88  drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
89  //draw grid
90  else
91  drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
92  }
93 
94  if ( group.size() > 1 )
95  {
96  //draw mid point
97  QgsFeature firstFeature = group.at( 0 ).feature;
98  if ( mCenterSymbol )
99  {
100  mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
101  }
102  else
103  {
104  context.painter()->drawRect( QRectF( centerPoint.x() - symbolContext.outputLineWidth( 1 ), centerPoint.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
105  }
106  }
107 
108  //draw symbols on the circle
109  drawSymbols( group, context, symbolPositions );
110  //and also the labels
111  if ( mLabelIndex >= 0 )
112  {
113  drawLabels( centerPoint, symbolContext, labelPositions, group );
114  }
115 }
116 
117 
119 {
120  if ( mCenterSymbol )
121  {
122  mCenterSymbol->startRender( context, fields );
123  }
124 
125  QgsPointDistanceRenderer::startRender( context, fields );
126 }
127 
129 {
131  if ( mCenterSymbol )
132  {
133  mCenterSymbol->stopRender( context );
134  }
135 }
136 
138 {
140  r->setLabelAttributeName( symbologyElem.attribute( QStringLiteral( "labelAttributeName" ) ) );
141  QFont labelFont;
142  if ( !QgsFontUtils::setFromXmlChildNode( labelFont, symbologyElem, QStringLiteral( "labelFontProperties" ) ) )
143  {
144  labelFont.fromString( symbologyElem.attribute( QStringLiteral( "labelFont" ), QLatin1String( "" ) ) );
145  }
146  r->setLabelFont( labelFont );
147  r->setPlacement( static_cast< Placement >( symbologyElem.attribute( QStringLiteral( "placement" ), QStringLiteral( "0" ) ).toInt() ) );
148  r->setCircleWidth( symbologyElem.attribute( QStringLiteral( "circleWidth" ), QStringLiteral( "0.4" ) ).toDouble() );
149  r->setCircleColor( QgsSymbolLayerUtils::decodeColor( symbologyElem.attribute( QStringLiteral( "circleColor" ), QLatin1String( "" ) ) ) );
150  r->setLabelColor( QgsSymbolLayerUtils::decodeColor( symbologyElem.attribute( QStringLiteral( "labelColor" ), QLatin1String( "" ) ) ) );
151  r->setCircleRadiusAddition( symbologyElem.attribute( QStringLiteral( "circleRadiusAddition" ), QStringLiteral( "0.0" ) ).toDouble() );
152  r->setMinimumLabelScale( symbologyElem.attribute( QStringLiteral( "maxLabelScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble() );
153  r->setTolerance( symbologyElem.attribute( QStringLiteral( "tolerance" ), QStringLiteral( "0.00001" ) ).toDouble() );
154  r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( QStringLiteral( "toleranceUnit" ), QStringLiteral( "MapUnit" ) ) ) );
155  r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( QStringLiteral( "toleranceUnitScale" ) ) ) );
156 
157  //look for an embedded renderer <renderer-v2>
158  QDomElement embeddedRendererElem = symbologyElem.firstChildElement( QStringLiteral( "renderer-v2" ) );
159  if ( !embeddedRendererElem.isNull() )
160  {
161  r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
162  }
163 
164  //center symbol
165  QDomElement centerSymbolElem = symbologyElem.firstChildElement( QStringLiteral( "symbol" ) );
166  if ( !centerSymbolElem.isNull() )
167  {
168  r->setCenterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ) );
169  }
170  return r;
171 }
172 
174 {
175  return mCenterSymbol.get();
176 }
177 
178 QDomElement QgsPointDisplacementRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
179 {
180  QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
181  rendererElement.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
182  rendererElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "pointDisplacement" ) );
183  rendererElement.setAttribute( QStringLiteral( "labelAttributeName" ), mLabelAttributeName );
184  rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, QStringLiteral( "labelFontProperties" ) ) );
185  rendererElement.setAttribute( QStringLiteral( "circleWidth" ), QString::number( mCircleWidth ) );
186  rendererElement.setAttribute( QStringLiteral( "circleColor" ), QgsSymbolLayerUtils::encodeColor( mCircleColor ) );
187  rendererElement.setAttribute( QStringLiteral( "labelColor" ), QgsSymbolLayerUtils::encodeColor( mLabelColor ) );
188  rendererElement.setAttribute( QStringLiteral( "circleRadiusAddition" ), QString::number( mCircleRadiusAddition ) );
189  rendererElement.setAttribute( QStringLiteral( "placement" ), static_cast< int >( mPlacement ) );
190  rendererElement.setAttribute( QStringLiteral( "maxLabelScaleDenominator" ), QString::number( mMinLabelScale ) );
191  rendererElement.setAttribute( QStringLiteral( "tolerance" ), QString::number( mTolerance ) );
192  rendererElement.setAttribute( QStringLiteral( "toleranceUnit" ), QgsUnitTypes::encodeUnit( mToleranceUnit ) );
193  rendererElement.setAttribute( QStringLiteral( "toleranceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
194 
195  if ( mRenderer )
196  {
197  QDomElement embeddedRendererElem = mRenderer->save( doc, context );
198  rendererElement.appendChild( embeddedRendererElem );
199  }
200  if ( mCenterSymbol )
201  {
202  QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "centerSymbol" ), mCenterSymbol.get(), doc, context );
203  rendererElement.appendChild( centerSymbolElem );
204  }
205 
207  mPaintEffect->saveProperties( doc, rendererElement );
208 
209  if ( !mOrderBy.isEmpty() )
210  {
211  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
212  mOrderBy.save( orderBy );
213  rendererElement.appendChild( orderBy );
214  }
215  rendererElement.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
216 
217  return rendererElement;
218 }
219 
221 {
222  QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
223  if ( mCenterSymbol )
224  attr.unite( mCenterSymbol->usedAttributes( context ) );
225  return attr;
226 }
227 
229 {
230  mCenterSymbol.reset( symbol );
231 }
232 
233 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition,
234  double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, double &gridRadius,
235  int &gridSize ) const
236 {
237  symbolPositions.clear();
238  labelShifts.clear();
239 
240  if ( nPosition < 1 )
241  {
242  return;
243  }
244  else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
245  {
246  symbolPositions.append( centerPoint );
247  labelShifts.append( QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
248  return;
249  }
250 
251  double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition );
252 
253  switch ( mPlacement )
254  {
255  case Ring:
256  {
257  double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 * M_PI );
258  double radius = std::max( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
259 
260  double fullPerimeter = 2 * M_PI;
261  double angleStep = fullPerimeter / nPosition;
262  for ( double currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
263  {
264  double sinusCurrentAngle = std::sin( currentAngle );
265  double cosinusCurrentAngle = std::cos( currentAngle );
266  QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
267  QPointF labelShift( ( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
268  symbolPositions.append( centerPoint + positionShift );
269  labelShifts.append( labelShift );
270  }
271 
272  circleRadius = radius;
273  break;
274  }
275  case ConcentricRings:
276  {
277  double centerDiagonal = symbolContext.renderContext().convertToPainterUnits( M_SQRT2 * mCenterSymbol->size(),
278  mCenterSymbol->sizeUnit(), mCenterSymbol->sizeMapUnitScale() );
279 
280  int pointsRemaining = nPosition;
281  int ringNumber = 1;
282  double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
283  while ( pointsRemaining > 0 )
284  {
285  double radiusCurrentRing = std::max( firstRingRadius + ( ringNumber - 1 ) * symbolDiagonal + ringNumber * circleAdditionPainterUnits, 0.0 );
286  int maxPointsCurrentRing = std::max( std::floor( 2 * M_PI * radiusCurrentRing / symbolDiagonal ), 1.0 );
287  int actualPointsCurrentRing = std::min( maxPointsCurrentRing, pointsRemaining );
288 
289  double angleStep = 2 * M_PI / actualPointsCurrentRing;
290  double currentAngle = 0.0;
291  for ( int i = 0; i < actualPointsCurrentRing; ++i )
292  {
293  double sinusCurrentAngle = std::sin( currentAngle );
294  double cosinusCurrentAngle = std::cos( currentAngle );
295  QPointF positionShift( radiusCurrentRing * sinusCurrentAngle, radiusCurrentRing * cosinusCurrentAngle );
296  QPointF labelShift( ( radiusCurrentRing + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radiusCurrentRing + symbolDiagonal / 2 ) * cosinusCurrentAngle );
297  symbolPositions.append( centerPoint + positionShift );
298  labelShifts.append( labelShift );
299  currentAngle += angleStep;
300  }
301 
302  pointsRemaining -= actualPointsCurrentRing;
303  ringNumber++;
304  circleRadius = radiusCurrentRing;
305  }
306  break;
307  }
308  case Grid:
309  {
310  double centerDiagonal = symbolContext.renderContext().convertToPainterUnits( M_SQRT2 * mCenterSymbol->size(),
311  mCenterSymbol->sizeUnit(), mCenterSymbol->sizeMapUnitScale() );
312  int pointsRemaining = nPosition;
313  gridSize = std::ceil( std::sqrt( pointsRemaining ) );
314  if ( pointsRemaining - std::pow( gridSize - 1, 2 ) < gridSize )
315  gridSize -= 1;
316  double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
317  double userPointRadius = originalPointRadius + circleAdditionPainterUnits;
318 
319  int yIndex = 0;
320  while ( pointsRemaining > 0 )
321  {
322  for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
323  {
324  QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
325  QPointF labelShift( ( userPointRadius + symbolDiagonal / 2 ) * xIndex, ( userPointRadius + symbolDiagonal / 2 ) * yIndex );
326  symbolPositions.append( centerPoint + positionShift );
327  labelShifts.append( labelShift );
328  pointsRemaining--;
329  }
330  yIndex++;
331  }
332 
333  centralizeGrid( symbolPositions, userPointRadius, gridSize );
334  centralizeGrid( labelShifts, userPointRadius, gridSize );
335  gridRadius = userPointRadius;
336  break;
337  }
338  }
339 }
340 
341 void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
342 {
343  double shiftAmount = -radius * ( size - 1.0 ) / 2.0;
344  QPointF centralShift( shiftAmount, shiftAmount );
345  for ( int i = 0; i < pointSymbolPositions.size(); ++i )
346  {
347  pointSymbolPositions[i] += centralShift;
348  }
349 }
350 
351 void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
352  QList<QPointF> pointSymbolPositions, int nSymbols )
353 {
354  QPainter *p = context.renderContext().painter();
355  if ( nSymbols < 2 || !p ) //draw grid only if multiple features
356  {
357  return;
358  }
359 
360  QPen gridPen( mCircleColor );
361  gridPen.setWidthF( context.outputLineWidth( mCircleWidth ) );
362  p->setPen( gridPen );
363 
364  for ( int i = 0; i < pointSymbolPositions.size(); ++i )
365  {
366  if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
367  {
368  QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
369  p->drawLine( gridLineRow );
370  }
371 
372  if ( i + gridSizeUnits < pointSymbolPositions.size() )
373  {
374  QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
375  p->drawLine( gridLineColumn );
376  }
377  }
378 }
379 
380 void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols )
381 {
382  QPainter *p = context.renderContext().painter();
383  if ( nSymbols < 2 || !p ) //draw circle only if multiple features
384  {
385  return;
386  }
387 
388  //draw Circle
389  QPen circlePen( mCircleColor );
390  circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) );
391  p->setPen( circlePen );
392  p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
393 }
394 
395 void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions )
396 {
397  QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
398  ClusteredGroup::const_iterator groupIt = group.constBegin();
399  for ( ; symbolPosIt != symbolPositions.constEnd() && groupIt != group.constEnd();
400  ++symbolPosIt, ++groupIt )
401  {
402  context.expressionContext().setFeature( groupIt->feature );
403  groupIt->symbol()->startRender( context );
404  groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
405  groupIt->symbol()->stopRender( context );
406  }
407 }
408 
410 {
411  if ( renderer->type() == QLatin1String( "pointDisplacement" ) )
412  {
413  return dynamic_cast<QgsPointDisplacementRenderer *>( renderer->clone() );
414  }
415  else if ( renderer->type() == QLatin1String( "singleSymbol" ) ||
416  renderer->type() == QLatin1String( "categorizedSymbol" ) ||
417  renderer->type() == QLatin1String( "graduatedSymbol" ) ||
418  renderer->type() == QLatin1String( "RuleRenderer" ) )
419  {
421  pointRenderer->setEmbeddedRenderer( renderer->clone() );
422  return pointRenderer;
423  }
424  else if ( renderer->type() == QLatin1String( "pointCluster" ) )
425  {
427  const QgsPointClusterRenderer *clusterRenderer = static_cast< const QgsPointClusterRenderer * >( renderer );
428  if ( clusterRenderer->embeddedRenderer() )
429  pointRenderer->setEmbeddedRenderer( clusterRenderer->embeddedRenderer()->clone() );
430  pointRenderer->setTolerance( clusterRenderer->tolerance() );
431  pointRenderer->setToleranceUnit( clusterRenderer->toleranceUnit() );
432  pointRenderer->setToleranceMapUnitScale( clusterRenderer->toleranceMapUnitScale() );
433  if ( const_cast< QgsPointClusterRenderer * >( clusterRenderer )->clusterSymbol() )
434  pointRenderer->setCenterSymbol( const_cast< QgsPointClusterRenderer * >( clusterRenderer )->clusterSymbol()->clone() );
435  return pointRenderer;
436  }
437  else
438  {
439  return nullptr;
440  }
441 }
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
The class is used as a container of context for various read/write operations on other objects...
QString mLabelAttributeName
Attribute name for labeling. An empty string indicates that no labels should be rendered.
static QgsFeatureRenderer * create(QDomElement &symbologyElem, const QgsReadWriteContext &context)
Create a renderer from XML element.
Place points in a grid around group.
QgsMarkerSymbol * centerSymbol()
Returns the symbol for the center of a displacement group (but not ownership of the symbol)...
QgsPointDisplacementRenderer * clone() const override
Create a deep copy of this renderer.
QgsUnitTypes::RenderUnit mToleranceUnit
Unit for distance tolerance.
QgsFeatureRequest::OrderBy mOrderBy
Definition: qgsrenderer.h:517
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setLabelFont(const QFont &font)
Sets the font used for labeling points.
QgsFeatureRequest::OrderBy orderBy() const
Get the order in which features shall be processed by this renderer.
void setTolerance(double distance)
Sets the tolerance distance for grouping points.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
void setLabelColor(const QColor &color)
Sets the color to use for for labeling points.
void setToleranceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the distance tolerance.
void setToleranceUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the tolerance distance.
double outputLineWidth(double width) const
Definition: qgssymbol.cpp:1030
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
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.
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:49
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:501
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
virtual void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
void setCenterSymbol(QgsMarkerSymbol *symbol)
Sets the center symbol for a displacement group.
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
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)
QgsPointDisplacementRenderer(const QString &labelAttributeName=QString())
Constructor for QgsPointDisplacementRenderer.
QFont labelFont() const
Returns the font used for labeling points.
QString type() const
Definition: qgsrenderer.h:126
double mTolerance
Distance tolerance. Points that are closer together than this distance are considered clustered...
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
void setCircleColor(const QColor &color)
Sets the color used for drawing the displacement group circle.
void setLabelAttributeName(const QString &name)
Sets the attribute name for labeling points.
A renderer that automatically clusters points with the same geographic position.
Place points in concentric rings around group.
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
void setPlacement(Placement placement)
Sets the placement method used for dispersing the points.
QColor mLabelColor
Label text color.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
QgsRenderContext & renderContext()
Definition: qgssymbol.h:450
QgsMapUnitScale mToleranceMapUnitScale
Map unit scale for distance tolerance.
double tolerance() const
Returns the tolerance distance for grouping points.
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
const QgsMapUnitScale & toleranceMapUnitScale() const
Returns the map unit scale object for the distance tolerance.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
Place points in a single ring around group.
QgsExpressionContext & expressionContext()
Gets the expression context.
Contains properties for a feature within a clustered group.
A renderer that automatically displaces points with the same geographic location. ...
QgsMarkerSymbol * symbol() const
Base symbol for rendering feature.
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setMinimumLabelScale(double scale)
Sets the minimum map scale (i.e.
std::unique_ptr< QgsFeatureRenderer > mRenderer
Embedded base renderer. This can be used for rendering individual, isolated points.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
static Q_INVOKABLE RenderUnit decodeRenderUnit(const QString &string, bool *ok=0)
Decodes a render unit from a string.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:48
QList< QgsPointDistanceRenderer::GroupedFeature > ClusteredGroup
A group of clustered points (ie features within the distance tolerance).
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
int mLabelIndex
Label attribute index (or -1 if none). This index is not stored, it is requested in the startRender()...
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Return a list of attributes required by this renderer.
void setCircleRadiusAddition(double distance)
Sets a factor for increasing the ring size of displacement groups.
void setEmbeddedRenderer(QgsFeatureRenderer *r) override
Sets an embedded renderer (subrenderer) for this feature renderer.
static QgsPointDisplacementRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointDisplacementRenderer from an existing renderer.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
void setCircleWidth(double width)
Sets the line width for the displacement group circle.
static QColor decodeColor(const QString &str)
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Return a list of attributes required by this renderer.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.