QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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 //calculate max diagonal size from all symbols in group
81 double diagonal = 0;
82 QVector<double> diagonals( group.size() );
83 double currentDiagonal;
84
85 int groupPosition = 0;
86 for ( const GroupedFeature &feature : group )
87 {
88 if ( QgsMarkerSymbol *symbol = feature.symbol() )
89 {
90 currentDiagonal = M_SQRT2 * symbol->size( context );
91 diagonals[groupPosition] = currentDiagonal;
92 diagonal = std::max( diagonal, currentDiagonal );
93 }
94 else
95 {
96 diagonals[groupPosition] = 0.0;
97 }
98 groupPosition++;
99 }
100
101 QgsSymbolRenderContext symbolContext( context, Qgis::RenderUnit::Millimeters, 1.0, false );
102
103 QList<QPointF> symbolPositions;
104 QList<QPointF> labelPositions;
105 double circleRadius = -1.0;
106 double gridRadius = -1.0;
107 int gridSize = -1;
108
109 calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize, diagonals );
110
111 //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids
112 if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 )
113 {
114 switch ( mPlacement )
115 {
116 case Ring:
117 case ConcentricRings:
118 drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
119 break;
120 case Grid:
121 drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
122 break;
123 }
124 }
125
126 if ( group.size() > 1 )
127 {
128 //draw mid point
129 const QgsFeature firstFeature = group.at( 0 ).feature;
130 if ( mCenterSymbol )
131 {
132 mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
133 }
134 else
135 {
136 const double rectSize = symbolContext.renderContext().convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
137 context.painter()->drawRect( QRectF( centerPoint.x() - rectSize, centerPoint.y() - rectSize, rectSize * 2, rectSize * 2 ) );
138 }
139 }
140
141 //draw symbols on the circle
142 drawSymbols( group, context, symbolPositions );
143 //and also the labels
144 if ( mLabelIndex >= 0 )
145 {
146 drawLabels( centerPoint, symbolContext, labelPositions, group );
147 }
148}
149
150
152{
153 if ( mCenterSymbol )
154 {
155 mCenterSymbol->startRender( context, fields );
156 }
157
158 QgsPointDistanceRenderer::startRender( context, fields );
159}
160
162{
164 if ( mCenterSymbol )
165 {
166 mCenterSymbol->stopRender( context );
167 }
168}
169
171{
173 r->setLabelAttributeName( symbologyElem.attribute( u"labelAttributeName"_s ) );
174 QFont labelFont;
175 if ( !QgsFontUtils::setFromXmlChildNode( labelFont, symbologyElem, u"labelFontProperties"_s ) )
176 {
177 labelFont.fromString( symbologyElem.attribute( u"labelFont"_s, QString() ) );
178 }
180 r->setPlacement( static_cast< Placement >( symbologyElem.attribute( u"placement"_s, u"0"_s ).toInt() ) );
181 r->setCircleWidth( symbologyElem.attribute( u"circleWidth"_s, u"0.4"_s ).toDouble() );
182 r->setCircleColor( QgsColorUtils::colorFromString( symbologyElem.attribute( u"circleColor"_s, QString() ) ) );
183 r->setLabelColor( QgsColorUtils::colorFromString( symbologyElem.attribute( u"labelColor"_s, QString() ) ) );
184 r->setCircleRadiusAddition( symbologyElem.attribute( u"circleRadiusAddition"_s, u"0.0"_s ).toDouble() );
185 r->setLabelDistanceFactor( symbologyElem.attribute( u"labelDistanceFactor"_s, u"0.5"_s ).toDouble() );
186 r->setMinimumLabelScale( symbologyElem.attribute( u"maxLabelScaleDenominator"_s, u"-1"_s ).toDouble() );
187 r->setTolerance( symbologyElem.attribute( u"tolerance"_s, u"0.00001"_s ).toDouble() );
188 r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( u"toleranceUnit"_s, u"MapUnit"_s ) ) );
189 r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( u"toleranceUnitScale"_s ) ) );
190
191 //look for an embedded renderer <renderer-v2>
192 QDomElement embeddedRendererElem = symbologyElem.firstChildElement( u"renderer-v2"_s );
193 if ( !embeddedRendererElem.isNull() )
194 {
195 r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
196 }
197
198 //center symbol
199 const QDomElement centerSymbolElem = symbologyElem.firstChildElement( u"symbol"_s );
200 if ( !centerSymbolElem.isNull() )
201 {
202 r->setCenterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ).release() );
203 }
204 return r;
205}
206
208{
209 return mCenterSymbol.get();
210}
211
212QDomElement QgsPointDisplacementRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
213{
214 QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
215 rendererElement.setAttribute( u"type"_s, u"pointDisplacement"_s );
216 rendererElement.setAttribute( u"labelAttributeName"_s, mLabelAttributeName );
217 rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, u"labelFontProperties"_s ) );
218 rendererElement.setAttribute( u"circleWidth"_s, QString::number( mCircleWidth ) );
219 rendererElement.setAttribute( u"circleColor"_s, QgsColorUtils::colorToString( mCircleColor ) );
220 rendererElement.setAttribute( u"labelColor"_s, QgsColorUtils::colorToString( mLabelColor ) );
221 rendererElement.setAttribute( u"circleRadiusAddition"_s, QString::number( mCircleRadiusAddition ) );
222 rendererElement.setAttribute( u"labelDistanceFactor"_s, QString::number( mLabelDistanceFactor ) );
223 rendererElement.setAttribute( u"placement"_s, static_cast< int >( mPlacement ) );
224 rendererElement.setAttribute( u"maxLabelScaleDenominator"_s, QString::number( mMinLabelScale ) );
225 rendererElement.setAttribute( u"tolerance"_s, QString::number( mTolerance ) );
226 rendererElement.setAttribute( u"toleranceUnit"_s, QgsUnitTypes::encodeUnit( mToleranceUnit ) );
227 rendererElement.setAttribute( u"toleranceUnitScale"_s, QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
228
229 if ( mRenderer )
230 {
231 const QDomElement embeddedRendererElem = mRenderer->save( doc, context );
232 rendererElement.appendChild( embeddedRendererElem );
233 }
234 if ( mCenterSymbol )
235 {
236 const QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( u"centerSymbol"_s, mCenterSymbol.get(), doc, context );
237 rendererElement.appendChild( centerSymbolElem );
238 }
239
240 saveRendererData( doc, rendererElement, context );
241
242 return rendererElement;
243}
244
246{
247 QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
248 if ( mCenterSymbol )
249 attr.unite( mCenterSymbol->usedAttributes( context ) );
250 return attr;
251}
252
254{
255 if ( !QgsPointDistanceRenderer::accept( visitor ) )
256 return false;
257
258 if ( mCenterSymbol )
259 {
260 QgsStyleSymbolEntity entity( mCenterSymbol.get() );
261 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, u"center"_s, QObject::tr( "Center Symbol" ) ) ) )
262 return false;
263 }
264
265 return true;
266}
267
269{
270 mCenterSymbol.reset( symbol );
271}
272
273void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions(
274 QgsSymbolRenderContext &symbolContext,
275 QPointF centerPoint,
276 int nPosition,
277 double symbolDiagonal,
278 QList<QPointF> &symbolPositions,
279 QList<QPointF> &labelShifts,
280 double &circleRadius,
281 double &gridRadius,
282 int &gridSize,
283 QVector<double> &diagonals
284) const
285{
286 symbolPositions.clear();
287 labelShifts.clear();
288
289 if ( nPosition < 1 )
290 {
291 return;
292 }
293 else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
294 {
295 const double side = std::sqrt( std::pow( symbolDiagonal, 2 ) / 2.0 );
296 symbolPositions.append( centerPoint );
297 labelShifts.append( QPointF( side * mLabelDistanceFactor, -side * mLabelDistanceFactor ) );
298 return;
299 }
300
301 const double circleAdditionPainterUnits = symbolContext.renderContext().convertToPainterUnits( mCircleRadiusAddition, Qgis::RenderUnit::Millimeters );
302
303 switch ( mPlacement )
304 {
305 case Ring:
306 {
307 const double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 * M_PI );
308 const double radius = std::max( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
309
310 const double angleStep = 2 * M_PI / nPosition;
311 double currentAngle = 0.0;
312 for ( int featureIndex = 0; featureIndex < nPosition; currentAngle += angleStep, featureIndex++ )
313 {
314 const double sinusCurrentAngle = std::sin( currentAngle );
315 const double cosinusCurrentAngle = std::cos( currentAngle );
316 const QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
317
318 const QPointF labelShift( ( radius + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * sinusCurrentAngle, ( radius + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * cosinusCurrentAngle );
319 symbolPositions.append( centerPoint + positionShift );
320 labelShifts.append( labelShift );
321 }
322 circleRadius = radius;
323 break;
324 }
325 case ConcentricRings:
326 {
327 const double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
328
329 int pointsRemaining = nPosition;
330 int ringNumber = 1;
331 const double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
332 int featureIndex = 0;
333 while ( pointsRemaining > 0 )
334 {
335 const double radiusCurrentRing = std::max( firstRingRadius + ( ringNumber - 1 ) * symbolDiagonal + ringNumber * circleAdditionPainterUnits, 0.0 );
336 const int maxPointsCurrentRing = std::max( std::floor( 2 * M_PI * radiusCurrentRing / symbolDiagonal ), 1.0 );
337 const int actualPointsCurrentRing = std::min( maxPointsCurrentRing, pointsRemaining );
338
339 const double angleStep = 2 * M_PI / actualPointsCurrentRing;
340 double currentAngle = 0.0;
341 for ( int i = 0; i < actualPointsCurrentRing; ++i )
342 {
343 const double sinusCurrentAngle = std::sin( currentAngle );
344 const double cosinusCurrentAngle = std::cos( currentAngle );
345 const QPointF positionShift( radiusCurrentRing * sinusCurrentAngle, radiusCurrentRing * cosinusCurrentAngle );
346 const QPointF
347 labelShift( ( radiusCurrentRing + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * sinusCurrentAngle, ( radiusCurrentRing + diagonals.at( featureIndex ) * mLabelDistanceFactor ) * cosinusCurrentAngle );
348 symbolPositions.append( centerPoint + positionShift );
349 labelShifts.append( labelShift );
350 currentAngle += angleStep;
351 featureIndex++;
352 }
353
354 pointsRemaining -= actualPointsCurrentRing;
355 ringNumber++;
356 circleRadius = radiusCurrentRing;
357 }
358 break;
359 }
360 case Grid:
361 {
362 const double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
363 int pointsRemaining = nPosition;
364 gridSize = std::ceil( std::sqrt( pointsRemaining ) );
365 if ( pointsRemaining - std::pow( gridSize - 1, 2 ) < gridSize )
366 gridSize -= 1;
367 const double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
368 const double userPointRadius = originalPointRadius + circleAdditionPainterUnits;
369
370 int yIndex = 0;
371 while ( pointsRemaining > 0 )
372 {
373 for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
374 {
375 const QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
376 symbolPositions.append( centerPoint + positionShift );
377 pointsRemaining--;
378 }
379 yIndex++;
380 }
381
382 centralizeGrid( symbolPositions, userPointRadius, gridSize );
383
384 int xFactor;
385 int yFactor;
386 double side = 0;
387 for ( int symbolIndex = 0; symbolIndex < symbolPositions.size(); ++symbolIndex )
388 {
389 if ( symbolPositions.at( symbolIndex ).x() < centerPoint.x() )
390 {
391 xFactor = -1;
392 }
393 else
394 {
395 xFactor = 1;
396 }
397
398 if ( symbolPositions.at( symbolIndex ).y() < centerPoint.y() )
399 {
400 yFactor = 1;
401 }
402 else
403 {
404 yFactor = -1;
405 }
406
407 side = std::sqrt( std::pow( diagonals.at( symbolIndex ), 2 ) / 2.0 );
408 const QPointF labelShift( ( side * mLabelDistanceFactor * xFactor ), ( -side * mLabelDistanceFactor * yFactor ) );
409 labelShifts.append( symbolPositions.at( symbolIndex ) - centerPoint + labelShift );
410 }
411
412 gridRadius = userPointRadius;
413 break;
414 }
415 }
416}
417
418void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
419{
420 const double shiftAmount = -radius * ( size - 1.0 ) / 2.0;
421 const QPointF centralShift( shiftAmount, shiftAmount );
422 for ( int i = 0; i < pointSymbolPositions.size(); ++i )
423 {
424 pointSymbolPositions[i] += centralShift;
425 }
426}
427
428void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context, QList<QPointF> pointSymbolPositions, int nSymbols ) const
429{
430 QPainter *p = context.renderContext().painter();
431 if ( nSymbols < 2 || !p ) //draw grid only if multiple features
432 {
433 return;
434 }
435
436 QPen gridPen( mCircleColor );
437 gridPen.setWidthF( context.renderContext().convertToPainterUnits( mCircleWidth, Qgis::RenderUnit::Millimeters ) );
438 p->setPen( gridPen );
439
440 for ( int i = 0; i < pointSymbolPositions.size(); ++i )
441 {
442 if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
443 {
444 const QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
445 p->drawLine( gridLineRow );
446 }
447
448 if ( i + gridSizeUnits < pointSymbolPositions.size() )
449 {
450 const QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
451 p->drawLine( gridLineColumn );
452 }
453 }
454}
455
456void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols ) const
457{
458 QPainter *p = context.renderContext().painter();
459 if ( nSymbols < 2 || !p ) //draw circle only if multiple features
460 {
461 return;
462 }
463
464 //draw Circle
465 QPen circlePen( mCircleColor );
466 circlePen.setWidthF( context.renderContext().convertToPainterUnits( mCircleWidth, Qgis::RenderUnit::Millimeters ) );
467 p->setPen( circlePen );
468 p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
469}
470
471void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions ) const
472{
473 QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
474 ClusteredGroup::const_iterator groupIt = group.constBegin();
475 for ( ; symbolPosIt != symbolPositions.constEnd() && groupIt != group.constEnd(); ++symbolPosIt, ++groupIt )
476 {
477 context.expressionContext().setFeature( groupIt->feature );
478 groupIt->symbol()->startRender( context );
479 groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
480 if ( context.hasRenderedFeatureHandlers() )
481 {
482 const QgsGeometry bounds( QgsGeometry::fromRect( QgsRectangle( groupIt->symbol()->bounds( *symbolPosIt, context, groupIt->feature ) ) ) );
483 const QList< QgsRenderedFeatureHandlerInterface * > handlers = context.renderedFeatureHandlers();
484 const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext featureContext( context );
485 for ( QgsRenderedFeatureHandlerInterface *handler : handlers )
486 handler->handleRenderedFeature( groupIt->feature, bounds, featureContext );
487 }
488 groupIt->symbol()->stopRender( context );
489 }
490}
491
493{
494 if ( renderer->type() == "pointDisplacement"_L1 )
495 {
496 return dynamic_cast<QgsPointDisplacementRenderer *>( renderer->clone() );
497 }
498 else if ( renderer->type() == "singleSymbol"_L1 || renderer->type() == "categorizedSymbol"_L1 || renderer->type() == "graduatedSymbol"_L1 || renderer->type() == "RuleRenderer"_L1 )
499 {
501 pointRenderer->setEmbeddedRenderer( renderer->clone() );
502 renderer->copyRendererData( pointRenderer );
503 return pointRenderer;
504 }
505 else if ( renderer->type() == "pointCluster"_L1 )
506 {
508 const QgsPointClusterRenderer *clusterRenderer = static_cast< const QgsPointClusterRenderer * >( renderer );
509 if ( clusterRenderer->embeddedRenderer() )
510 pointRenderer->setEmbeddedRenderer( clusterRenderer->embeddedRenderer()->clone() );
511 pointRenderer->setTolerance( clusterRenderer->tolerance() );
512 pointRenderer->setToleranceUnit( clusterRenderer->toleranceUnit() );
513 pointRenderer->setToleranceMapUnitScale( clusterRenderer->toleranceMapUnitScale() );
514 renderer->copyRendererData( pointRenderer );
515 return pointRenderer;
516 }
517 else
518 {
519 return nullptr;
520 }
521}
QFlags< FeatureRendererFlag > FeatureRendererFlags
Flags controlling behavior of vector feature renderers.
Definition qgis.h:864
@ AffectsLabeling
If present, indicates that the renderer will participate in the map labeling problem.
Definition qgis.h:855
@ Millimeters
Millimeters.
Definition qgis.h:5341
@ AffectsLabeling
If present, indicates that the symbol will participate in the map labeling problem.
Definition qgis.h:875
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:1393
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.