Skip to content

Commit 1725182

Browse files
committed
Make @cluster_size, @cluster_color usable in displacement renderer too
1 parent 7acb07f commit 1725182

6 files changed

+91
-37
lines changed

src/core/symbology-ng/qgspointclusterrenderer.cpp

-34
Original file line numberDiff line numberDiff line change
@@ -55,40 +55,6 @@ void QgsPointClusterRenderer::drawGroup( QPointF centerPoint, QgsRenderContext&
5555
{
5656
if ( group.size() > 1 )
5757
{
58-
//scan through symbols to check color, eg if all clustered symbols are same color
59-
QColor groupColor;
60-
ClusteredGroup::const_iterator groupIt = group.constBegin();
61-
for ( ; groupIt != group.constEnd(); ++groupIt )
62-
{
63-
if ( !groupIt->symbol )
64-
continue;
65-
66-
if ( !groupColor.isValid() )
67-
{
68-
groupColor = groupIt->symbol->color();
69-
}
70-
else
71-
{
72-
if ( groupColor != groupIt->symbol->color() )
73-
{
74-
groupColor = QColor();
75-
break;
76-
}
77-
}
78-
}
79-
80-
if ( groupColor.isValid() )
81-
{
82-
context.expressionContext().lastScope()->setVariable( "cluster_color", QgsSymbolLayerUtils::encodeColor( groupColor ) );
83-
}
84-
else
85-
{
86-
//mixed colors
87-
context.expressionContext().lastScope()->setVariable( "cluster_color", "" );
88-
}
89-
90-
//multiple clustered symbols, so draw just the cluster symbol
91-
context.expressionContext().lastScope()->setVariable( "cluster_size", group.size() );
9258
mClusterSymbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, false );
9359
}
9460
else

src/core/symbology-ng/qgspointdisplacementrenderer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ QgsPointDisplacementRenderer* QgsPointDisplacementRenderer::clone() const
6464

6565
void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext& context, const ClusteredGroup& group )
6666
{
67+
6768
//calculate max diagonal size from all symbols in group
6869
double diagonal = 0;
6970

@@ -88,9 +89,9 @@ void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderCont
8889
if ( circleRadius > 0 )
8990
drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
9091

91-
//draw mid point
9292
if ( group.size() > 1 )
9393
{
94+
//draw mid point
9495
QgsFeature firstFeature = group.at( 0 ).feature;
9596
if ( mCenterSymbol )
9697
{

src/core/symbology-ng/qgspointdistancerenderer.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ void QgsPointDistanceRenderer::drawGroup( const ClusteredGroup& group, QgsRender
140140
QgsGeometry centroid = groupGeom.centroid();
141141
QPointF pt = _getPoint( context, *static_cast<QgsPointV2*>( centroid.geometry() ) );
142142

143+
context.expressionContext().appendScope( createGroupScope( group ) );
143144
drawGroup( pt, context, group );
145+
delete context.expressionContext().popScope();
144146
}
145147

146148
void QgsPointDistanceRenderer::setEmbeddedRenderer( QgsFeatureRenderer* r )
@@ -407,6 +409,48 @@ void QgsPointDistanceRenderer::drawLabels( QPointF centerPoint, QgsSymbolRenderC
407409
}
408410
}
409411

412+
QgsExpressionContextScope* QgsPointDistanceRenderer::createGroupScope( const ClusteredGroup& group ) const
413+
{
414+
QgsExpressionContextScope* clusterScope = new QgsExpressionContextScope();
415+
if ( group.size() > 1 )
416+
{
417+
//scan through symbols to check color, eg if all clustered symbols are same color
418+
QColor groupColor;
419+
ClusteredGroup::const_iterator groupIt = group.constBegin();
420+
for ( ; groupIt != group.constEnd(); ++groupIt )
421+
{
422+
if ( !groupIt->symbol )
423+
continue;
424+
425+
if ( !groupColor.isValid() )
426+
{
427+
groupColor = groupIt->symbol->color();
428+
}
429+
else
430+
{
431+
if ( groupColor != groupIt->symbol->color() )
432+
{
433+
groupColor = QColor();
434+
break;
435+
}
436+
}
437+
}
438+
439+
if ( groupColor.isValid() )
440+
{
441+
clusterScope->setVariable( "cluster_color", QgsSymbolLayerUtils::encodeColor( groupColor ) );
442+
}
443+
else
444+
{
445+
//mixed colors
446+
clusterScope->setVariable( "cluster_color", "" );
447+
}
448+
449+
clusterScope->setVariable( "cluster_size", group.size() );
450+
}
451+
return clusterScope;
452+
}
453+
410454
QgsMarkerSymbol* QgsPointDistanceRenderer::firstSymbolForFeature( QgsFeature& feature, QgsRenderContext &context )
411455
{
412456
if ( !mRenderer )

src/core/symbology-ng/qgspointdistancerenderer.h

+6
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,12 @@ class CORE_EXPORT QgsPointDistanceRenderer: public QgsFeatureRenderer
276276
*/
277277
QgsMarkerSymbol* firstSymbolForFeature( QgsFeature& feature, QgsRenderContext& context );
278278

279+
/** Creates an expression context scope for a clustered group, with variables reflecting the group's properties.
280+
* @param group clustered group
281+
* @returns new expression context scope
282+
*/
283+
QgsExpressionContextScope* createGroupScope( const ClusteredGroup& group ) const;
284+
279285
};
280286

281287
#endif // QGSPOINTDISTANCERENDERER_H

tests/src/python/test_qgspointclusterrenderer.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
QgsMarkerSymbol,
4141
QgsSingleSymbolRenderer,
4242
QgsPointDisplacementRenderer,
43-
QgsMapSettings
43+
QgsMapSettings,
44+
QgsDataDefined
4445
)
4546
from qgis.testing import start_app, unittest
4647
from utilities import (unitTestDataPath)
@@ -162,6 +163,24 @@ def testRenderWithin(self):
162163
renderchecker.setControlName('expected_cluster_cluster')
163164
self.assertTrue(renderchecker.runTest('expected_cluster_cluster'))
164165

166+
def testRenderVariables(self):
167+
""" test rendering with expression variables in marker """
168+
self.layer.renderer().setTolerance(10)
169+
170+
old_marker = self.layer.renderer().clusterSymbol().clone()
171+
172+
new_marker = QgsMarkerSymbol.createSimple({'color': '#ffff00', 'size': '3', 'outline_style': 'no'})
173+
new_marker.symbolLayer(0).setDataDefinedProperty('color', QgsDataDefined('@cluster_color'))
174+
new_marker.symbolLayer(0).setDataDefinedProperty('size', QgsDataDefined('@cluster_size*2'))
175+
self.layer.renderer().setClusterSymbol(new_marker)
176+
renderchecker = QgsMultiRenderChecker()
177+
renderchecker.setMapSettings(self.mapsettings)
178+
renderchecker.setControlPathPrefix('cluster_renderer')
179+
renderchecker.setControlName('expected_cluster_variables')
180+
result = renderchecker.runTest('expected_cluster_variables')
181+
self.layer.renderer().setClusterSymbol(old_marker)
182+
self.assertTrue(result)
183+
165184

166185
if __name__ == '__main__':
167186
unittest.main()

tests/src/python/test_qgspointdisplacementrenderer.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
QgsMarkerSymbol,
4343
QgsSingleSymbolRenderer,
4444
QgsPointClusterRenderer,
45-
QgsMapSettings
45+
QgsMapSettings,
46+
QgsDataDefined
4647
)
4748
from qgis.testing import start_app, unittest
4849
from utilities import (unitTestDataPath)
@@ -185,6 +186,23 @@ def testRenderWithin(self):
185186
renderchecker.setControlName('expected_displacement_cluster')
186187
self.assertTrue(renderchecker.runTest('expected_displacement_cluster'))
187188

189+
def testRenderVariables(self):
190+
""" test rendering with expression variables in marker """
191+
self.layer.renderer().setTolerance(10)
192+
193+
old_marker = self.layer.renderer().centerSymbol().clone()
194+
195+
new_marker = QgsMarkerSymbol.createSimple({'color': '#ffff00', 'size': '3', 'outline_style': 'no'})
196+
new_marker.symbolLayer(0).setDataDefinedProperty('color', QgsDataDefined('@cluster_color'))
197+
new_marker.symbolLayer(0).setDataDefinedProperty('size', QgsDataDefined('@cluster_size*2'))
198+
self.layer.renderer().setCenterSymbol(new_marker)
199+
renderchecker = QgsMultiRenderChecker()
200+
renderchecker.setMapSettings(self.mapsettings)
201+
renderchecker.setControlPathPrefix('displacement_renderer')
202+
renderchecker.setControlName('expected_displacement_variables')
203+
result = renderchecker.runTest('expected_displacement_variables')
204+
self.layer.renderer().setCenterSymbol(old_marker)
205+
self.assertTrue(result)
188206

189207
if __name__ == '__main__':
190208
unittest.main()

0 commit comments

Comments
 (0)