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

This commit is contained in:
Nyall Dawson 2016-04-29 17:36:52 +10:00
parent d20a2ced9d
commit a67853f825
11 changed files with 76 additions and 11 deletions

View File

@ -494,11 +494,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/;
};

View File

@ -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 );
}
}

View File

@ -767,7 +767,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 ) );
}
if ( drawVertexMarker )
@ -1479,9 +1479,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 )

View File

@ -565,10 +565,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;

View File

@ -63,6 +63,9 @@ class TestQgsSimpleMarkerSymbol : public QObject
void simpleMarkerSymbolMiterJoin();
void simpleMarkerSymbolRoundJoin();
void bounds();
void boundsWithOffset();
void boundsWithRotation();
void boundsWithRotationAndOffset();
private:
bool mTestHasError;
@ -194,6 +197,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.

After

Width:  |  Height:  |  Size: 11 KiB