void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group )
{

  //calculate max diagonal size from all symbols in group
  double diagonal = 0;

  for ( const GroupedFeature &feature : group )
  {
    if ( QgsMarkerSymbol *symbol = feature.symbol() )
    {
      diagonal = std::max( diagonal, M_SQRT2 * symbol->size( context ) );
    }
  }

  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false );

  QList<QPointF> symbolPositions;
  QList<QPointF> labelPositions;
  double circleRadius = -1.0;
  double gridRadius = -1.0;
  int gridSize = -1;

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

  //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids
  if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 )
  {
    //draw circle
    if ( circleRadius > 0 )
      drawCircle( circleRadius, symbolContext, centerPoint, group.size() );
    //draw grid
    else
      drawGrid( gridSize, symbolContext, symbolPositions, group.size() );
  }

  if ( group.size() > 1 )
  {
    //draw mid point
    QgsFeature firstFeature = group.at( 0 ).feature;
    if ( mCenterSymbol )
    {
      mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
    }
    else
    {
      context.painter()->drawRect( QRectF( centerPoint.x() - symbolContext.outputLineWidth( 1 ), centerPoint.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
    }
  }

  //draw symbols on the circle
  drawSymbols( group, context, symbolPositions );
  //and also the labels
  if ( mLabelIndex >= 0 )
  {
    drawLabels( centerPoint, symbolContext, labelPositions, group );
  }
}
void QgsPointClusterRenderer::drawGroup( QPointF centerPoint, QgsRenderContext& context, const ClusteredGroup& group )
{
  if ( group.size() > 1 )
  {
    mClusterSymbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, false );
  }
  else
  {
    //single isolated symbol, draw it untouched
    QgsMarkerSymbol* symbol = group.at( 0 ).symbol;
    symbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, group.at( 0 ).isSelected );
  }
}
void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions )
{
  QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
  ClusteredGroup::const_iterator groupIt = group.constBegin();
  for ( ; symbolPosIt != symbolPositions.constEnd() && groupIt != group.constEnd();
        ++symbolPosIt, ++groupIt )
  {
    context.expressionContext().setFeature( groupIt->feature );
    groupIt->symbol()->startRender( context );
    groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
    groupIt->symbol()->stopRender( context );
  }
}
void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext& context, const ClusteredGroup& group )
{

  //calculate max diagonal size from all symbols in group
  double diagonal = 0;

  Q_FOREACH ( const GroupedFeature& feature, group )
  {
    if ( QgsMarkerSymbol* symbol = feature.symbol )
    {
      diagonal = qMax( diagonal, context.convertToPainterUnits( M_SQRT2 * symbol->size(),
                       symbol->sizeUnit(), symbol->sizeMapUnitScale() ) );
    }
  }

  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false );

  QList<QPointF> symbolPositions;
  QList<QPointF> labelPositions;
  double circleRadius = -1.0;
  calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius );

  //draw circle
  if ( circleRadius > 0 )
    drawCircle( circleRadius, symbolContext, centerPoint, group.size() );

  if ( group.size() > 1 )
  {
    //draw mid point
    QgsFeature firstFeature = group.at( 0 ).feature;
    if ( mCenterSymbol )
    {
      mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false );
    }
    else
    {
      context.painter()->drawRect( QRectF( centerPoint.x() - symbolContext.outputLineWidth( 1 ), centerPoint.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
    }
  }

  //draw symbols on the circle
  drawSymbols( group, context, symbolPositions );
  //and also the labels
  if ( mLabelIndex >= 0 )
  {
    drawLabels( centerPoint, symbolContext, labelPositions, group );
  }
}