QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
qgspointclusterrenderer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointclusterrenderer.cpp
3 ---------------------------
4 begin : February 2016
5 copyright : (C) 2016 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
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 "qgsmarkersymbol.h"
26#include "qgsproperty.h"
28#include "qgssymbollayerutils.h"
29#include "qgsunittypes.h"
30
32 : QgsPointDistanceRenderer( QStringLiteral( "pointCluster" ) )
33{
34 mClusterSymbol = std::make_unique<QgsMarkerSymbol>( );
35 mClusterSymbol->setSize( 4 );
36 mClusterSymbol->setColor( QColor( 245, 75, 80 ) );
37
39 fm->setFontFamily( QFont().defaultFamily() );
40 fm->setColor( QColor( 255, 255, 255 ) );
41 fm->setSize( 3.2 );
42 fm->setOffset( QPointF( 0, -0.4 ) );
44 mClusterSymbol->insertSymbolLayer( 1, fm );
45}
46
48{
50 if ( mClusterSymbol && mClusterSymbol->flags().testFlag( Qgis::SymbolFlag::AffectsLabeling ) )
54 return res;
55}
56
58{
60 if ( mRenderer )
61 r->setEmbeddedRenderer( mRenderer->clone() );
68 if ( mClusterSymbol )
69 {
70 r->setClusterSymbol( mClusterSymbol->clone() );
71 }
73 return r;
74}
75
76void QgsPointClusterRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group ) const
77{
78 if ( group.size() > 1 )
79 {
80 mClusterSymbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, false );
81 }
82 else
83 {
84 //single isolated symbol, draw it untouched
85 QgsMarkerSymbol *symbol = group.at( 0 ).symbol();
86 symbol->startRender( context );
87 symbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, group.at( 0 ).isSelected );
88 symbol->stopRender( context );
89 }
90}
91
93{
94 if ( mClusterSymbol )
95 {
96 mClusterSymbol->startRender( context, fields );
97 }
99}
100
102{
104 if ( mClusterSymbol )
105 {
106 mClusterSymbol->stopRender( context );
107 }
108}
109
110QgsFeatureRenderer *QgsPointClusterRenderer::create( QDomElement &symbologyElem, const QgsReadWriteContext &context )
111{
113 r->setTolerance( symbologyElem.attribute( QStringLiteral( "tolerance" ), QStringLiteral( "0.00001" ) ).toDouble() );
114 r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( QStringLiteral( "toleranceUnit" ), QStringLiteral( "MapUnit" ) ) ) );
115 r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( QStringLiteral( "toleranceUnitScale" ) ) ) );
116
117 //look for an embedded renderer <renderer-v2>
118 QDomElement embeddedRendererElem = symbologyElem.firstChildElement( QStringLiteral( "renderer-v2" ) );
119 if ( !embeddedRendererElem.isNull() )
120 {
121 r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
122 }
123
124 //center symbol
125 const QDomElement centerSymbolElem = symbologyElem.firstChildElement( QStringLiteral( "symbol" ) );
126 if ( !centerSymbolElem.isNull() )
127 {
128 r->setClusterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ).release() );
129 }
130 return r;
131}
132
134{
135 return mClusterSymbol.get();
136}
137
138QDomElement QgsPointClusterRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
139{
140 QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
141 rendererElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "pointCluster" ) );
142 rendererElement.setAttribute( QStringLiteral( "tolerance" ), QString::number( mTolerance ) );
143 rendererElement.setAttribute( QStringLiteral( "toleranceUnit" ), QgsUnitTypes::encodeUnit( mToleranceUnit ) );
144 rendererElement.setAttribute( QStringLiteral( "toleranceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
145
146 if ( mRenderer )
147 {
148 const QDomElement embeddedRendererElem = mRenderer->save( doc, context );
149 rendererElement.appendChild( embeddedRendererElem );
150 }
151 if ( mClusterSymbol )
152 {
153 const QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "centerSymbol" ), mClusterSymbol.get(), doc, context );
154 rendererElement.appendChild( centerSymbolElem );
155 }
156
157 saveRendererData( doc, rendererElement, context );
158
159 return rendererElement;
160}
161
163{
164 QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
165 if ( mClusterSymbol )
166 attr.unite( mClusterSymbol->usedAttributes( context ) );
167 return attr;
168}
169
171{
172 if ( !QgsPointDistanceRenderer::accept( visitor ) )
173 return false;
174
175 if ( mClusterSymbol )
176 {
177 QgsStyleSymbolEntity entity( mClusterSymbol.get() );
178 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "cluster" ), QObject::tr( "Cluster Symbol" ) ) ) )
179 return false;
180 }
181
182 return true;
183}
184
186{
187 mClusterSymbol.reset( symbol );
188}
189
191{
192 if ( renderer->type() == QLatin1String( "pointCluster" ) )
193 {
194 return dynamic_cast<QgsPointClusterRenderer *>( renderer->clone() );
195 }
196 else if ( renderer->type() == QLatin1String( "singleSymbol" ) ||
197 renderer->type() == QLatin1String( "categorizedSymbol" ) ||
198 renderer->type() == QLatin1String( "graduatedSymbol" ) ||
199 renderer->type() == QLatin1String( "RuleRenderer" ) )
200 {
202 pointRenderer->setEmbeddedRenderer( renderer->clone() );
203 renderer->copyRendererData( pointRenderer );
204 return pointRenderer;
205 }
206 else if ( renderer->type() == QLatin1String( "pointDisplacement" ) )
207 {
209 const QgsPointDisplacementRenderer *displacementRenderer = static_cast< const QgsPointDisplacementRenderer * >( renderer );
210 if ( displacementRenderer->embeddedRenderer() )
211 pointRenderer->setEmbeddedRenderer( displacementRenderer->embeddedRenderer()->clone() );
212 pointRenderer->setTolerance( displacementRenderer->tolerance() );
213 pointRenderer->setToleranceUnit( displacementRenderer->toleranceUnit() );
214 pointRenderer->setToleranceMapUnitScale( displacementRenderer->toleranceMapUnitScale() );
215 renderer->copyRendererData( pointRenderer );
216 return pointRenderer;
217 }
218 else
219 {
220 return nullptr;
221 }
222}
QFlags< FeatureRendererFlag > FeatureRendererFlags
Flags controlling behavior of vector feature renderers.
Definition qgis.h:838
@ AffectsLabeling
If present, indicates that the renderer will participate in the map labeling problem.
Definition qgis.h:829
@ AffectsLabeling
If present, indicates that the symbol will participate in the map labeling problem.
Definition qgis.h:849
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
A marker symbol layer which displays characters rendered using a font.
void setFontFamily(const QString &family)
Sets the font family for the font which will be used to render the point.
virtual void setSize(double size)
Sets the symbol size.
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
A marker symbol type, for rendering Point and MultiPoint geometries.
void renderPoint(QPointF point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol at the specified point, using the given render context.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
QgsPointClusterRenderer * clone() const override
Create a deep copy of this renderer.
void setClusterSymbol(QgsMarkerSymbol *symbol)
Sets the symbol for rendering clustered groups.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
Stores renderer properties to an XML element.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
static QgsFeatureRenderer * create(QDomElement &symbologyElem, const QgsReadWriteContext &context)
Creates a renderer from XML element.
Qgis::FeatureRendererFlags flags() const override
Returns flags associated with the renderer.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
QgsMarkerSymbol * clusterSymbol()
Returns the symbol used for rendering clustered groups (but not ownership of the symbol).
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
static QgsPointClusterRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointClusterRenderer from an existing renderer.
A renderer that automatically displaces points with the same geographic location.
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.
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 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.
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.
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...
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
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:1397
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.
@ Character
Character, eg for font marker symbol layers.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
void stopRender(QgsRenderContext &context)
Ends the rendering process.
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
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:55
Contains information relating to the style entity currently being visited.