Skip to content

Commit

Permalink
[FEATURE] add grid renderer for points displacement. funded by Kartoza
Browse files Browse the repository at this point in the history
  • Loading branch information
myarjunar authored and nyalldawson committed Oct 26, 2017
1 parent 0a615b6 commit ff2ade9
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 6 deletions.
3 changes: 2 additions & 1 deletion python/core/symbology/qgspointdisplacementrenderer.sip
Expand Up @@ -23,7 +23,8 @@ class QgsPointDisplacementRenderer: QgsPointDistanceRenderer
enum Placement
{
Ring,
ConcentricRings
ConcentricRings,
Grid
};

QgsPointDisplacementRenderer( const QString &labelAttributeName = QString() );
Expand Down
80 changes: 78 additions & 2 deletions src/core/symbology/qgspointdisplacementrenderer.cpp
Expand Up @@ -75,11 +75,17 @@ void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderCont
QList<QPointF> symbolPositions;
QList<QPointF> labelPositions;
double circleRadius = -1.0;
calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius );
double gridRadius;
int gridSize;

calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize );

//draw circle
if ( circleRadius > 0 )
drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
//draw grid
else
drawGrid( gridSize, symbolContext, symbolPositions, group.size() );

if ( group.size() > 1 )
{
Expand Down Expand Up @@ -221,7 +227,8 @@ void QgsPointDisplacementRenderer::setCenterSymbol( QgsMarkerSymbol *symbol )
}

void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition,
double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius ) const
double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, double &gridRadius,
int &gridSize ) const
{
symbolPositions.clear();
labelShifts.clear();
Expand Down Expand Up @@ -294,6 +301,75 @@ void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRe
}
break;
}
case Grid:
{
double centerDiagonal = symbolContext.renderContext().convertToPainterUnits( M_SQRT2 * mCenterSymbol->size(),
mCenterSymbol->sizeUnit(), mCenterSymbol->sizeMapUnitScale() );
int pointsRemaining = nPosition;
gridSize = ceil( sqrt( pointsRemaining ) );
if ( pointsRemaining - pow( gridSize - 1, 2 ) < gridSize )
gridSize -= 1;
double originalPointRadius = ( ( centerDiagonal / 2.0 + symbolDiagonal / 2.0 ) + symbolDiagonal ) / 2;
double userPointRadius = originalPointRadius + circleAdditionPainterUnits;

int yIndex = 0;
while ( pointsRemaining > 0 )
{
for ( int xIndex = 0; xIndex < gridSize && pointsRemaining > 0; ++xIndex )
{
QPointF positionShift( userPointRadius * xIndex, userPointRadius * yIndex );
QPointF labelShift( ( userPointRadius + symbolDiagonal / 2 ) * xIndex, ( userPointRadius + symbolDiagonal / 2 ) * yIndex );
symbolPositions.append( centerPoint + positionShift );
labelShifts.append( labelShift );
pointsRemaining--;
}
yIndex++;
}

centralizeGrid( symbolPositions, userPointRadius, gridSize );
centralizeGrid( labelShifts, userPointRadius, gridSize );
gridRadius = userPointRadius;
break;
}
}
}

void QgsPointDisplacementRenderer::centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const
{
double shiftAmount = -radius * ( size - 1 ) / 2;
QPointF centralShift( shiftAmount, shiftAmount );
for ( int i = 0; i < pointSymbolPositions.size(); ++i )
{
pointSymbolPositions[i] += centralShift;
}
}

void QgsPointDisplacementRenderer::drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
QList<QPointF> pointSymbolPositions, int nSymbols )
{
QPainter *p = context.renderContext().painter();
if ( nSymbols < 2 || !p ) //draw grid only if multiple features
{
return;
}

QPen gridPen( mCircleColor );
gridPen.setWidthF( context.outputLineWidth( mCircleWidth ) );
p->setPen( gridPen );

for ( int i = 0; i < pointSymbolPositions.size(); ++i )
{
if ( i + 1 < pointSymbolPositions.size() && 0 != ( i + 1 ) % gridSizeUnits )
{
QLineF gridLineRow( pointSymbolPositions[i], pointSymbolPositions[i + 1] );
p->drawLine( gridLineRow );
}

if ( i + gridSizeUnits < pointSymbolPositions.size() )
{
QLineF gridLineColumn( pointSymbolPositions[i], pointSymbolPositions[i + gridSizeUnits] );
p->drawLine( gridLineColumn );
}
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/core/symbology/qgspointdisplacementrenderer.h
Expand Up @@ -37,7 +37,8 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsPointDistanceRenderer
enum Placement
{
Ring, //!< Place points in a single ring around group
ConcentricRings //!< Place points in concentric rings around group
ConcentricRings, //!< Place points in concentric rings around group
Grid //!< Place points in a grid around group
};

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

//helper functions
void calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition, double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius ) const;
void calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition, double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius,
double &gridRadius, int &gridSize ) const;
void drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols );
void drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions );
void drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context,
QList<QPointF> pointSymbolPositions, int nSymbols );
void centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const;
};

#endif // QGSPOINTDISPLACEMENTRENDERER_H
1 change: 1 addition & 0 deletions src/gui/symbology/qgspointdisplacementrendererwidget.cpp
Expand Up @@ -79,6 +79,7 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto

mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
mPlacementComboBox->addItem( tr( "Grid" ), QgsPointDisplacementRenderer::Grid );

//insert attributes into combo box
if ( layer )
Expand Down
2 changes: 1 addition & 1 deletion src/ui/qgspointdisplacementrendererwidgetbase.ui
Expand Up @@ -215,7 +215,7 @@
<item row="3" column="0">
<widget class="QLabel" name="mCircleRadiusLabel">
<property name="text">
<string>Ring size adjustment</string>
<string>Size adjustment</string>
</property>
</widget>
</item>
Expand Down

0 comments on commit ff2ade9

Please sign in to comment.