QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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  for ( const GroupedFeature &feature : group )
65  {
66  if ( QgsMarkerSymbol *symbol = feature.symbol() )
67  {
68  diagonal = std::max( diagonal, M_SQRT2 * symbol->size( context ) );
69  }
70  }
71 
72  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false );
73 
74  QList<QPointF> symbolPositions;
75  QList<QPointF> labelPositions;
76  double circleRadius = -1.0;
77  double gridRadius = -1.0;
78  int gridSize = -1;
79 
80  calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize );
81 
82  //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids
83  if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 )
84  {
85  //draw circle
86  if ( circleRadius > 0 )
87  drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
88  //draw grid
89  else
90  drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
91  }
92 
93  if ( group.size() > 1 )
94  {
95  //draw mid point
96  QgsFeature firstFeature = group.at( 0 ).feature;
97  if ( mCenterSymbol )
98  {
99  mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
100  }
101  else
102  {
103  context.painter()->drawRect( QRectF( centerPoint.x() - symbolContext.outputLineWidth( 1 ), centerPoint.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
104  }
105  }
106 
107  //draw symbols on the circle
108  drawSymbols( group, context, symbolPositions );
109  //and also the labels
110  if ( mLabelIndex >= 0 )
111  {
112  drawLabels( centerPoint, symbolContext, labelPositions, group );
113  }
114 }
115 
116 
118 {
119  if ( mCenterSymbol )
120  {
121  mCenterSymbol->startRender( context, fields );
122  }
123 
124  QgsPointDistanceRenderer::startRender( context, fields );
125 }
126 
128 {
130  if ( mCenterSymbol )
131  {
132  mCenterSymbol->stopRender( context );
133  }
134 }
135 
137 {
139  r->setLabelAttributeName( symbologyElem.attribute( QStringLiteral( "labelAttributeName" ) ) );
140  QFont labelFont;
141  if ( !QgsFontUtils::setFromXmlChildNode( labelFont, symbologyElem, QStringLiteral( "labelFontProperties" ) ) )
142  {
143  labelFont.fromString( symbologyElem.attribute( QStringLiteral( "labelFont" ), QString() ) );
144  }
145  r->setLabelFont( labelFont );
146  r->setPlacement( static_cast< Placement >( symbologyElem.attribute( QStringLiteral( "placement" ), QStringLiteral( "0" ) ).toInt() ) );
147  r->setCircleWidth( symbologyElem.attribute( QStringLiteral( "circleWidth" ), QStringLiteral( "0.4" ) ).toDouble() );
148  r->setCircleColor( QgsSymbolLayerUtils::decodeColor( symbologyElem.attribute( QStringLiteral( "circleColor" ), QString() ) ) );
149  r->setLabelColor( QgsSymbolLayerUtils::decodeColor( symbologyElem.attribute( QStringLiteral( "labelColor" ), QString() ) ) );
150  r->setCircleRadiusAddition( symbologyElem.attribute( QStringLiteral( "circleRadiusAddition" ), QStringLiteral( "0.0" ) ).toDouble() );
151  r->setMinimumLabelScale( symbologyElem.attribute( QStringLiteral( "maxLabelScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble() );
152  r->setTolerance( symbologyElem.attribute( QStringLiteral( "tolerance" ), QStringLiteral( "0.00001" ) ).toDouble() );
153  r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( QStringLiteral( "toleranceUnit" ), QStringLiteral( "MapUnit" ) ) ) );
154  r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( QStringLiteral( "toleranceUnitScale" ) ) ) );
155 
156  //look for an embedded renderer <renderer-v2>
157  QDomElement embeddedRendererElem = symbologyElem.firstChildElement( QStringLiteral( "renderer-v2" ) );
158  if ( !embeddedRendererElem.isNull() )
159  {
160  r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
161  }
162 
163  //center symbol
164  QDomElement centerSymbolElem = symbologyElem.firstChildElement( QStringLiteral( "symbol" ) );
165  if ( !centerSymbolElem.isNull() )
166  {
167  r->setCenterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ) );
168  }
169  return r;
170 }
171 
173 {
174  return mCenterSymbol.get();
175 }
176 
177 QDomElement QgsPointDisplacementRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
178 {
179  QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
180  rendererElement.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
181  rendererElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "pointDisplacement" ) );
182  rendererElement.setAttribute( QStringLiteral( "labelAttributeName" ), mLabelAttributeName );
183  rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, QStringLiteral( "labelFontProperties" ) ) );
184  rendererElement.setAttribute( QStringLiteral( "circleWidth" ), QString::number( mCircleWidth ) );
185  rendererElement.setAttribute( QStringLiteral( "circleColor" ), QgsSymbolLayerUtils::encodeColor( mCircleColor ) );
186  rendererElement.setAttribute( QStringLiteral( "labelColor" ), QgsSymbolLayerUtils::encodeColor( mLabelColor ) );
187  rendererElement.setAttribute( QStringLiteral( "circleRadiusAddition" ), QString::number( mCircleRadiusAddition ) );
188  rendererElement.setAttribute( QStringLiteral( "placement" ), static_cast< int >( mPlacement ) );
189  rendererElement.setAttribute( QStringLiteral( "maxLabelScaleDenominator" ), QString::number( mMinLabelScale ) );
190  rendererElement.setAttribute( QStringLiteral( "tolerance" ), QString::number( mTolerance ) );
191  rendererElement.setAttribute( QStringLiteral( "toleranceUnit" ), QgsUnitTypes::encodeUnit( mToleranceUnit ) );
192  rendererElement.setAttribute( QStringLiteral( "toleranceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
193 
194  if ( mRenderer )
195  {
196  QDomElement embeddedRendererElem = mRenderer->save( doc, context );
197  rendererElement.appendChild( embeddedRendererElem );
198  }
199  if ( mCenterSymbol )
200  {
201  QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "centerSymbol" ), mCenterSymbol.get(), doc, context );
202  rendererElement.appendChild( centerSymbolElem );
203  }
204 
206  mPaintEffect->saveProperties( doc, rendererElement );
207 
208  if ( !mOrderBy.isEmpty() )
209  {
210  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
211  mOrderBy.save( orderBy );
212  rendererElement.appendChild( orderBy );
213  }
214  rendererElement.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
215 
216  return rendererElement;
217 }
218 
220 {
221  QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
222  if ( mCenterSymbol )
223  attr.unite( mCenterSymbol->usedAttributes( context ) );
224  return attr;
225 }
226 
228 {
229  mCenterSymbol.reset( symbol );
230 }
231 
232 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition,
233  double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, double &gridRadius,
234  int &gridSize ) const
235 {
236  symbolPositions.clear();
237  labelShifts.clear();
238 
239  if ( nPosition < 1 )
240  {
241  return;
242  }
243  else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
244  {
245  symbolPositions.append( centerPoint );
246  labelShifts.append( QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
247  return;
248  }
249 
250  double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition );
251 
252  switch ( mPlacement )
253  {
254  case Ring:
255  {
256  double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 * M_PI );
257  double radius = std::max( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
258 
259  double fullPerimeter = 2 * M_PI;
260  double angleStep = fullPerimeter / nPosition;
261  for ( double currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
262  {
263  double sinusCurrentAngle = std::sin( currentAngle );
264  double cosinusCurrentAngle = std::cos( currentAngle );
265  QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
266  QPointF labelShift( ( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
267  symbolPositions.append( centerPoint + positionShift );
268  labelShifts.append( labelShift );
269  }
270 
271  circleRadius = radius;
272  break;
273  }
274  case ConcentricRings:
275  {
276  double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
277 
278  int pointsRemaining = nPosition;
279  int ringNumber = 1;
280  double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
281  while ( pointsRemaining > 0 )
282  {
283  double radiusCurrentRing = std::max( firstRingRadius + ( ringNumber - 1 ) * symbolDiagonal + ringNumber * circleAdditionPainterUnits, 0.0 );
284  int maxPointsCurrentRing = std::max( std::floor( 2 * M_PI * radiusCurrentRing / symbolDiagonal ), 1.0 );
285  int actualPointsCurrentRing = std::min( maxPointsCurrentRing, pointsRemaining );
286 
287  double angleStep = 2 * M_PI / actualPointsCurrentRing;
288  double currentAngle = 0.0;
289  for ( int i = 0; i < actualPointsCurrentRing; ++i )
290  {
291  double sinusCurrentAngle = std::sin( currentAngle );
292  double cosinusCurrentAngle = std::cos( currentAngle );
293  QPointF positionShift( radiusCurrentRing * sinusCurrentAngle, radiusCurrentRing * cosinusCurrentAngle );
294  QPointF labelShift( ( radiusCurrentRing + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radiusCurrentRing + symbolDiagonal / 2 ) * cosinusCurrentAngle );
295  symbolPositions.append( centerPoint + positionShift );
296  labelShifts.append( labelShift );
297  currentAngle += angleStep;
298  }
299 
300  pointsRemaining -= actualPointsCurrentRing;
301  ringNumber++;
302  circleRadius = radiusCurrentRing;
303  }
304  break;
305  }
306  case Grid:
307  {
308  double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
309  int pointsRemaining = nPosition;
310  gridSize = std::ceil( std::sqrt( pointsRemaining ) );
311  if ( pointsRemaining - std::pow( gridSize - 1, 2 ) < gridSize )
312  gridSize -= 1;
313  double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
314  double userPointRadius = originalPointRadius + circleAdditionPainterUnits;
315 
316  int yIndex = 0;
317  while ( pointsRemaining > 0 )
318  {
319  for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
320  {
321  QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
322  QPointF labelShift( ( userPointRadius + symbolDiagonal / 2 ) * xIndex, ( userPointRadius + symbolDiagonal / 2 ) * yIndex );
323  symbolPositions.append( centerPoint + positionShift );
324  labelShifts.append( labelShift );
325  pointsRemaining--;
326  }
327  yIndex++;
328  }
329 
330  centralizeGrid( symbolPositions, userPointRadius, gridSize );
331  centralizeGrid( labelShifts, userPointRadius, gridSize );
332  gridRadius = userPointRadius;
333  break;
334  }
335  }
336 }
337 
338 void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
339 {
340  double shiftAmount = -radius * ( size - 1.0 ) / 2.0;
341  QPointF centralShift( shiftAmount, shiftAmount );
342  for ( int i = 0; i < pointSymbolPositions.size(); ++i )
343  {
344  pointSymbolPositions[i] += centralShift;
345  }
346 }
347 
348 void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
349  QList<QPointF> pointSymbolPositions, int nSymbols )
350 {
351  QPainter *p = context.renderContext().painter();
352  if ( nSymbols < 2 || !p ) //draw grid only if multiple features
353  {
354  return;
355  }
356 
357  QPen gridPen( mCircleColor );
358  gridPen.setWidthF( context.outputLineWidth( mCircleWidth ) );
359  p->setPen( gridPen );
360 
361  for ( int i = 0; i < pointSymbolPositions.size(); ++i )
362  {
363  if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
364  {
365  QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
366  p->drawLine( gridLineRow );
367  }
368 
369  if ( i + gridSizeUnits < pointSymbolPositions.size() )
370  {
371  QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
372  p->drawLine( gridLineColumn );
373  }
374  }
375 }
376 
377 void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols )
378 {
379  QPainter *p = context.renderContext().painter();
380  if ( nSymbols < 2 || !p ) //draw circle only if multiple features
381  {
382  return;
383  }
384 
385  //draw Circle
386  QPen circlePen( mCircleColor );
387  circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) );
388  p->setPen( circlePen );
389  p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
390 }
391 
392 void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions )
393 {
394  QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
395  ClusteredGroup::const_iterator groupIt = group.constBegin();
396  for ( ; symbolPosIt != symbolPositions.constEnd() && groupIt != group.constEnd();
397  ++symbolPosIt, ++groupIt )
398  {
399  context.expressionContext().setFeature( groupIt->feature );
400  groupIt->symbol()->startRender( context );
401  groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
402  groupIt->symbol()->stopRender( context );
403  }
404 }
405 
407 {
408  if ( renderer->type() == QLatin1String( "pointDisplacement" ) )
409  {
410  return dynamic_cast<QgsPointDisplacementRenderer *>( renderer->clone() );
411  }
412  else if ( renderer->type() == QLatin1String( "singleSymbol" ) ||
413  renderer->type() == QLatin1String( "categorizedSymbol" ) ||
414  renderer->type() == QLatin1String( "graduatedSymbol" ) ||
415  renderer->type() == QLatin1String( "RuleRenderer" ) )
416  {
418  pointRenderer->setEmbeddedRenderer( renderer->clone() );
419  return pointRenderer;
420  }
421  else if ( renderer->type() == QLatin1String( "pointCluster" ) )
422  {
424  const QgsPointClusterRenderer *clusterRenderer = static_cast< const QgsPointClusterRenderer * >( renderer );
425  if ( clusterRenderer->embeddedRenderer() )
426  pointRenderer->setEmbeddedRenderer( clusterRenderer->embeddedRenderer()->clone() );
427  pointRenderer->setTolerance( clusterRenderer->tolerance() );
428  pointRenderer->setToleranceUnit( clusterRenderer->toleranceUnit() );
429  pointRenderer->setToleranceMapUnitScale( clusterRenderer->toleranceMapUnitScale() );
430  if ( const_cast< QgsPointClusterRenderer * >( clusterRenderer )->clusterSymbol() )
431  pointRenderer->setCenterSymbol( const_cast< QgsPointClusterRenderer * >( clusterRenderer )->clusterSymbol()->clone() );
432  return pointRenderer;
433  }
434  else
435  {
436  return nullptr;
437  }
438 }
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...
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
QString type() const
Definition: qgsrenderer.h:129
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
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:521
const QgsMapUnitScale & toleranceMapUnitScale() const
Returns the map unit scale object for the distance tolerance.
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.
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.
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
double outputLineWidth(double width) const
Definition: qgssymbol.cpp:1096
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:505
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
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.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:732
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.
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.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:572
QgsMapUnitScale mToleranceMapUnitScale
Map unit scale for distance tolerance.
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
QFont labelFont() const
Returns the font used for labeling points.
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. ...
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Contains information about the context of a rendering operation.
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 copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:48
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
QList< QgsPointDistanceRenderer::GroupedFeature > ClusteredGroup
A group of clustered points (ie features within the distance tolerance).
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
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()...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns 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.
double tolerance() const
Returns the tolerance distance for grouping points.
static QColor decodeColor(const QString &str)
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.