QGIS API Documentation  3.0.2-Girona (307d082)
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:1060
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
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.
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:453
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 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()...
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)
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.