Skip to content
Permalink
Browse files

Fix calculation of point symbol bounds using data defined rotation or…

… offset

(cherry-picked from a67853f)
  • Loading branch information
nyalldawson committed Apr 29, 2016
1 parent 80102b1 commit c230c23cda03ee386ba63da99fe4f1a81ab7bc96
@@ -476,11 +476,16 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
void renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layer = -1, bool selected = false );

/** Returns the approximate bounding box of the marker symbol, which includes the bounding box
* of all symbol layers for the symbol.
* of all symbol layers for the symbol. It is recommended to use this method only between startRender()
* and stopRender() calls, or data defined rotation and offset will not be correctly calculated.
* @param point location of rendered point in painter units
* @param context render context
* @param feature feature being rendered at point (optional). If not specified, the bounds calculation will not
* include data defined parameters such as offset and rotation
* @returns approximate symbol bounds, in painter units
* @note added in QGIS 2.14
*/
QRectF bounds( QPointF point, QgsRenderContext& context ) const;
*/
QRectF bounds(QPointF point, QgsRenderContext& context, const QgsFeature &feature = QgsFeature() ) const;

virtual QgsMarkerSymbolV2* clone() const /Factory/;
};
@@ -353,9 +353,9 @@ QgsGeometry* QgsVectorLayerLabelProvider::getPointObstacleGeometry( QgsFeature&
if ( symbol->type() == QgsSymbolV2::Marker )
{
if ( bounds.isValid() )
bounds = bounds.united( static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context ) );
bounds = bounds.united( static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context, fet ) );
else
bounds = static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context );
bounds = static_cast< QgsMarkerSymbolV2* >( symbol )->bounds( pt, context, fet );
}
}

@@ -758,7 +758,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
//draw debugging rect
context.painter()->setPen( Qt::red );
context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context ) );
context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context, feature ) );
}
}
break;
@@ -1422,9 +1422,9 @@ void QgsMarkerSymbolV2::renderPoint( QPointF point, const QgsFeature* f, QgsRend
}
}

QRectF QgsMarkerSymbolV2::bounds( QPointF point, QgsRenderContext& context ) const
QRectF QgsMarkerSymbolV2::bounds( QPointF point, QgsRenderContext& context, const QgsFeature& feature ) const
{
QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, nullptr, mapUnitScale() );
QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, &feature, feature.fields(), mapUnitScale() );

QRectF bound;
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
@@ -545,10 +545,16 @@ class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
void renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layer = -1, bool selected = false );

/** Returns the approximate bounding box of the marker symbol, which includes the bounding box
* of all symbol layers for the symbol.
* of all symbol layers for the symbol. It is recommended to use this method only between startRender()
* and stopRender() calls, or data defined rotation and offset will not be correctly calculated.
* @param point location of rendered point in painter units
* @param context render context
* @param feature feature being rendered at point (optional). If not specified, the bounds calculation will not
* include data defined parameters such as offset and rotation
* @returns approximate symbol bounds, in painter units
* @note added in QGIS 2.14 */
QRectF bounds( QPointF point, QgsRenderContext& context ) const;
* @note added in QGIS 2.14
*/
QRectF bounds( QPointF point, QgsRenderContext& context, const QgsFeature &feature = QgsFeature() ) const;

virtual QgsMarkerSymbolV2* clone() const override;

@@ -60,6 +60,9 @@ class TestQgsSimpleMarkerSymbol : public QObject

void simpleMarkerSymbol();
void bounds();
void boundsWithOffset();
void boundsWithRotation();
void boundsWithRotationAndOffset();

private:
bool mTestHasError;
@@ -152,6 +155,57 @@ void TestQgsSimpleMarkerSymbol::bounds()
mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
bool result = imageCheck( "simplemarker_bounds" );
mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
mSimpleMarkerLayer->removeDataDefinedProperty( "size" );
QVERIFY( result );
}

void TestQgsSimpleMarkerSymbol::boundsWithOffset()
{
mSimpleMarkerLayer->setColor( QColor( 200, 200, 200 ) );
mSimpleMarkerLayer->setBorderColor( QColor( 0, 0, 0 ) );
mSimpleMarkerLayer->setName( "circle" );
mSimpleMarkerLayer->setSize( 5 );
mSimpleMarkerLayer->setDataDefinedProperty( "offset", new QgsDataDefined( true, true, "if(importance > 2, '5,10', '10, 5')" ) );
mSimpleMarkerLayer->setOutlineWidth( 0.5 );

mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
bool result = imageCheck( "simplemarker_boundsoffset" );
mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
mSimpleMarkerLayer->removeDataDefinedProperty( "offset" );
QVERIFY( result );
}

void TestQgsSimpleMarkerSymbol::boundsWithRotation()
{
mSimpleMarkerLayer->setColor( QColor( 200, 200, 200 ) );
mSimpleMarkerLayer->setBorderColor( QColor( 0, 0, 0 ) );
mSimpleMarkerLayer->setName( "square" );
mSimpleMarkerLayer->setSize( 5 );
mSimpleMarkerLayer->setDataDefinedProperty( "angle", new QgsDataDefined( true, true, "importance * 20" ) );
mSimpleMarkerLayer->setOutlineWidth( 0.5 );

mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
bool result = imageCheck( "simplemarker_boundsrotation" );
mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
mSimpleMarkerLayer->removeDataDefinedProperty( "angle" );
QVERIFY( result );
}

void TestQgsSimpleMarkerSymbol::boundsWithRotationAndOffset()
{
mSimpleMarkerLayer->setColor( QColor( 200, 200, 200 ) );
mSimpleMarkerLayer->setBorderColor( QColor( 0, 0, 0 ) );
mSimpleMarkerLayer->setName( "square" );
mSimpleMarkerLayer->setSize( 5 );
mSimpleMarkerLayer->setDataDefinedProperty( "offset", new QgsDataDefined( true, true, "if(importance > 2, '5,10', '10, 5')" ) );
mSimpleMarkerLayer->setDataDefinedProperty( "angle", new QgsDataDefined( true, false, QString(), "heading" ) );
mSimpleMarkerLayer->setOutlineWidth( 0.5 );

mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, true );
bool result = imageCheck( "simplemarker_boundsrotationoffset" );
mMapSettings.setFlag( QgsMapSettings::DrawSymbolBounds, false );
mSimpleMarkerLayer->removeDataDefinedProperty( "offset" );
mSimpleMarkerLayer->removeDataDefinedProperty( "angle" );
QVERIFY( result );
}

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit c230c23

Please sign in to comment.
You can’t perform that action at this time.