QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
20 #include "qgssymbollayerutils.h"
21 #include "qgspainteffectregistry.h"
22 #include "qgspainteffect.h"
23 #include "qgsmarkersymbollayer.h"
24 #include "qgsproperty.h"
25 #include "qgsstyleentityvisitor.h"
26 #include <cmath>
27 
29  : QgsPointDistanceRenderer( QStringLiteral( "pointCluster" ) )
30 {
31  mClusterSymbol.reset( new QgsMarkerSymbol() );
32  mClusterSymbol->setSize( 4 );
33  mClusterSymbol->setColor( QColor( 245, 75, 80 ) );
34 
36  fm->setFontFamily( QFont().defaultFamily() );
37  fm->setColor( QColor( 255, 255, 255 ) );
38  fm->setSize( 3.2 );
39  fm->setOffset( QPointF( 0, -0.4 ) );
41  mClusterSymbol->insertSymbolLayer( 1, fm );
42 }
43 
45 {
47  if ( mRenderer )
48  r->setEmbeddedRenderer( mRenderer->clone() );
55  if ( mClusterSymbol )
56  {
57  r->setClusterSymbol( mClusterSymbol->clone() );
58  }
59  copyRendererData( r );
60  return r;
61 }
62 
63 void QgsPointClusterRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group )
64 {
65  if ( group.size() > 1 )
66  {
67  mClusterSymbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, false );
68  }
69  else
70  {
71  //single isolated symbol, draw it untouched
72  QgsMarkerSymbol *symbol = group.at( 0 ).symbol();
73  symbol->startRender( context );
74  symbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, group.at( 0 ).isSelected );
75  symbol->stopRender( context );
76  }
77 }
78 
80 {
81  if ( mClusterSymbol )
82  {
83  mClusterSymbol->startRender( context, fields );
84  }
85  QgsPointDistanceRenderer::startRender( context, fields );
86 }
87 
89 {
91  if ( mClusterSymbol )
92  {
93  mClusterSymbol->stopRender( context );
94  }
95 }
96 
97 QgsFeatureRenderer *QgsPointClusterRenderer::create( QDomElement &symbologyElem, const QgsReadWriteContext &context )
98 {
100  r->setTolerance( symbologyElem.attribute( QStringLiteral( "tolerance" ), QStringLiteral( "0.00001" ) ).toDouble() );
101  r->setToleranceUnit( QgsUnitTypes::decodeRenderUnit( symbologyElem.attribute( QStringLiteral( "toleranceUnit" ), QStringLiteral( "MapUnit" ) ) ) );
102  r->setToleranceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( symbologyElem.attribute( QStringLiteral( "toleranceUnitScale" ) ) ) );
103 
104  //look for an embedded renderer <renderer-v2>
105  QDomElement embeddedRendererElem = symbologyElem.firstChildElement( QStringLiteral( "renderer-v2" ) );
106  if ( !embeddedRendererElem.isNull() )
107  {
108  r->setEmbeddedRenderer( QgsFeatureRenderer::load( embeddedRendererElem, context ) );
109  }
110 
111  //center symbol
112  QDomElement centerSymbolElem = symbologyElem.firstChildElement( QStringLiteral( "symbol" ) );
113  if ( !centerSymbolElem.isNull() )
114  {
115  r->setClusterSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( centerSymbolElem, context ) );
116  }
117  return r;
118 }
119 
121 {
122  return mClusterSymbol.get();
123 }
124 
125 QDomElement QgsPointClusterRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
126 {
127  QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
128  rendererElement.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
129  rendererElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "pointCluster" ) );
130  rendererElement.setAttribute( QStringLiteral( "tolerance" ), QString::number( mTolerance ) );
131  rendererElement.setAttribute( QStringLiteral( "toleranceUnit" ), QgsUnitTypes::encodeUnit( mToleranceUnit ) );
132  rendererElement.setAttribute( QStringLiteral( "toleranceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mToleranceMapUnitScale ) );
133 
134  if ( mRenderer )
135  {
136  QDomElement embeddedRendererElem = mRenderer->save( doc, context );
137  rendererElement.appendChild( embeddedRendererElem );
138  }
139  if ( mClusterSymbol )
140  {
141  QDomElement centerSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "centerSymbol" ), mClusterSymbol.get(), doc, context );
142  rendererElement.appendChild( centerSymbolElem );
143  }
144 
146  mPaintEffect->saveProperties( doc, rendererElement );
147 
148  if ( !mOrderBy.isEmpty() )
149  {
150  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
151  mOrderBy.save( orderBy );
152  rendererElement.appendChild( orderBy );
153  }
154  rendererElement.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
155 
156  return rendererElement;
157 }
158 
159 QSet<QString> QgsPointClusterRenderer::usedAttributes( const QgsRenderContext &context ) const
160 {
161  QSet<QString> attr = QgsPointDistanceRenderer::usedAttributes( context );
162  if ( mClusterSymbol )
163  attr.unite( mClusterSymbol->usedAttributes( context ) );
164  return attr;
165 }
166 
168 {
169  if ( !QgsPointDistanceRenderer::accept( visitor ) )
170  return false;
171 
172  if ( mClusterSymbol )
173  {
174  QgsStyleSymbolEntity entity( mClusterSymbol.get() );
175  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "cluster" ), QObject::tr( "Cluster Symbol" ) ) ) )
176  return false;
177  }
178 
179  return true;
180 }
181 
183 {
184  mClusterSymbol.reset( symbol );
185 }
186 
188 {
189  if ( renderer->type() == QLatin1String( "pointCluster" ) )
190  {
191  return dynamic_cast<QgsPointClusterRenderer *>( renderer->clone() );
192  }
193  else if ( renderer->type() == QLatin1String( "singleSymbol" ) ||
194  renderer->type() == QLatin1String( "categorizedSymbol" ) ||
195  renderer->type() == QLatin1String( "graduatedSymbol" ) ||
196  renderer->type() == QLatin1String( "RuleRenderer" ) )
197  {
198  QgsPointClusterRenderer *pointRenderer = new QgsPointClusterRenderer();
199  pointRenderer->setEmbeddedRenderer( renderer->clone() );
200  return pointRenderer;
201  }
202  else if ( renderer->type() == QLatin1String( "pointDisplacement" ) )
203  {
204  QgsPointClusterRenderer *pointRenderer = new QgsPointClusterRenderer();
205  const QgsPointDisplacementRenderer *displacementRenderer = static_cast< const QgsPointDisplacementRenderer * >( renderer );
206  if ( displacementRenderer->embeddedRenderer() )
207  pointRenderer->setEmbeddedRenderer( displacementRenderer->embeddedRenderer()->clone() );
208  pointRenderer->setTolerance( displacementRenderer->tolerance() );
209  pointRenderer->setToleranceUnit( displacementRenderer->toleranceUnit() );
210  pointRenderer->setToleranceMapUnitScale( displacementRenderer->toleranceMapUnitScale() );
211  if ( const_cast< QgsPointDisplacementRenderer * >( displacementRenderer )->centerSymbol() )
212  pointRenderer->setClusterSymbol( const_cast< QgsPointDisplacementRenderer * >( displacementRenderer )->centerSymbol()->clone() );
213  return pointRenderer;
214  }
215  else
216  {
217  return nullptr;
218  }
219 }
QgsFeatureRenderer::copyRendererData
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:49
QgsFeatureRenderer::mOrderByEnabled
bool mOrderByEnabled
Definition: qgsrenderer.h:547
QgsFeatureRenderer::mForceRaster
bool mForceRaster
Definition: qgsrenderer.h:531
QgsFeatureRenderer::mPaintEffect
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:529
QgsPointDistanceRenderer::mToleranceUnit
QgsUnitTypes::RenderUnit mToleranceUnit
Unit for distance tolerance.
Definition: qgspointdistancerenderer.h:245
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:35
QgsSymbolLayerUtils::encodeMapUnitScale
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
Definition: qgssymbollayerutils.cpp:558
QgsFeatureRequest::OrderBy::save
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
Definition: qgsfeaturerequest.cpp:448
QgsStyleSymbolEntity
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1201
QgsSymbolLayer::setColor
virtual void setColor(const QColor &color)
The fill color.
Definition: qgssymbollayer.h:232
qgssymbollayerutils.h
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsFeatureRenderer::type
QString type() const
Definition: qgsrenderer.h:141
qgsmarkersymbollayer.h
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsPointClusterRenderer::convertFromRenderer
static QgsPointClusterRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointClusterRenderer from an existing renderer.
Definition: qgspointclusterrenderer.cpp:187
QgsStyleEntityVisitorInterface
An interface for classes which can visit style entity (e.g.
Definition: qgsstyleentityvisitor.h:34
QgsPointClusterRenderer::create
static QgsFeatureRenderer * create(QDomElement &symbologyElem, const QgsReadWriteContext &context)
Creates a renderer from XML element.
Definition: qgspointclusterrenderer.cpp:97
qgspainteffectregistry.h
QgsPointDistanceRenderer::embeddedRenderer
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Definition: qgspointdistancerenderer.cpp:164
QgsProperty::fromExpression
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
Definition: qgsproperty.cpp:212
qgspainteffect.h
QgsPointDistanceRenderer::mLabelFont
QFont mLabelFont
Label font.
Definition: qgspointdistancerenderer.h:250
QgsFeatureRenderer::load
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
Definition: qgsrenderer.cpp:149
QgsPointClusterRenderer::save
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
Definition: qgspointclusterrenderer.cpp:125
QgsPointDistanceRenderer::toleranceMapUnitScale
const QgsMapUnitScale & toleranceMapUnitScale() const
Returns the map unit scale object for the distance tolerance.
Definition: qgspointdistancerenderer.h:229
QgsPaintEffect::saveProperties
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Definition: qgspainteffect.cpp:54
QgsPointClusterRenderer::clone
QgsPointClusterRenderer * clone() const override
Create a deep copy of this renderer.
Definition: qgspointclusterrenderer.cpp:44
QgsStyleEntityVisitorInterface::StyleLeaf
Contains information relating to the style entity currently being visited.
Definition: qgsstyleentityvisitor.h:61
QgsPointClusterRenderer::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
Definition: qgspointclusterrenderer.cpp:79
QgsPointDistanceRenderer::mMinLabelScale
double mMinLabelScale
Maximum scale denominator for label display. A zero value indicates no scale limitation.
Definition: qgspointdistancerenderer.h:256
QgsPointClusterRenderer::clusterSymbol
QgsMarkerSymbol * clusterSymbol()
Returns the symbol used for rendering clustered groups (but not ownership of the symbol).
Definition: qgspointclusterrenderer.cpp:120
QgsMarkerSymbol::clone
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1937
QgsFeatureRenderer::orderBy
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
Definition: qgsrenderer.cpp:435
QgsUnitTypes::decodeRenderUnit
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
Definition: qgsunittypes.cpp:2900
QgsPointDistanceRenderer::mRenderer
std::unique_ptr< QgsFeatureRenderer > mRenderer
Embedded base renderer. This can be used for rendering individual, isolated points.
Definition: qgspointdistancerenderer.h:234
QgsPointClusterRenderer
A renderer that automatically clusters points with the same geographic position.
Definition: qgspointclusterrenderer.h:32
QgsPointDistanceRenderer::toleranceUnit
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
Definition: qgspointdistancerenderer.h:212
QgsPointClusterRenderer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
Definition: qgspointclusterrenderer.cpp:159
QgsPointDisplacementRenderer::centerSymbol
QgsMarkerSymbol * centerSymbol()
Returns the symbol for the center of a displacement group (but not ownership of the symbol).
Definition: qgspointdisplacementrenderer.cpp:188
QgsPaintEffectRegistry::isDefaultStack
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
Definition: qgspainteffectregistry.cpp:134
QgsSymbolLayer::PropertyCharacter
@ PropertyCharacter
Character, eg for font marker symbol layers.
Definition: qgssymbollayer.h:140
QgsPointDistanceRenderer::setLabelColor
void setLabelColor(const QColor &color)
Sets the color to use for for labeling points.
Definition: qgspointdistancerenderer.h:170
QgsUnitTypes::encodeUnit
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
Definition: qgsunittypes.cpp:122
QgsSymbol::stopRender
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:479
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:931
QgsFeatureRenderer::clone
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
RENDERER_TAG_NAME
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:51
QgsPointDistanceRenderer::mLabelColor
QColor mLabelColor
Label text color.
Definition: qgspointdistancerenderer.h:252
QgsPointDistanceRenderer
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
Definition: qgspointdistancerenderer.h:39
QgsPointDistanceRenderer::setEmbeddedRenderer
void setEmbeddedRenderer(QgsFeatureRenderer *r) override
Sets an embedded renderer (subrenderer) for this feature renderer.
Definition: qgspointdistancerenderer.cpp:159
QgsPointDistanceRenderer::mToleranceMapUnitScale
QgsMapUnitScale mToleranceMapUnitScale
Map unit scale for distance tolerance.
Definition: qgspointdistancerenderer.h:247
QgsMarkerSymbolLayer::setOffset
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
Definition: qgssymbollayer.h:718
QgsPointClusterRenderer::QgsPointClusterRenderer
QgsPointClusterRenderer()
Definition: qgspointclusterrenderer.cpp:28
QgsSymbol::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:454
QgsFontMarkerSymbolLayer::setFontFamily
void setFontFamily(const QString &family)
Sets the font family for the font which will be used to render the point.
Definition: qgsmarkersymbollayer.h:855
QgsPointDistanceRenderer::setToleranceMapUnitScale
void setToleranceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the distance tolerance.
Definition: qgspointdistancerenderer.h:221
QgsPointClusterRenderer::accept
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Definition: qgspointclusterrenderer.cpp:167
QgsPointDistanceRenderer::tolerance
double tolerance() const
Returns the tolerance distance for grouping points.
Definition: qgspointdistancerenderer.h:195
QgsFeatureRenderer::mOrderBy
QgsFeatureRequest::OrderBy mOrderBy
Definition: qgsrenderer.h:545
QgsPointDistanceRenderer::setToleranceUnit
void setToleranceUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the tolerance distance.
Definition: qgspointdistancerenderer.h:204
QgsPointDistanceRenderer::accept
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Definition: qgspointdistancerenderer.cpp:209
QgsFeatureRenderer
Definition: qgsrenderer.h:103
QgsPointDisplacementRenderer
A renderer that automatically displaces points with the same geographic location.
Definition: qgspointdisplacementrenderer.h:31
QgsPointDistanceRenderer::stopRender
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
Definition: qgspointdistancerenderer.cpp:334
QgsFontMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:803
QgsPointDistanceRenderer::setLabelFont
void setLabelFont(const QFont &font)
Sets the font used for labeling points.
Definition: qgspointdistancerenderer.h:137
qgspointdisplacementrenderer.h
qgsproperty.h
QgsPointDistanceRenderer::setMinimumLabelScale
void setMinimumLabelScale(double scale)
Sets the minimum map scale (i.e.
Definition: qgspointdistancerenderer.h:153
QgsPointDistanceRenderer::setTolerance
void setTolerance(double distance)
Sets the tolerance distance for grouping points.
Definition: qgspointdistancerenderer.h:187
QgsStyleEntityVisitorInterface::visit
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
Definition: qgsstyleentityvisitor.h:153
QgsMarkerSymbolLayer::setSize
virtual void setSize(double size)
Sets the symbol size.
Definition: qgssymbollayer.h:653
qgspointclusterrenderer.h
QgsPointClusterRenderer::setClusterSymbol
void setClusterSymbol(QgsMarkerSymbol *symbol)
Sets the symbol for rendering clustered groups.
Definition: qgspointclusterrenderer.cpp:182
QgsPointDistanceRenderer::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
Definition: qgspointdistancerenderer.cpp:304
QgsMarkerSymbol::renderPoint
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.
Definition: qgssymbol.cpp:1876
QgsSymbolLayerUtils::saveSymbol
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Definition: qgssymbollayerutils.cpp:1182
QgsSymbolLayerUtils::decodeMapUnitScale
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
Definition: qgssymbollayerutils.cpp:568
QgsPointDistanceRenderer::mTolerance
double mTolerance
Distance tolerance. Points that are closer together than this distance are considered clustered.
Definition: qgspointdistancerenderer.h:243
QgsSymbolLayer::setDataDefinedProperty
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
Definition: qgssymbollayer.cpp:113
qgsstyleentityvisitor.h
QgsPointDistanceRenderer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
Definition: qgspointdistancerenderer.cpp:218
QgsPointClusterRenderer::stopRender
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
Definition: qgspointclusterrenderer.cpp:88