Skip to content

Commit ff2ade9

Browse files
myarjunarnyalldawson
authored andcommitted
[FEATURE] add grid renderer for points displacement. funded by Kartoza
1 parent 0a615b6 commit ff2ade9

5 files changed

+89
-6
lines changed

python/core/symbology/qgspointdisplacementrenderer.sip

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ class QgsPointDisplacementRenderer: QgsPointDistanceRenderer
2323
enum Placement
2424
{
2525
Ring,
26-
ConcentricRings
26+
ConcentricRings,
27+
Grid
2728
};
2829

2930
QgsPointDisplacementRenderer( const QString &labelAttributeName = QString() );

src/core/symbology/qgspointdisplacementrenderer.cpp

+78-2
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,17 @@ void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderCont
7575
QList<QPointF> symbolPositions;
7676
QList<QPointF> labelPositions;
7777
double circleRadius = -1.0;
78-
calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius );
78+
double gridRadius;
79+
int gridSize;
80+
81+
calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize );
7982

8083
//draw circle
8184
if ( circleRadius > 0 )
8285
drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
86+
//draw grid
87+
else
88+
drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
8389

8490
if ( group.size() > 1 )
8591
{
@@ -221,7 +227,8 @@ void QgsPointDisplacementRenderer::setCenterSymbol( QgsMarkerSymbol *symbol )
221227
}
222228

223229
void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition,
224-
double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius ) const
230+
double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, double &gridRadius,
231+
int &gridSize ) const
225232
{
226233
symbolPositions.clear();
227234
labelShifts.clear();
@@ -294,6 +301,75 @@ void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRe
294301
}
295302
break;
296303
}
304+
case Grid:
305+
{
306+
double centerDiagonal = symbolContext.renderContext().convertToPainterUnits( M_SQRT2 * mCenterSymbol->size(),
307+
mCenterSymbol->sizeUnit(), mCenterSymbol->sizeMapUnitScale() );
308+
int pointsRemaining = nPosition;
309+
gridSize = ceil( sqrt( pointsRemaining ) );
310+
if ( pointsRemaining - pow( gridSize - 1, 2 ) < gridSize )
311+
gridSize -= 1;
312+
double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
313+
double userPointRadius = originalPointRadius + circleAdditionPainterUnits;
314+
315+
int yIndex = 0;
316+
while ( pointsRemaining > 0 )
317+
{
318+
for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
319+
{
320+
QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
321+
QPointF labelShift( ( userPointRadius + symbolDiagonal / 2 ) * xIndex, ( userPointRadius + symbolDiagonal / 2 ) * yIndex );
322+
symbolPositions.append( centerPoint + positionShift );
323+
labelShifts.append( labelShift );
324+
pointsRemaining--;
325+
}
326+
yIndex++;
327+
}
328+
329+
centralizeGrid( symbolPositions, userPointRadius, gridSize );
330+
centralizeGrid( labelShifts, userPointRadius, gridSize );
331+
gridRadius = userPointRadius;
332+
break;
333+
}
334+
}
335+
}
336+
337+
void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
338+
{
339+
double shiftAmount = -radius * ( size - 1 ) / 2;
340+
QPointF centralShift( shiftAmount, shiftAmount );
341+
for ( int i = 0; i < pointSymbolPositions.size(); ++i )
342+
{
343+
pointSymbolPositions[i] += centralShift;
344+
}
345+
}
346+
347+
void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
348+
QList<QPointF> pointSymbolPositions, int nSymbols )
349+
{
350+
QPainter *p = context.renderContext().painter();
351+
if ( nSymbols < 2 || !p ) //draw grid only if multiple features
352+
{
353+
return;
354+
}
355+
356+
QPen gridPen( mCircleColor );
357+
gridPen.setWidthF( context.outputLineWidth( mCircleWidth ) );
358+
p->setPen( gridPen );
359+
360+
for ( int i = 0; i < pointSymbolPositions.size(); ++i )
361+
{
362+
if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
363+
{
364+
QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
365+
p->drawLine( gridLineRow );
366+
}
367+
368+
if ( i + gridSizeUnits < pointSymbolPositions.size() )
369+
{
370+
QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
371+
p->drawLine( gridLineColumn );
372+
}
297373
}
298374
}
299375

src/core/symbology/qgspointdisplacementrenderer.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsPointDistanceRenderer
3737
enum Placement
3838
{
3939
Ring, //!< Place points in a single ring around group
40-
ConcentricRings //!< Place points in concentric rings around group
40+
ConcentricRings, //!< Place points in concentric rings around group
41+
Grid //!< Place points in a grid around group
4142
};
4243

4344
/**
@@ -155,9 +156,13 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsPointDistanceRenderer
155156
virtual void drawGroup( QPointF centerPoint, QgsRenderContext &context, const QgsPointDistanceRenderer::ClusteredGroup &group ) override SIP_FORCE;
156157

157158
//helper functions
158-
void calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition, double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius ) const;
159+
void calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition, double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius,
160+
double &gridRadius, int &gridSize ) const;
159161
void drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols );
160162
void drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions );
163+
void drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
164+
QList<QPointF> pointSymbolPositions, int nSymbols );
165+
void centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const;
161166
};
162167

163168
#endif // QGSPOINTDISPLACEMENTRENDERER_H

src/gui/symbology/qgspointdisplacementrendererwidget.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
7979

8080
mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
8181
mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
82+
mPlacementComboBox->addItem( tr( "Grid" ), QgsPointDisplacementRenderer::Grid );
8283

8384
//insert attributes into combo box
8485
if ( layer )

src/ui/qgspointdisplacementrendererwidgetbase.ui

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@
215215
<item row="3" column="0">
216216
<widget class="QLabel" name="mCircleRadiusLabel">
217217
<property name="text">
218-
<string>Ring size adjustment</string>
218+
<string>Size adjustment</string>
219219
</property>
220220
</widget>
221221
</item>

0 commit comments

Comments
 (0)