Skip to content

Commit 55ead85

Browse files
committed
Allow setting label obstacle geom in QgsPalLabeling::registerFeature
Sponsored by City of Uster
1 parent 9cc10e2 commit 55ead85

File tree

3 files changed

+66
-20
lines changed

3 files changed

+66
-20
lines changed

python/core/qgspallabeling.sip

+7
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,13 @@ class QgsPalLayerSettings
492492
* @param context render context. The QgsExpressionContext contained within the render context
493493
* must have already had the feature and fields sets prior to calling this method.
494494
* @param dxfLayer dxfLayer name
495+
* @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature. Not available
496+
* in Python bindings.
497+
* @param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
498+
* should be used as an obstacle for labels (eg, if the feature has been rendered with an offset point
499+
* symbol, the obstacle geometry should represent the bounds of the offset symbol). If not set,
500+
* the feature's original geometry will be used as an obstacle for labels. Not available
501+
* in Python bindings.
495502
*/
496503
void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer );
497504

src/core/qgspallabeling.cpp

+50-17
Original file line numberDiff line numberDiff line change
@@ -1896,25 +1896,32 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t
18961896
#endif
18971897
}
18981898

1899-
1900-
void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** labelFeature )
1899+
void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** labelFeature , QgsGeometry* obstacleGeometry )
19011900
{
19021901
// either used in QgsPalLabeling (palLayer is set) or in QgsLabelingEngineV2 (labelFeature is set)
19031902
Q_ASSERT( labelFeature );
19041903

19051904
Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider
19061905

1906+
QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful
1907+
mCurFeat = &f;
1908+
1909+
// data defined is obstacle? calculate this first, to avoid wasting time working with obstacles we don't require
1910+
bool isObstacle = obstacle; // start with layer default
1911+
if ( dataDefinedEvaluate( QgsPalLayerSettings::IsObstacle, exprVal, &context.expressionContext(), obstacle ) )
1912+
{
1913+
isObstacle = exprVal.toBool();
1914+
}
1915+
19071916
if ( !drawLabels )
19081917
{
1909-
if ( obstacle )
1918+
if ( isObstacle )
19101919
{
1911-
registerObstacleFeature( f, context, QString(), labelFeature );
1920+
registerObstacleFeature( f, context, QString(), labelFeature, obstacleGeometry );
19121921
}
19131922
return;
19141923
}
19151924

1916-
QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful
1917-
mCurFeat = &f;
19181925
// mCurFields = &layer->pendingFields();
19191926

19201927
// store data defined-derived values for later adding to label feature for use during rendering
@@ -2237,7 +2244,6 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
22372244
const GEOSGeometry* geos_geom = 0;
22382245
const QgsGeometry* preparedGeom = geom;
22392246
QScopedPointer<QgsGeometry> scopedPreparedGeom;
2240-
22412247
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, ct, doClip ? extentGeom : 0 ) )
22422248
{
22432249
scopedPreparedGeom.reset( QgsPalLabeling::prepareGeometry( geom, context, ct, doClip ? extentGeom : 0 ) );
@@ -2250,6 +2256,22 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
22502256
{
22512257
geos_geom = geom->asGeos();
22522258
}
2259+
const GEOSGeometry* geosObstacleGeom = 0;
2260+
const QgsGeometry* preparedObstacleGeom = obstacleGeometry;
2261+
QScopedPointer<QgsGeometry> scopedObstacleGeom;
2262+
if ( isObstacle )
2263+
{
2264+
if ( obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( obstacleGeometry, context, ct, doClip ? extentGeom : 0 ) )
2265+
{
2266+
scopedObstacleGeom.reset( QgsPalLabeling::prepareGeometry( obstacleGeometry, context, ct, doClip ? extentGeom : 0 ) );
2267+
preparedObstacleGeom = scopedObstacleGeom.data();
2268+
geosObstacleGeom = scopedObstacleGeom.data()->asGeos();
2269+
}
2270+
else if ( obstacleGeometry )
2271+
{
2272+
geosObstacleGeom = obstacleGeometry->asGeos();
2273+
}
2274+
}
22532275

22542276
if ( minFeatureSize > 0 && !checkMinimumSizeMM( context, preparedGeom, minFeatureSize ) )
22552277
return;
@@ -2291,6 +2313,12 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
22912313
{
22922314
geos_geom_clone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
22932315
}
2316+
GEOSGeometry* geosObstacleGeomClone = 0;
2317+
if ( geosObstacleGeom )
2318+
{
2319+
geosObstacleGeomClone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geosObstacleGeom );
2320+
}
2321+
22942322

22952323
//data defined position / alignment / rotation?
22962324
bool dataDefinedPosition = false;
@@ -2610,6 +2638,10 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
26102638
( *labelFeature )->setAlwaysShow( alwaysShow );
26112639
( *labelFeature )->setRepeatDistance( repeatDist );
26122640
( *labelFeature )->setLabelText( labelText );
2641+
if ( geosObstacleGeomClone )
2642+
{
2643+
( *labelFeature )->setObstacleGeometry( geosObstacleGeomClone );
2644+
}
26132645

26142646
// store the label's calculated font for later use during painting
26152647
QgsDebugMsgLevel( QString( "PAL font stored definedFont: %1, Style: %2" ).arg( labelFont.toString(), labelFont.styleName() ), 4 );
@@ -2678,13 +2710,6 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
26782710
}
26792711
}
26802712

2681-
// data defined is obstacle?
2682-
bool isObstacle = obstacle; // start with layer default
2683-
if ( dataDefinedEvaluate( QgsPalLayerSettings::IsObstacle, exprVal, &context.expressionContext(), obstacle ) )
2684-
{
2685-
isObstacle = exprVal.toBool();
2686-
}
2687-
26882713
( *labelFeature )->setIsObstacle( isObstacle );
26892714

26902715
double featObstacleFactor = obstacleFactor;
@@ -2705,14 +2730,22 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
27052730
lf->setDataDefinedValues( dataDefinedValues );
27062731
}
27072732

2708-
2709-
void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature )
2733+
void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry )
27102734
{
27112735
Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider
27122736

27132737
mCurFeat = &f;
27142738

2715-
const QgsGeometry* geom = f.constGeometry();
2739+
const QgsGeometry* geom = 0;
2740+
if ( obstacleGeometry )
2741+
{
2742+
geom = obstacleGeometry;
2743+
}
2744+
else
2745+
{
2746+
geom = f.constGeometry();
2747+
}
2748+
27162749
if ( !geom )
27172750
{
27182751
return;

src/core/qgspallabeling.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,15 @@ class CORE_EXPORT QgsPalLayerSettings
474474
* @param context render context. The QgsExpressionContext contained within the render context
475475
* must have already had the feature and fields sets prior to calling this method.
476476
* @param dxfLayer dxfLayer name
477-
* @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature
477+
* @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature. Not available
478+
* in Python bindings.
479+
* @param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
480+
* should be used as an obstacle for labels (eg, if the feature has been rendered with an offset point
481+
* symbol, the obstacle geometry should represent the bounds of the offset symbol). If not set,
482+
* the feature's original geometry will be used as an obstacle for labels. Not available
483+
* in Python bindings.
478484
*/
479-
void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer, QgsLabelFeature** labelFeature = 0 );
485+
void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer, QgsLabelFeature** labelFeature = 0, QgsGeometry* obstacleGeometry = 0 );
480486

481487
void readFromLayer( QgsVectorLayer* layer );
482488
void writeToLayer( QgsVectorLayer* layer );
@@ -644,7 +650,7 @@ class CORE_EXPORT QgsPalLayerSettings
644650

645651
/** Registers a feature as an obstacle only (no label rendered)
646652
*/
647-
void registerObstacleFeature( QgsFeature &f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature );
653+
void registerObstacleFeature( QgsFeature &f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry = 0 );
648654

649655
QMap<DataDefinedProperties, QVariant> dataDefinedValues;
650656
QgsExpression* expression;

0 commit comments

Comments
 (0)