Skip to content

Commit

Permalink
Allow setting label obstacle geom in QgsPalLabeling::registerFeature
Browse files Browse the repository at this point in the history
Sponsored by City of Uster
  • Loading branch information
nyalldawson committed Nov 21, 2015
1 parent 9cc10e2 commit 55ead85
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 20 deletions.
7 changes: 7 additions & 0 deletions python/core/qgspallabeling.sip
Expand Up @@ -492,6 +492,13 @@ class QgsPalLayerSettings
* @param context render context. The QgsExpressionContext contained within the render context
* must have already had the feature and fields sets prior to calling this method.
* @param dxfLayer dxfLayer name
* @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature. Not available
* in Python bindings.
* @param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
* should be used as an obstacle for labels (eg, if the feature has been rendered with an offset point
* symbol, the obstacle geometry should represent the bounds of the offset symbol). If not set,
* the feature's original geometry will be used as an obstacle for labels. Not available
* in Python bindings.
*/
void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer );

Expand Down
67 changes: 50 additions & 17 deletions src/core/qgspallabeling.cpp
Expand Up @@ -1896,25 +1896,32 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t
#endif
}


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

Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider

QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful
mCurFeat = &f;

// data defined is obstacle? calculate this first, to avoid wasting time working with obstacles we don't require
bool isObstacle = obstacle; // start with layer default
if ( dataDefinedEvaluate( QgsPalLayerSettings::IsObstacle, exprVal, &context.expressionContext(), obstacle ) )
{
isObstacle = exprVal.toBool();
}

if ( !drawLabels )
{
if ( obstacle )
if ( isObstacle )
{
registerObstacleFeature( f, context, QString(), labelFeature );
registerObstacleFeature( f, context, QString(), labelFeature, obstacleGeometry );
}
return;
}

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

// store data defined-derived values for later adding to label feature for use during rendering
Expand Down Expand Up @@ -2237,7 +2244,6 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
const GEOSGeometry* geos_geom = 0;
const QgsGeometry* preparedGeom = geom;
QScopedPointer<QgsGeometry> scopedPreparedGeom;

if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, ct, doClip ? extentGeom : 0 ) )
{
scopedPreparedGeom.reset( QgsPalLabeling::prepareGeometry( geom, context, ct, doClip ? extentGeom : 0 ) );
Expand All @@ -2250,6 +2256,22 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
{
geos_geom = geom->asGeos();
}
const GEOSGeometry* geosObstacleGeom = 0;
const QgsGeometry* preparedObstacleGeom = obstacleGeometry;
QScopedPointer<QgsGeometry> scopedObstacleGeom;
if ( isObstacle )
{
if ( obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( obstacleGeometry, context, ct, doClip ? extentGeom : 0 ) )
{
scopedObstacleGeom.reset( QgsPalLabeling::prepareGeometry( obstacleGeometry, context, ct, doClip ? extentGeom : 0 ) );
preparedObstacleGeom = scopedObstacleGeom.data();
geosObstacleGeom = scopedObstacleGeom.data()->asGeos();
}
else if ( obstacleGeometry )
{
geosObstacleGeom = obstacleGeometry->asGeos();
}
}

if ( minFeatureSize > 0 && !checkMinimumSizeMM( context, preparedGeom, minFeatureSize ) )
return;
Expand Down Expand Up @@ -2291,6 +2313,12 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
{
geos_geom_clone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
}
GEOSGeometry* geosObstacleGeomClone = 0;
if ( geosObstacleGeom )
{
geosObstacleGeomClone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geosObstacleGeom );
}


//data defined position / alignment / rotation?
bool dataDefinedPosition = false;
Expand Down Expand Up @@ -2610,6 +2638,10 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
( *labelFeature )->setAlwaysShow( alwaysShow );
( *labelFeature )->setRepeatDistance( repeatDist );
( *labelFeature )->setLabelText( labelText );
if ( geosObstacleGeomClone )
{
( *labelFeature )->setObstacleGeometry( geosObstacleGeomClone );
}

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

// data defined is obstacle?
bool isObstacle = obstacle; // start with layer default
if ( dataDefinedEvaluate( QgsPalLayerSettings::IsObstacle, exprVal, &context.expressionContext(), obstacle ) )
{
isObstacle = exprVal.toBool();
}

( *labelFeature )->setIsObstacle( isObstacle );

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


void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature )
void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry )
{
Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider

mCurFeat = &f;

const QgsGeometry* geom = f.constGeometry();
const QgsGeometry* geom = 0;
if ( obstacleGeometry )
{
geom = obstacleGeometry;
}
else
{
geom = f.constGeometry();
}

if ( !geom )
{
return;
Expand Down
12 changes: 9 additions & 3 deletions src/core/qgspallabeling.h
Expand Up @@ -474,9 +474,15 @@ class CORE_EXPORT QgsPalLayerSettings
* @param context render context. The QgsExpressionContext contained within the render context
* must have already had the feature and fields sets prior to calling this method.
* @param dxfLayer dxfLayer name
* @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature
* @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature. Not available
* in Python bindings.
* @param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
* should be used as an obstacle for labels (eg, if the feature has been rendered with an offset point
* symbol, the obstacle geometry should represent the bounds of the offset symbol). If not set,
* the feature's original geometry will be used as an obstacle for labels. Not available
* in Python bindings.
*/
void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer, QgsLabelFeature** labelFeature = 0 );
void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer, QgsLabelFeature** labelFeature = 0, QgsGeometry* obstacleGeometry = 0 );

void readFromLayer( QgsVectorLayer* layer );
void writeToLayer( QgsVectorLayer* layer );
Expand Down Expand Up @@ -644,7 +650,7 @@ class CORE_EXPORT QgsPalLayerSettings

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

QMap<DataDefinedProperties, QVariant> dataDefinedValues;
QgsExpression* expression;
Expand Down

0 comments on commit 55ead85

Please sign in to comment.