1
0
mirror of https://github.com/qgis/QGIS.git synced 2025-04-27 00:03:38 -04:00

Fix crash in displacement/distance renderers

Individual symbol instances were being rendered multiple times
concurrently
This commit is contained in:
Nyall Dawson 2017-07-23 14:15:01 +10:00
parent b95d432a8c
commit 99bf32bafb
5 changed files with 43 additions and 36 deletions

@ -29,11 +29,11 @@ class QgsPointDistanceRenderer: QgsFeatureRenderer
struct GroupedFeature struct GroupedFeature
{ {
GroupedFeature( const QgsFeature &feature, QgsMarkerSymbol *symbol, bool isSelected, const QString &label = QString() ); GroupedFeature( const QgsFeature &feature, QgsMarkerSymbol *symbol /Transfer/, bool isSelected, const QString &label = QString() );
%Docstring %Docstring
Constructor for GroupedFeature. Constructor for GroupedFeature.
\param feature feature \param feature feature
\param symbol base symbol for rendering feature \param symbol base symbol for rendering feature (owned by GroupedFeature)
\param isSelected set to true if feature is selected and should be rendered in a selected state \param isSelected set to true if feature is selected and should be rendered in a selected state
\param label optional label text, or empty string for no label \param label optional label text, or empty string for no label
%End %End
@ -43,9 +43,10 @@ class QgsPointDistanceRenderer: QgsFeatureRenderer
Feature Feature
%End %End
QgsMarkerSymbol *symbol; QgsMarkerSymbol *symbol() const;
%Docstring %Docstring
Base symbol for rendering feature Base symbol for rendering feature
:rtype: QgsMarkerSymbol
%End %End
bool isSelected; bool isSelected;
@ -57,6 +58,7 @@ True if feature is selected and should be rendered in a selected state
%Docstring %Docstring
Optional label text Optional label text
%End %End
}; };
typedef QList< QgsPointDistanceRenderer::GroupedFeature > ClusteredGroup; typedef QList< QgsPointDistanceRenderer::GroupedFeature > ClusteredGroup;

@ -72,8 +72,10 @@ void QgsPointClusterRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &
else else
{ {
//single isolated symbol, draw it untouched //single isolated symbol, draw it untouched
QgsMarkerSymbol *symbol = group.at( 0 ).symbol; QgsMarkerSymbol *symbol = group.at( 0 ).symbol();
symbol->startRender( context );
symbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, group.at( 0 ).isSelected ); symbol->renderPoint( centerPoint, &( group.at( 0 ).feature ), context, -1, group.at( 0 ).isSelected );
symbol->stopRender( context );
} }
} }

@ -70,7 +70,7 @@ void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderCont
Q_FOREACH ( const GroupedFeature &feature, group ) Q_FOREACH ( const GroupedFeature &feature, group )
{ {
if ( QgsMarkerSymbol *symbol = feature.symbol ) if ( QgsMarkerSymbol *symbol = feature.symbol() )
{ {
diagonal = qMax( diagonal, context.convertToPainterUnits( M_SQRT2 * symbol->size(), diagonal = qMax( diagonal, context.convertToPainterUnits( M_SQRT2 * symbol->size(),
symbol->sizeUnit(), symbol->sizeMapUnitScale() ) ); symbol->sizeUnit(), symbol->sizeMapUnitScale() ) );
@ -327,9 +327,9 @@ void QgsPointDisplacementRenderer::drawSymbols( const ClusteredGroup &group, Qgs
++symbolPosIt, ++groupIt ) ++symbolPosIt, ++groupIt )
{ {
context.expressionContext().setFeature( groupIt->feature ); context.expressionContext().setFeature( groupIt->feature );
groupIt->symbol->startRender( context ); groupIt->symbol()->startRender( context );
groupIt->symbol->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected ); groupIt->symbol()->renderPoint( *symbolPosIt, &( groupIt->feature ), context, -1, groupIt->isSelected );
groupIt->symbol->stopRender( context ); groupIt->symbol()->stopRender( context );
} }
} }

@ -96,7 +96,7 @@ bool QgsPointDistanceRenderer::renderFeature( QgsFeature &feature, QgsRenderCont
mSpatialIndex->insertFeature( transformedFeature ); mSpatialIndex->insertFeature( transformedFeature );
// create new group // create new group
ClusteredGroup newGroup; ClusteredGroup newGroup;
newGroup << GroupedFeature( transformedFeature, symbol, selected, label ); newGroup << GroupedFeature( transformedFeature, symbol->clone(), selected, label );
mClusteredGroups.push_back( newGroup ); mClusteredGroups.push_back( newGroup );
// add to group index // add to group index
mGroupIndex.insert( transformedFeature.id(), mClusteredGroups.count() - 1 ); mGroupIndex.insert( transformedFeature.id(), mClusteredGroups.count() - 1 );
@ -127,7 +127,7 @@ bool QgsPointDistanceRenderer::renderFeature( QgsFeature &feature, QgsRenderCont
( oldCenter.y() * group.size() + point.y() ) / ( group.size() + 1.0 ) ); ( oldCenter.y() * group.size() + point.y() ) / ( group.size() + 1.0 ) );
// add to a group // add to a group
group << GroupedFeature( transformedFeature, symbol, selected, label ); group << GroupedFeature( transformedFeature, symbol->clone(), selected, label );
// add to group index // add to group index
mGroupIndex.insert( transformedFeature.id(), groupIdx ); mGroupIndex.insert( transformedFeature.id(), groupIdx );
} }
@ -425,16 +425,16 @@ QgsExpressionContextScope *QgsPointDistanceRenderer::createGroupScope( const Clu
ClusteredGroup::const_iterator groupIt = group.constBegin(); ClusteredGroup::const_iterator groupIt = group.constBegin();
for ( ; groupIt != group.constEnd(); ++groupIt ) for ( ; groupIt != group.constEnd(); ++groupIt )
{ {
if ( !groupIt->symbol ) if ( !groupIt->symbol() )
continue; continue;
if ( !groupColor.isValid() ) if ( !groupColor.isValid() )
{ {
groupColor = groupIt->symbol->color(); groupColor = groupIt->symbol()->color();
} }
else else
{ {
if ( groupColor != groupIt->symbol->color() ) if ( groupColor != groupIt->symbol()->color() )
{ {
groupColor = QColor(); groupColor = QColor();
break; break;

@ -44,28 +44,31 @@ class CORE_EXPORT QgsPointDistanceRenderer: public QgsFeatureRenderer
/** Constructor for GroupedFeature. /** Constructor for GroupedFeature.
* \param feature feature * \param feature feature
* \param symbol base symbol for rendering feature * \param symbol base symbol for rendering feature (owned by GroupedFeature)
* \param isSelected set to true if feature is selected and should be rendered in a selected state * \param isSelected set to true if feature is selected and should be rendered in a selected state
* \param label optional label text, or empty string for no label * \param label optional label text, or empty string for no label
*/ */
GroupedFeature( const QgsFeature &feature, QgsMarkerSymbol *symbol, bool isSelected, const QString &label = QString() ) GroupedFeature( const QgsFeature &feature, QgsMarkerSymbol *symbol SIP_TRANSFER, bool isSelected, const QString &label = QString() )
: feature( feature ) : feature( feature )
, symbol( symbol )
, isSelected( isSelected ) , isSelected( isSelected )
, label( label ) , label( label )
, mSymbol( symbol )
{} {}
//! Feature //! Feature
QgsFeature feature; QgsFeature feature;
//! Base symbol for rendering feature //! Base symbol for rendering feature
QgsMarkerSymbol *symbol = nullptr; QgsMarkerSymbol *symbol() const { return mSymbol.get(); }
//! True if feature is selected and should be rendered in a selected state //! True if feature is selected and should be rendered in a selected state
bool isSelected; bool isSelected;
//! Optional label text //! Optional label text
QString label; QString label;
private:
std::shared_ptr< QgsMarkerSymbol > mSymbol;
}; };
//! A group of clustered points (ie features within the distance tolerance). //! A group of clustered points (ie features within the distance tolerance).