QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 }
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:529
QString type() const
Definition: qgsrenderer.h:141
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:50
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
QgsFeatureRequest::OrderBy mOrderBy
Definition: qgsrenderer.h:545
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
Container of fields for a vector layer.
Definition: qgsfields.h:45
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.
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:1004
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:2036
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
A renderer that automatically clusters points with the same geographic position.
QgsMarkerSymbol * clusterSymbol()
Returns the symbol used for rendering clustered groups (but not ownership of the symbol).
A renderer that automatically displaces points with the same geographic location.
QgsPointDisplacementRenderer(const QString &labelAttributeName=QString())
Constructor for QgsPointDisplacementRenderer.
void setPlacement(Placement placement)
Sets the placement method used for dispersing the points.
void setLabelDistanceFactor(double factor)
Sets a factor for increasing the label distances from the symbol.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
QgsPointDisplacementRenderer * clone() const override
Create a deep copy of this renderer.
void setCircleColor(const QColor &color)
Sets the color used for drawing the displacement group circle.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
static QgsFeatureRenderer * create(QDomElement &symbologyElem, const QgsReadWriteContext &context)
Create a renderer from XML element.
void setCenterSymbol(QgsMarkerSymbol *symbol)
Sets the center symbol for a displacement group.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
Placement
Placement methods for dispersing points.
@ ConcentricRings
Place points in concentric rings around group.
@ Ring
Place points in a single ring around group.
@ Grid
Place points in a grid around group.
void setCircleRadiusAddition(double distance)
Sets a factor for increasing the ring size of displacement groups.
QgsMarkerSymbol * centerSymbol()
Returns the symbol for the center of a displacement group (but not ownership of the symbol).
void setCircleWidth(double width)
Sets the line width for the displacement group circle.
static QgsPointDisplacementRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointDisplacementRenderer from an existing renderer.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
void setLabelColor(const QColor &color)
Sets the color to use for for labeling points.
double mMinLabelScale
Maximum scale denominator for label display. A zero value indicates no scale limitation.
int mLabelIndex
Label attribute index (or -1 if none). This index is not stored, it is requested in the startRender()...
QColor mLabelColor
Label text color.
QgsMapUnitScale mToleranceMapUnitScale
Map unit scale for distance tolerance.
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
void setLabelFont(const QFont &font)
Sets the font used for labeling points.
void setMinimumLabelScale(double scale)
Sets the minimum map scale (i.e.
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
double tolerance() const
Returns the tolerance distance for grouping points.
QFont labelFont() const
Returns the font used for labeling points.
const QgsMapUnitScale & toleranceMapUnitScale() const
Returns the map unit scale object for the distance tolerance.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
void setEmbeddedRenderer(QgsFeatureRenderer *r) override
Sets an embedded renderer (subrenderer) for this feature renderer.
void setToleranceUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the tolerance distance.
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
QString mLabelAttributeName
Attribute name for labeling. An empty string indicates that no labels should be rendered.
void drawLabels(QPointF centerPoint, QgsSymbolRenderContext &context, const QList< QPointF > &labelShifts, const ClusteredGroup &group)
Renders the labels for a group.
void setLabelAttributeName(const QString &name)
Sets the attribute name for labeling points.
double mTolerance
Distance tolerance. Points that are closer together than this distance are considered clustered.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
std::unique_ptr< QgsFeatureRenderer > mRenderer
Embedded base renderer. This can be used for rendering individual, isolated points.
QgsUnitTypes::RenderUnit mToleranceUnit
Unit for distance tolerance.
void setToleranceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the distance tolerance.
void setTolerance(double distance)
Sets the tolerance distance for grouping points.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
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:42
Contains information about the context of a rendering operation.
bool hasRenderedFeatureHandlers() const
Returns true if the context has any rendered feature handlers.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
QList< QgsRenderedFeatureHandlerInterface * > renderedFeatureHandlers() const
Returns the list of rendered feature handlers to use while rendering map layers.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
An interface for classes which provider custom handlers for features rendered as part of a map render...
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1201
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QColor decodeColor(const QString &str)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QString encodeColor(const QColor &color)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbol.h:794
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:51
Contains information relating to the style entity currently being visited.