QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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
20#include <cmath>
21#include <memory>
22
23#include "qgscolorutils.h"
24#include "qgsfontutils.h"
25#include "qgsmarkersymbol.h"
29#include "qgssymbollayerutils.h"
30#include "qgsunittypes.h"
31
32#include <QPainter>
33#include <QString>
34
35using namespace Qt::StringLiterals;
36
38 : QgsPointDistanceRenderer( u"pointDisplacement"_s, labelAttributeName )
39 , mCircleColor( QColor( 125, 125, 125 ) )
40{
41 mCenterSymbol = std::make_unique<QgsMarkerSymbol>( );
42}
43
45{
47 if ( mCenterSymbol && mCenterSymbol->flags().testFlag( Qgis::SymbolFlag::AffectsLabeling ) )
51 return res;
52}
53
55{
57 if ( mRenderer )
58 r->setEmbeddedRenderer( mRenderer->clone() );
59 r->setCircleWidth( mCircleWidth );
60 r->setCircleColor( mCircleColor );
63 r->setPlacement( mPlacement );
64 r->setCircleRadiusAddition( mCircleRadiusAddition );
65 r->setLabelDistanceFactor( mLabelDistanceFactor );
70 if ( mCenterSymbol )
71 {
72 r->setCenterSymbol( mCenterSymbol->clone() );
73 }
75 return r;
76}
77
78void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group ) const
79{
80
81 //calculate max diagonal size from all symbols in group
82 double diagonal = 0;
83 QVector<double> diagonals( group.size() );
84 double currentDiagonal;
85
86 int groupPosition = 0;
87 for ( const GroupedFeature &feature : group )
88 {
89 if ( QgsMarkerSymbol *symbol = feature.symbol() )
90 {
91 currentDiagonal = M_SQRT2 * symbol->size( context );
92 diagonals[groupPosition] = currentDiagonal;
93 diagonal = std::max( diagonal, currentDiagonal );
94
95 }
96 else
97 {
98 diagonals[groupPosition] = 0.0;
99 }
100 groupPosition++;
101 }
102
103 QgsSymbolRenderContext symbolContext( context, Qgis::RenderUnit::Millimeters, 1.0, false );
104
105 QList<QPointF> symbolPositions;
106 QList<QPointF> labelPositions;
107 double circleRadius = -1.0;
108 double gridRadius = -1.0;
109 int gridSize = -1;
110
111 calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize, diagonals );
112
113 //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids
114 if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 )
115 {
116 switch ( mPlacement )
117 {
118 case Ring:
119 case ConcentricRings:
120 drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
121 break;
122 case Grid:
123 drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
124 break;
125 }
126 }
127
128 if ( group.size() > 1 )
129 {
130 //draw mid point
131 const QgsFeature firstFeature = group.at( 0 ).feature;
132 if ( mCenterSymbol )
133 {
134 mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
135 }
136 else
137 {
138 const double rectSize = symbolContext.renderContext().convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
139 context.painter()->drawRect( QRectF( centerPoint.x() - rectSize, centerPoint.y() - rectSize, rectSize * 2, rectSize * 2 ) );
140 }
141 }
142
143 //draw symbols on the circle
144 drawSymbols( group, context, symbolPositions );
145 //and also the labels
146 if ( mLabelIndex >= 0 )
147 {
148 drawLabels( centerPoint, symbolContext, labelPositions, group );
149 }
150}
151
152
154{
155 if ( mCenterSymbol )
156 {
157 mCenterSymbol->startRender( context, fields );
158 }
159
160 QgsPointDistanceRenderer::startRender( context, fields );
161}
162
164{
166 if ( mCenterSymbol )
167 {
168 mCenterSymbol->stopRender( context );
169 }
170}
171
173{
175 r->setLabelAttributeName( symbologyElem.attribute( u"labelAttributeName"_s ) );
176 QFont labelFont;
177 if ( !QgsFontUtils::setFromXmlChildNode( labelFont, symbologyElem, u"labelFontProperties"_s ) )
178 {
179 labelFont.fromString( symbologyElem.attribute( u"labelFont"_s, QString() ) );
180 }
182 r->setPlacement( static_cast< Placement >( symbologyElem.attribute( u"placement"_s, u"0"_s ).toInt() ) );
183 r->setCircleWidth( symbologyElem.attribute( u"circleWidth"_s, u"0.4"_s ).toDouble() );
184 r->setCircleColor( QgsColorUtils::colorFromString( symbologyElem.attribute( u"circleColor"_s, QString() ) ) );
185 r->setLabelColor( QgsColorUtils::colorFromString( symbologyElem.attribute( u"labelColor"_s, QString() ) ) );
186 r->setCircleRadiusAddition( symbologyElem.attribute( u"circleRadiusAddition"_s, u"0.0"_s ).toDouble() );
187 r->setLabelDistanceFactor( symbologyElem.attribute( u"labelDistanceFactor"_s, u"0.5"_s ).toDouble() );
188 r->setMinimumLabelScale( symbologyElem.attribute( u"maxLabelScaleDenominator"_s, u"-1"_s ).toDouble() );
189 r->setTolerance( symbologyElem.attribute( u"tolerance"_s, u"0.00001"_s ).toDouble() );
190 r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( u"toleranceUnit"_s, u"MapUnit"_s ) ) );
191 r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( u"toleranceUnitScale"_s ) ) );
192
193 //look for an embedded renderer <renderer-v2>
194 QDomElement embeddedRendererElem = symbologyElem.firstChildElement( u"renderer-v2"_s );
195 if ( !embeddedRendererElem.isNull() )
196 {
197 r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
198 }
199
200 //center symbol
201 const QDomElement centerSymbolElem = symbologyElem.firstChildElement( u"symbol"_s );
202 if ( !centerSymbolElem.isNull() )
203 {
204 r->setCenterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ).release() );
205 }
206 return r;
207}
208
210{
211 return mCenterSymbol.get();
212}
213
214QDomElement QgsPointDisplacementRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
215{
216 QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
217 rendererElement.setAttribute( u"type"_s, u"pointDisplacement"_s );
218 rendererElement.setAttribute( u"labelAttributeName"_s, mLabelAttributeName );
219 rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, u"labelFontProperties"_s ) );
220 rendererElement.setAttribute( u"circleWidth"_s, QString::number( mCircleWidth ) );
221 rendererElement.setAttribute( u"circleColor"_s, QgsColorUtils::colorToString( mCircleColor ) );
222 rendererElement.setAttribute( u"labelColor"_s, QgsColorUtils::colorToString( mLabelColor ) );
223 rendererElement.setAttribute( u"circleRadiusAddition"_s, QString::number( mCircleRadiusAddition ) );
224 rendererElement.setAttribute( u"labelDistanceFactor"_s, QString::number( mLabelDistanceFactor ) );
225 rendererElement.setAttribute( u"placement"_s, static_cast< int >( mPlacement ) );
226 rendererElement.setAttribute( u"maxLabelScaleDenominator"_s, QString::number( mMinLabelScale ) );
227 rendererElement.setAttribute( u"tolerance"_s, QString::number( mTolerance ) );
228 rendererElement.setAttribute( u"toleranceUnit"_s, QgsUnitTypes::encodeUnit( mToleranceUnit ) );
229 rendererElement.setAttribute( u"toleranceUnitScale"_s, QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
230
231 if ( mRenderer )
232 {
233 const QDomElement embeddedRendererElem = mRenderer->save( doc, context );
234 rendererElement.appendChild( embeddedRendererElem );
235 }
236 if ( mCenterSymbol )
237 {
238 const QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( u"centerSymbol"_s, mCenterSymbol.get(), doc, context );
239 rendererElement.appendChild( centerSymbolElem );
240 }
241
242 saveRendererData( doc, rendererElement, context );
243
244 return rendererElement;
245}
246
248{
249 QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
250 if ( mCenterSymbol )
251 attr.unite( mCenterSymbol->usedAttributes( context ) );
252 return attr;
253}
254
256{
257 if ( !QgsPointDistanceRenderer::accept( visitor ) )
258 return false;
259
260 if ( mCenterSymbol )
261 {
262 QgsStyleSymbolEntity entity( mCenterSymbol.get() );
263 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, u"center"_s, QObject::tr( "Center Symbol" ) ) ) )
264 return false;
265 }
266
267 return true;
268}
269
271{
272 mCenterSymbol.reset( symbol );
273}
274
275void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition,
276 double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, double &gridRadius,
277 int &gridSize, QVector<double> &diagonals ) const
278{
279 symbolPositions.clear();
280 labelShifts.clear();
281
282 if ( nPosition < 1 )
283 {
284 return;
285 }
286 else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
287 {
288 const double side = std::sqrt( std::pow( symbolDiagonal, 2 ) / 2.0 );
289 symbolPositions.append( centerPoint );
290 labelShifts.append( QPointF( side * mLabelDistanceFactor, -side * mLabelDistanceFactor ) );
291 return;
292 }
293
294 const double circleAdditionPainterUnits = symbolContext.renderContext().convertToPainterUnits( mCircleRadiusAddition, Qgis::RenderUnit::Millimeters );
295
296 switch ( mPlacement )
297 {
298 case Ring:
299 {
300 const double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 * M_PI );
301 const double radius = std::max( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
302
303 const double angleStep = 2 * M_PI / nPosition;
304 double currentAngle = 0.0;
305 for ( int featureIndex = 0; featureIndex < nPosition; currentAngle += angleStep, featureIndex++ )
306 {
307 const double sinusCurrentAngle = std::sin( currentAngle );
308 const double cosinusCurrentAngle = std::cos( currentAngle );
309 const QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
310
311 const QPointF labelShift( ( radius + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * sinusCurrentAngle, ( radius + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * cosinusCurrentAngle );
312 symbolPositions.append( centerPoint + positionShift );
313 labelShifts.append( labelShift );
314 }
315 circleRadius = radius;
316 break;
317 }
318 case ConcentricRings:
319 {
320 const double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
321
322 int pointsRemaining = nPosition;
323 int ringNumber = 1;
324 const double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
325 int featureIndex = 0;
326 while ( pointsRemaining > 0 )
327 {
328 const double radiusCurrentRing = std::max( firstRingRadius + ( ringNumber - 1 ) * symbolDiagonal + ringNumber * circleAdditionPainterUnits, 0.0 );
329 const int maxPointsCurrentRing = std::max( std::floor( 2 * M_PI * radiusCurrentRing / symbolDiagonal ), 1.0 );
330 const int actualPointsCurrentRing = std::min( maxPointsCurrentRing, pointsRemaining );
331
332 const double angleStep = 2 * M_PI / actualPointsCurrentRing;
333 double currentAngle = 0.0;
334 for ( int i = 0; i < actualPointsCurrentRing; ++i )
335 {
336 const double sinusCurrentAngle = std::sin( currentAngle );
337 const double cosinusCurrentAngle = std::cos( currentAngle );
338 const QPointF positionShift( radiusCurrentRing * sinusCurrentAngle, radiusCurrentRing * cosinusCurrentAngle );
339 const QPointF labelShift( ( radiusCurrentRing + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * sinusCurrentAngle, ( radiusCurrentRing + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * cosinusCurrentAngle );
340 symbolPositions.append( centerPoint + positionShift );
341 labelShifts.append( labelShift );
342 currentAngle += angleStep;
343 featureIndex++;
344 }
345
346 pointsRemaining -= actualPointsCurrentRing;
347 ringNumber++;
348 circleRadius = radiusCurrentRing;
349 }
350 break;
351 }
352 case Grid:
353 {
354 const double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
355 int pointsRemaining = nPosition;
356 gridSize = std::ceil( std::sqrt( pointsRemaining ) );
357 if ( pointsRemaining - std::pow( gridSize - 1, 2 ) < gridSize )
358 gridSize -= 1;
359 const double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
360 const double userPointRadius = originalPointRadius + circleAdditionPainterUnits;
361
362 int yIndex = 0;
363 while ( pointsRemaining > 0 )
364 {
365 for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
366 {
367 const QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
368 symbolPositions.append( centerPoint + positionShift );
369 pointsRemaining--;
370 }
371 yIndex++;
372 }
373
374 centralizeGrid( symbolPositions, userPointRadius, gridSize );
375
376 int xFactor;
377 int yFactor;
378 double side = 0;
379 for ( int symbolIndex = 0; symbolIndex < symbolPositions.size(); ++symbolIndex )
380 {
381 if ( symbolPositions.at( symbolIndex ).x() < centerPoint.x() )
382 {
383 xFactor = -1;
384 }
385 else
386 {
387 xFactor = 1;
388 }
389
390 if ( symbolPositions.at( symbolIndex ).y() < centerPoint.y() )
391 {
392 yFactor = 1;
393 }
394 else
395 {
396 yFactor = -1;
397 }
398
399 side = std::sqrt( std::pow( diagonals.at( symbolIndex ), 2 ) / 2.0 );
400 const QPointF labelShift( ( side * mLabelDistanceFactor * xFactor ), ( -side * mLabelDistanceFactor * yFactor ) );
401 labelShifts.append( symbolPositions.at( symbolIndex ) - centerPoint + labelShift );
402 }
403
404 gridRadius = userPointRadius;
405 break;
406 }
407 }
408}
409
410void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
411{
412 const double shiftAmount = -radius * ( size - 1.0 ) / 2.0;
413 const QPointF centralShift( shiftAmount, shiftAmount );
414 for ( int i = 0; i < pointSymbolPositions.size(); ++i )
415 {
416 pointSymbolPositions[i] += centralShift;
417 }
418}
419
420void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
421 QList<QPointF> pointSymbolPositions, int nSymbols ) const
422{
423 QPainter *p = context.renderContext().painter();
424 if ( nSymbols < 2 || !p ) //draw grid only if multiple features
425 {
426 return;
427 }
428
429 QPen gridPen( mCircleColor );
430 gridPen.setWidthF( context.renderContext().convertToPainterUnits( mCircleWidth, Qgis::RenderUnit::Millimeters ) );
431 p->setPen( gridPen );
432
433 for ( int i = 0; i < pointSymbolPositions.size(); ++i )
434 {
435 if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
436 {
437 const QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
438 p->drawLine( gridLineRow );
439 }
440
441 if ( i + gridSizeUnits < pointSymbolPositions.size() )
442 {
443 const QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
444 p->drawLine( gridLineColumn );
445 }
446 }
447}
448
449void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols ) const
450{
451 QPainter *p = context.renderContext().painter();
452 if ( nSymbols < 2 || !p ) //draw circle only if multiple features
453 {
454 return;
455 }
456
457 //draw Circle
458 QPen circlePen( mCircleColor );
459 circlePen.setWidthF( context.renderContext().convertToPainterUnits( mCircleWidth, Qgis::RenderUnit::Millimeters ) );
460 p->setPen( circlePen );
461 p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
462}
463
464void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions ) const
465{
466 QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
467 ClusteredGroup::const_iterator groupIt = group.constBegin();
468 for ( ; symbolPosIt != symbolPositions.constEnd() && groupIt != group.constEnd();
469 ++symbolPosIt, ++groupIt )
470 {
471 context.expressionContext().setFeature( groupIt->feature );
472 groupIt->symbol()->startRender( context );
473 groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
474 if ( context.hasRenderedFeatureHandlers() )
475 {
476 const QgsGeometry bounds( QgsGeometry::fromRect( QgsRectangle( groupIt->symbol()->bounds( *symbolPosIt, context, groupIt->feature ) ) ) );
477 const QList< QgsRenderedFeatureHandlerInterface * > handlers = context.renderedFeatureHandlers();
478 const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext featureContext( context );
479 for ( QgsRenderedFeatureHandlerInterface *handler : handlers )
480 handler->handleRenderedFeature( groupIt->feature, bounds, featureContext );
481 }
482 groupIt->symbol()->stopRender( context );
483 }
484}
485
487{
488 if ( renderer->type() == "pointDisplacement"_L1 )
489 {
490 return dynamic_cast<QgsPointDisplacementRenderer *>( renderer->clone() );
491 }
492 else if ( renderer->type() == "singleSymbol"_L1 ||
493 renderer->type() == "categorizedSymbol"_L1 ||
494 renderer->type() == "graduatedSymbol"_L1 ||
495 renderer->type() == "RuleRenderer"_L1 )
496 {
498 pointRenderer->setEmbeddedRenderer( renderer->clone() );
499 renderer->copyRendererData( pointRenderer );
500 return pointRenderer;
501 }
502 else if ( renderer->type() == "pointCluster"_L1 )
503 {
505 const QgsPointClusterRenderer *clusterRenderer = static_cast< const QgsPointClusterRenderer * >( renderer );
506 if ( clusterRenderer->embeddedRenderer() )
507 pointRenderer->setEmbeddedRenderer( clusterRenderer->embeddedRenderer()->clone() );
508 pointRenderer->setTolerance( clusterRenderer->tolerance() );
509 pointRenderer->setToleranceUnit( clusterRenderer->toleranceUnit() );
510 pointRenderer->setToleranceMapUnitScale( clusterRenderer->toleranceMapUnitScale() );
511 renderer->copyRendererData( pointRenderer );
512 return pointRenderer;
513 }
514 else
515 {
516 return nullptr;
517 }
518}
QFlags< FeatureRendererFlag > FeatureRendererFlags
Flags controlling behavior of vector feature renderers.
Definition qgis.h:857
@ AffectsLabeling
If present, indicates that the renderer will participate in the map labeling problem.
Definition qgis.h:848
@ Millimeters
Millimeters.
Definition qgis.h:5256
@ AffectsLabeling
If present, indicates that the symbol will participate in the map labeling problem.
Definition qgis.h:868
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsFeatureRenderer(const QString &type)
QString type() const
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
void saveRendererData(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context)
Saves generic renderer data into the specified element.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
Container of fields for a vector layer.
Definition qgsfields.h:46
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.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
A marker symbol type, for rendering Point and MultiPoint geometries.
A renderer that automatically clusters points with the same geographic position.
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
Stores renderer properties to an 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).
Qgis::FeatureRendererFlags flags() const override
Returns flags associated with the renderer.
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...
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.
void setLabelFont(const QFont &font)
Sets the font used for labeling points.
void setToleranceUnit(Qgis::RenderUnit unit)
Sets the units for the tolerance distance.
QgsPointDistanceRenderer(const QString &rendererName, const QString &labelAttributeName=QString())
Constructor for QgsPointDistanceRenderer.
void drawLabels(QPointF centerPoint, QgsSymbolRenderContext &context, const QList< QPointF > &labelShifts, const ClusteredGroup &group) const
Renders the labels for a group.
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.
QString labelAttributeName() const
Returns the attribute name used for labeling points, or an empty string if no labeling will be done b...
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
const QgsMapUnitScale & toleranceMapUnitScale() const
Returns the map unit scale object for the distance tolerance.
void setEmbeddedRenderer(QgsFeatureRenderer *r) override
Sets an embedded renderer (subrenderer) for this feature renderer.
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 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.
Qgis::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
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.
Qgis::RenderUnit mToleranceUnit
Unit for distance tolerance.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
bool hasRenderedFeatureHandlers() const
Returns true if the context has any rendered feature handlers.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
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.
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:1398
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Encapsulates the context in which a symbol is being rendered.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
#define RENDERER_TAG_NAME
Definition qgsrenderer.h:57
Contains information relating to the style entity currently being visited.