QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 #include "qgsstyleentityvisitor.h"
26 
27 #include <QPainter>
28 #include <cmath>
29 
31  : QgsPointDistanceRenderer( QStringLiteral( "pointDisplacement" ), labelAttributeName )
32  , mCircleColor( QColor( 125, 125, 125 ) )
33 {
34  mCenterSymbol.reset( new QgsMarkerSymbol() );
35 }
36 
38 {
40  if ( mRenderer )
41  r->setEmbeddedRenderer( mRenderer->clone() );
42  r->setCircleWidth( mCircleWidth );
43  r->setCircleColor( mCircleColor );
46  r->setPlacement( mPlacement );
47  r->setCircleRadiusAddition( mCircleRadiusAddition );
48  r->setLabelDistanceFactor( mLabelDistanceFactor );
53  if ( mCenterSymbol )
54  {
55  r->setCenterSymbol( mCenterSymbol->clone() );
56  }
57  copyRendererData( r );
58  return r;
59 }
60 
61 void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group )
62 {
63 
64  //calculate max diagonal size from all symbols in group
65  double diagonal = 0;
66  QVector<double> diagonals( group.size() );
67  double currentDiagonal;
68 
69  int groupPosition = 0;
70  for ( const GroupedFeature &feature : group )
71  {
72  if ( QgsMarkerSymbol *symbol = feature.symbol() )
73  {
74  currentDiagonal = M_SQRT2 * symbol->size( context );
75  diagonals[groupPosition] = currentDiagonal;
76  diagonal = std::max( diagonal, currentDiagonal );
77 
78  }
79  else
80  {
81  diagonals[groupPosition] = 0.0;
82  }
83  groupPosition++;
84  }
85 
86  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false );
87 
88  QList<QPointF> symbolPositions;
89  QList<QPointF> labelPositions;
90  double circleRadius = -1.0;
91  double gridRadius = -1.0;
92  int gridSize = -1;
93 
94  calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize, diagonals );
95 
96  //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids
97  if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 )
98  {
99  //draw circle
100  if ( circleRadius > 0 )
101  drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
102  //draw grid
103  else
104  drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
105  }
106 
107  if ( group.size() > 1 )
108  {
109  //draw mid point
110  QgsFeature firstFeature = group.at( 0 ).feature;
111  if ( mCenterSymbol )
112  {
113  mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
114  }
115  else
116  {
117  const double rectSize = symbolContext.renderContext().convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters );
118  context.painter()->drawRect( QRectF( centerPoint.x() - rectSize, centerPoint.y() - rectSize, rectSize * 2, rectSize * 2 ) );
119  }
120  }
121 
122  //draw symbols on the circle
123  drawSymbols( group, context, symbolPositions );
124  //and also the labels
125  if ( mLabelIndex >= 0 )
126  {
127  drawLabels( centerPoint, symbolContext, labelPositions, group );
128  }
129 }
130 
131 
133 {
134  if ( mCenterSymbol )
135  {
136  mCenterSymbol->startRender( context, fields );
137  }
138 
139  QgsPointDistanceRenderer::startRender( context, fields );
140 }
141 
143 {
145  if ( mCenterSymbol )
146  {
147  mCenterSymbol->stopRender( context );
148  }
149 }
150 
152 {
154  r->setLabelAttributeName( symbologyElem.attribute( QStringLiteral( "labelAttributeName" ) ) );
155  QFont labelFont;
156  if ( !QgsFontUtils::setFromXmlChildNode( labelFont, symbologyElem, QStringLiteral( "labelFontProperties" ) ) )
157  {
158  labelFont.fromString( symbologyElem.attribute( QStringLiteral( "labelFont" ), QString() ) );
159  }
160  r->setLabelFont( labelFont );
161  r->setPlacement( static_cast< Placement >( symbologyElem.attribute( QStringLiteral( "placement" ), QStringLiteral( "0" ) ).toInt() ) );
162  r->setCircleWidth( symbologyElem.attribute( QStringLiteral( "circleWidth" ), QStringLiteral( "0.4" ) ).toDouble() );
163  r->setCircleColor( QgsSymbolLayerUtils::decodeColor( symbologyElem.attribute( QStringLiteral( "circleColor" ), QString() ) ) );
164  r->setLabelColor( QgsSymbolLayerUtils::decodeColor( symbologyElem.attribute( QStringLiteral( "labelColor" ), QString() ) ) );
165  r->setCircleRadiusAddition( symbologyElem.attribute( QStringLiteral( "circleRadiusAddition" ), QStringLiteral( "0.0" ) ).toDouble() );
166  r->setLabelDistanceFactor( symbologyElem.attribute( QStringLiteral( "labelDistanceFactor" ), QStringLiteral( "0.5" ) ).toDouble() );
167  r->setMinimumLabelScale( symbologyElem.attribute( QStringLiteral( "maxLabelScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble() );
168  r->setTolerance( symbologyElem.attribute( QStringLiteral( "tolerance" ), QStringLiteral( "0.00001" ) ).toDouble() );
169  r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( QStringLiteral( "toleranceUnit" ), QStringLiteral( "MapUnit" ) ) ) );
170  r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( QStringLiteral( "toleranceUnitScale" ) ) ) );
171 
172  //look for an embedded renderer <renderer-v2>
173  QDomElement embeddedRendererElem = symbologyElem.firstChildElement( QStringLiteral( "renderer-v2" ) );
174  if ( !embeddedRendererElem.isNull() )
175  {
176  r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
177  }
178 
179  //center symbol
180  QDomElement centerSymbolElem = symbologyElem.firstChildElement( QStringLiteral( "symbol" ) );
181  if ( !centerSymbolElem.isNull() )
182  {
183  r->setCenterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ) );
184  }
185  return r;
186 }
187 
189 {
190  return mCenterSymbol.get();
191 }
192 
193 QDomElement QgsPointDisplacementRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
194 {
195  QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
196  rendererElement.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
197  rendererElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "pointDisplacement" ) );
198  rendererElement.setAttribute( QStringLiteral( "labelAttributeName" ), mLabelAttributeName );
199  rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, QStringLiteral( "labelFontProperties" ) ) );
200  rendererElement.setAttribute( QStringLiteral( "circleWidth" ), QString::number( mCircleWidth ) );
201  rendererElement.setAttribute( QStringLiteral( "circleColor" ), QgsSymbolLayerUtils::encodeColor( mCircleColor ) );
202  rendererElement.setAttribute( QStringLiteral( "labelColor" ), QgsSymbolLayerUtils::encodeColor( mLabelColor ) );
203  rendererElement.setAttribute( QStringLiteral( "circleRadiusAddition" ), QString::number( mCircleRadiusAddition ) );
204  rendererElement.setAttribute( QStringLiteral( "labelDistanceFactor" ), QString::number( mLabelDistanceFactor ) );
205  rendererElement.setAttribute( QStringLiteral( "placement" ), static_cast< int >( mPlacement ) );
206  rendererElement.setAttribute( QStringLiteral( "maxLabelScaleDenominator" ), QString::number( mMinLabelScale ) );
207  rendererElement.setAttribute( QStringLiteral( "tolerance" ), QString::number( mTolerance ) );
208  rendererElement.setAttribute( QStringLiteral( "toleranceUnit" ), QgsUnitTypes::encodeUnit( mToleranceUnit ) );
209  rendererElement.setAttribute( QStringLiteral( "toleranceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
210 
211  if ( mRenderer )
212  {
213  QDomElement embeddedRendererElem = mRenderer->save( doc, context );
214  rendererElement.appendChild( embeddedRendererElem );
215  }
216  if ( mCenterSymbol )
217  {
218  QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "centerSymbol" ), mCenterSymbol.get(), doc, context );
219  rendererElement.appendChild( centerSymbolElem );
220  }
221 
223  mPaintEffect->saveProperties( doc, rendererElement );
224 
225  if ( !mOrderBy.isEmpty() )
226  {
227  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
228  mOrderBy.save( orderBy );
229  rendererElement.appendChild( orderBy );
230  }
231  rendererElement.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
232 
233  return rendererElement;
234 }
235 
237 {
238  QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
239  if ( mCenterSymbol )
240  attr.unite( mCenterSymbol->usedAttributes( context ) );
241  return attr;
242 }
243 
245 {
246  if ( !QgsPointDistanceRenderer::accept( visitor ) )
247  return false;
248 
249  if ( mCenterSymbol )
250  {
251  QgsStyleSymbolEntity entity( mCenterSymbol.get() );
252  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "center" ), QObject::tr( "Center Symbol" ) ) ) )
253  return false;
254  }
255 
256  return true;
257 }
258 
260 {
261  mCenterSymbol.reset( symbol );
262 }
263 
264 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition,
265  double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, double &gridRadius,
266  int &gridSize, QVector<double> &diagonals ) const
267 {
268  symbolPositions.clear();
269  labelShifts.clear();
270 
271  if ( nPosition < 1 )
272  {
273  return;
274  }
275  else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
276  {
277  const double side = std::sqrt( std::pow( symbolDiagonal, 2 ) / 2.0 );
278  symbolPositions.append( centerPoint );
279  labelShifts.append( QPointF( side * mLabelDistanceFactor, -side * mLabelDistanceFactor ) );
280  return;
281  }
282 
283  double circleAdditionPainterUnits = symbolContext.renderContext().convertToPainterUnits( mCircleRadiusAddition, QgsUnitTypes::RenderMillimeters );
284 
285  switch ( mPlacement )
286  {
287  case Ring:
288  {
289  const double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 * M_PI );
290  const double radius = std::max( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
291 
292  const double angleStep = 2 * M_PI / nPosition;
293  double currentAngle = 0.0;
294  for ( int featureIndex = 0; featureIndex < nPosition; currentAngle += angleStep, featureIndex++ )
295  {
296  const double sinusCurrentAngle = std::sin( currentAngle );
297  const double cosinusCurrentAngle = std::cos( currentAngle );
298  const QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
299 
300  const QPointF labelShift( ( radius + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * sinusCurrentAngle, ( radius + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * cosinusCurrentAngle );
301  symbolPositions.append( centerPoint + positionShift );
302  labelShifts.append( labelShift );
303  }
304  circleRadius = radius;
305  break;
306  }
307  case ConcentricRings:
308  {
309  double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
310 
311  int pointsRemaining = nPosition;
312  int ringNumber = 1;
313  double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
314  int featureIndex = 0;
315  while ( pointsRemaining > 0 )
316  {
317  double radiusCurrentRing = std::max( firstRingRadius + ( ringNumber - 1 ) * symbolDiagonal + ringNumber * circleAdditionPainterUnits, 0.0 );
318  int maxPointsCurrentRing = std::max( std::floor( 2 * M_PI * radiusCurrentRing / symbolDiagonal ), 1.0 );
319  int actualPointsCurrentRing = std::min( maxPointsCurrentRing, pointsRemaining );
320 
321  double angleStep = 2 * M_PI / actualPointsCurrentRing;
322  double currentAngle = 0.0;
323  for ( int i = 0; i < actualPointsCurrentRing; ++i )
324  {
325  double sinusCurrentAngle = std::sin( currentAngle );
326  double cosinusCurrentAngle = std::cos( currentAngle );
327  QPointF positionShift( radiusCurrentRing * sinusCurrentAngle, radiusCurrentRing * cosinusCurrentAngle );
328  QPointF labelShift( ( radiusCurrentRing + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * sinusCurrentAngle, ( radiusCurrentRing + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * cosinusCurrentAngle );
329  symbolPositions.append( centerPoint + positionShift );
330  labelShifts.append( labelShift );
331  currentAngle += angleStep;
332  featureIndex++;
333  }
334 
335  pointsRemaining -= actualPointsCurrentRing;
336  ringNumber++;
337  circleRadius = radiusCurrentRing;
338  }
339  break;
340  }
341  case Grid:
342  {
343  double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
344  int pointsRemaining = nPosition;
345  gridSize = std::ceil( std::sqrt( pointsRemaining ) );
346  if ( pointsRemaining - std::pow( gridSize - 1, 2 ) < gridSize )
347  gridSize -= 1;
348  double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
349  double userPointRadius = originalPointRadius + circleAdditionPainterUnits;
350 
351  int yIndex = 0;
352  while ( pointsRemaining > 0 )
353  {
354  for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
355  {
356  QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
357  symbolPositions.append( centerPoint + positionShift );
358  pointsRemaining--;
359  }
360  yIndex++;
361  }
362 
363  centralizeGrid( symbolPositions, userPointRadius, gridSize );
364 
365  int xFactor;
366  int yFactor;
367  double side = 0;
368  for ( int symbolIndex = 0; symbolIndex < symbolPositions.size(); ++symbolIndex )
369  {
370  if ( symbolPositions.at( symbolIndex ).x() < centerPoint.x() )
371  {
372  xFactor = -1;
373  }
374  else
375  {
376  xFactor = 1;
377  }
378 
379  if ( symbolPositions.at( symbolIndex ).y() < centerPoint.y() )
380  {
381  yFactor = 1;
382  }
383  else
384  {
385  yFactor = -1;
386  }
387 
388  side = std::sqrt( std::pow( diagonals.at( symbolIndex ), 2 ) / 2.0 );
389  QPointF labelShift( ( side * mLabelDistanceFactor * xFactor ), ( -side * mLabelDistanceFactor * yFactor ) );
390  labelShifts.append( symbolPositions.at( symbolIndex ) - centerPoint + labelShift );
391  }
392 
393  gridRadius = userPointRadius;
394  break;
395  }
396  }
397 }
398 
399 void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
400 {
401  double shiftAmount = -radius * ( size - 1.0 ) / 2.0;
402  QPointF centralShift( shiftAmount, shiftAmount );
403  for ( int i = 0; i < pointSymbolPositions.size(); ++i )
404  {
405  pointSymbolPositions[i] += centralShift;
406  }
407 }
408 
409 void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
410  QList<QPointF> pointSymbolPositions, int nSymbols )
411 {
412  QPainter *p = context.renderContext().painter();
413  if ( nSymbols < 2 || !p ) //draw grid only if multiple features
414  {
415  return;
416  }
417 
418  QPen gridPen( mCircleColor );
419  gridPen.setWidthF( context.renderContext().convertToPainterUnits( mCircleWidth, QgsUnitTypes::RenderMillimeters ) );
420  p->setPen( gridPen );
421 
422  for ( int i = 0; i < pointSymbolPositions.size(); ++i )
423  {
424  if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
425  {
426  QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
427  p->drawLine( gridLineRow );
428  }
429 
430  if ( i + gridSizeUnits < pointSymbolPositions.size() )
431  {
432  QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
433  p->drawLine( gridLineColumn );
434  }
435  }
436 }
437 
438 void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols )
439 {
440  QPainter *p = context.renderContext().painter();
441  if ( nSymbols < 2 || !p ) //draw circle only if multiple features
442  {
443  return;
444  }
445 
446  //draw Circle
447  QPen circlePen( mCircleColor );
448  circlePen.setWidthF( context.renderContext().convertToPainterUnits( mCircleWidth, QgsUnitTypes::RenderMillimeters ) );
449  p->setPen( circlePen );
450  p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
451 }
452 
453 void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions )
454 {
455  QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
456  ClusteredGroup::const_iterator groupIt = group.constBegin();
457  for ( ; symbolPosIt != symbolPositions.constEnd() && groupIt != group.constEnd();
458  ++symbolPosIt, ++groupIt )
459  {
460  context.expressionContext().setFeature( groupIt->feature );
461  groupIt->symbol()->startRender( context );
462  groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
463  if ( context.hasRenderedFeatureHandlers() )
464  {
465  const QgsGeometry bounds( QgsGeometry::fromRect( QgsRectangle( groupIt->symbol()->bounds( *symbolPosIt, context, groupIt->feature ) ) ) );
466  const QList< QgsRenderedFeatureHandlerInterface * > handlers = context.renderedFeatureHandlers();
468  for ( QgsRenderedFeatureHandlerInterface *handler : handlers )
469  handler->handleRenderedFeature( groupIt->feature, bounds, featureContext );
470  }
471  groupIt->symbol()->stopRender( context );
472  }
473 }
474 
476 {
477  if ( renderer->type() == QLatin1String( "pointDisplacement" ) )
478  {
479  return dynamic_cast<QgsPointDisplacementRenderer *>( renderer->clone() );
480  }
481  else if ( renderer->type() == QLatin1String( "singleSymbol" ) ||
482  renderer->type() == QLatin1String( "categorizedSymbol" ) ||
483  renderer->type() == QLatin1String( "graduatedSymbol" ) ||
484  renderer->type() == QLatin1String( "RuleRenderer" ) )
485  {
487  pointRenderer->setEmbeddedRenderer( renderer->clone() );
488  return pointRenderer;
489  }
490  else if ( renderer->type() == QLatin1String( "pointCluster" ) )
491  {
493  const QgsPointClusterRenderer *clusterRenderer = static_cast< const QgsPointClusterRenderer * >( renderer );
494  if ( clusterRenderer->embeddedRenderer() )
495  pointRenderer->setEmbeddedRenderer( clusterRenderer->embeddedRenderer()->clone() );
496  pointRenderer->setTolerance( clusterRenderer->tolerance() );
497  pointRenderer->setToleranceUnit( clusterRenderer->toleranceUnit() );
498  pointRenderer->setToleranceMapUnitScale( clusterRenderer->toleranceMapUnitScale() );
499  if ( const_cast< QgsPointClusterRenderer * >( clusterRenderer )->clusterSymbol() )
500  pointRenderer->setCenterSymbol( const_cast< QgsPointClusterRenderer * >( clusterRenderer )->clusterSymbol()->clone() );
501  return pointRenderer;
502  }
503  else
504  {
505  return nullptr;
506  }
507 }
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...
A rectangle specified with double values.
Definition: qgsrectangle.h:41
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.
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:971
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:533
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
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.
QList< QgsRenderedFeatureHandlerInterface * > renderedFeatureHandlers() const
Returns the list of rendered feature handlers to use while rendering map layers.
QgsFeatureRequest::OrderBy orderBy() const
Gets 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.
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.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:517
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
An interface for classes which can visit style entity (e.g.
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.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:860
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
bool hasRenderedFeatureHandlers() const
Returns true if the context has any rendered feature handlers.
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.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QFont labelFont() const
Returns the font used for labeling points.
QString type() const
Definition: qgsrenderer.h:130
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.
An interface for classes which provider custom handlers for features rendered as part of a map render...
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.
void setLabelDistanceFactor(double factor)
Sets a factor for increasing the label distances from the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:668
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. ...
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.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
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.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:49
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
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.
Contains information relating to the style entity currently being visited.
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
Returns 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.