mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-10 00:04:23 -04:00
Nicer memory handling when registering label features
This commit is contained in:
parent
d4ac6fc347
commit
cf8b96ad44
@ -505,17 +505,20 @@ vertically oriented text will be written to ``rotatedLabelX`` and ``rotatedLabel
|
|||||||
%End
|
%End
|
||||||
|
|
||||||
void registerFeature( const QgsFeature &f, QgsRenderContext &context );
|
void registerFeature( const QgsFeature &f, QgsRenderContext &context );
|
||||||
|
|
||||||
%Docstring
|
%Docstring
|
||||||
Register a feature for labeling.
|
Registers a feature for labeling.
|
||||||
|
|
||||||
:param f: feature to label
|
:param f: feature to label
|
||||||
:param context: render context. The :py:class:`QgsExpressionContext` contained within the render context
|
:param context: render context. The :py:class:`QgsExpressionContext` contained within the render context
|
||||||
must have already had the feature and fields sets prior to calling this method.
|
must have already had the feature and fields sets prior to calling this method.
|
||||||
:param labelFeature: if using :py:class:`QgsLabelingEngine`, this will receive the label feature. Not available
|
|
||||||
in Python bindings.
|
.. warning::
|
||||||
|
|
||||||
|
This method is designed for use by PyQGIS clients only. C++ code should use the
|
||||||
|
variant with additional arguments.
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
|
||||||
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
|
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
|
||||||
%Docstring
|
%Docstring
|
||||||
Read settings from a DOM element
|
Read settings from a DOM element
|
||||||
|
@ -1670,11 +1670,13 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext &context, QgsLabelFeature **labelFeature, QgsGeometry obstacleGeometry, const QgsSymbol *symbol )
|
void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext &context )
|
||||||
{
|
{
|
||||||
// either used in QgsPalLabeling (palLayer is set) or in QgsLabelingEngine (labelFeature is set)
|
registerFeatureWithDetails( f, context, QgsGeometry(), nullptr );
|
||||||
Q_ASSERT( labelFeature );
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails( const QgsFeature &f, QgsRenderContext &context, QgsGeometry obstacleGeometry, const QgsSymbol *symbol )
|
||||||
|
{
|
||||||
QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful
|
QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful
|
||||||
mCurFeat = &f;
|
mCurFeat = &f;
|
||||||
|
|
||||||
@ -1687,9 +1689,12 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
{
|
{
|
||||||
if ( isObstacle )
|
if ( isObstacle )
|
||||||
{
|
{
|
||||||
registerObstacleFeature( f, context, labelFeature, obstacleGeometry );
|
return registerObstacleFeature( f, context, obstacleGeometry );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsFeature feature = f;
|
QgsFeature feature = f;
|
||||||
@ -1720,7 +1725,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
context.expressionContext().setOriginalValueVariable( true );
|
context.expressionContext().setOriginalValueVariable( true );
|
||||||
if ( !mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Show, context.expressionContext(), true ) )
|
if ( !mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Show, context.expressionContext(), true ) )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1747,7 +1752,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
|
|
||||||
if ( !qgsDoubleNear( maxScale, 0.0 ) && context.rendererScale() < maxScale )
|
if ( !qgsDoubleNear( maxScale, 0.0 ) && context.rendererScale() < maxScale )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// data defined min scale?
|
// data defined min scale?
|
||||||
@ -1766,7 +1771,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
|
|
||||||
if ( !qgsDoubleNear( minScale, 0.0 ) && context.rendererScale() > minScale )
|
if ( !qgsDoubleNear( minScale, 0.0 ) && context.rendererScale() > minScale )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1797,14 +1802,14 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
}
|
}
|
||||||
if ( fontSize <= 0.0 )
|
if ( fontSize <= 0.0 )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fontPixelSize = QgsTextRenderer::sizeToPixel( fontSize, context, fontunits, mFormat.sizeMapUnitScale() );
|
int fontPixelSize = QgsTextRenderer::sizeToPixel( fontSize, context, fontunits, mFormat.sizeMapUnitScale() );
|
||||||
// don't try to show font sizes less than 1 pixel (Qt complains)
|
// don't try to show font sizes less than 1 pixel (Qt complains)
|
||||||
if ( fontPixelSize < 1 )
|
if ( fontPixelSize < 1 )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
labelFont.setPixelSize( fontPixelSize );
|
labelFont.setPixelSize( fontPixelSize );
|
||||||
|
|
||||||
@ -1820,7 +1825,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
|
|
||||||
if ( fontMinPixel > labelFont.pixelSize() || labelFont.pixelSize() > fontMaxPixel )
|
if ( fontMinPixel > labelFont.pixelSize() || labelFont.pixelSize() > fontMaxPixel )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1851,14 +1856,14 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
if ( exp->hasParserError() )
|
if ( exp->hasParserError() )
|
||||||
{
|
{
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Expression parser error:%1" ).arg( exp->parserErrorString() ), 4 );
|
QgsDebugMsgLevel( QStringLiteral( "Expression parser error:%1" ).arg( exp->parserErrorString() ), 4 );
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant result = exp->evaluate( &context.expressionContext() ); // expression prepared in QgsPalLabeling::prepareLayer()
|
QVariant result = exp->evaluate( &context.expressionContext() ); // expression prepared in QgsPalLabeling::prepareLayer()
|
||||||
if ( exp->hasEvalError() )
|
if ( exp->hasEvalError() )
|
||||||
{
|
{
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Expression parser eval error:%1" ).arg( exp->evalErrorString() ), 4 );
|
QgsDebugMsgLevel( QStringLiteral( "Expression parser eval error:%1" ).arg( exp->evalErrorString() ), 4 );
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
labelText = result.isNull() ? QString() : result.toString();
|
labelText = result.isNull() ? QString() : result.toString();
|
||||||
}
|
}
|
||||||
@ -2012,7 +2017,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
QgsGeometry geom = feature.geometry();
|
QgsGeometry geom = feature.geometry();
|
||||||
if ( geom.isNull() )
|
if ( geom.isNull() )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simplify?
|
// simplify?
|
||||||
@ -2132,7 +2137,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
geom = QgsPalLabeling::prepareGeometry( geom, context, ct, doClip ? extentGeom : QgsGeometry(), lineSettings.mergeLines() );
|
geom = QgsPalLabeling::prepareGeometry( geom, context, ct, doClip ? extentGeom : QgsGeometry(), lineSettings.mergeLines() );
|
||||||
|
|
||||||
if ( geom.isEmpty() )
|
if ( geom.isEmpty() )
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
geos_geom_clone = QgsGeos::asGeos( geom );
|
geos_geom_clone = QgsGeos::asGeos( geom );
|
||||||
|
|
||||||
@ -2158,12 +2163,12 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( !checkMinimumSizeMM( context, geom, featureThinningSettings.minimumFeatureSize() ) )
|
if ( !checkMinimumSizeMM( context, geom, featureThinningSettings.minimumFeatureSize() ) )
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !geos_geom_clone )
|
if ( !geos_geom_clone )
|
||||||
return; // invalid geometry
|
return nullptr; // invalid geometry
|
||||||
|
|
||||||
// likelihood exists label will be registered with PAL and may be drawn
|
// likelihood exists label will be registered with PAL and may be drawn
|
||||||
// check if max number of features to label (already registered with PAL) has been reached
|
// check if max number of features to label (already registered with PAL) has been reached
|
||||||
@ -2172,11 +2177,11 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
{
|
{
|
||||||
if ( !featureThinningSettings.maximumNumberLabels() )
|
if ( !featureThinningSettings.maximumNumberLabels() )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if ( mFeatsRegPal >= featureThinningSettings.maximumNumberLabels() )
|
if ( mFeatsRegPal >= featureThinningSettings.maximumNumberLabels() )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int divNum = static_cast< int >( ( static_cast< double >( mFeaturesToLabel ) / featureThinningSettings.maximumNumberLabels() ) + 0.5 ); // NOLINT
|
int divNum = static_cast< int >( ( static_cast< double >( mFeaturesToLabel ) / featureThinningSettings.maximumNumberLabels() ) + 0.5 ); // NOLINT
|
||||||
@ -2185,7 +2190,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
mFeatsSendingToPal += 1;
|
mFeatsSendingToPal += 1;
|
||||||
if ( divNum && mFeatsSendingToPal % divNum )
|
if ( divNum && mFeatsSendingToPal % divNum )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2531,39 +2536,38 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
// feature to the layer
|
// feature to the layer
|
||||||
QgsTextLabelFeature *lf = new QgsTextLabelFeature( feature.id(), std::move( geos_geom_clone ), QSizeF( labelX, labelY ) );
|
std::unique_ptr< QgsTextLabelFeature > labelFeature = std::make_unique< QgsTextLabelFeature>( feature.id(), std::move( geos_geom_clone ), QSizeF( labelX, labelY ) );
|
||||||
lf->setAnchorPosition( anchorPosition );
|
labelFeature->setAnchorPosition( anchorPosition );
|
||||||
lf->setFeature( feature );
|
labelFeature->setFeature( feature );
|
||||||
lf->setSymbol( symbol );
|
labelFeature->setSymbol( symbol );
|
||||||
lf->setDocument( doc );
|
labelFeature->setDocument( doc );
|
||||||
if ( !qgsDoubleNear( rotatedLabelX, 0.0 ) && !qgsDoubleNear( rotatedLabelY, 0.0 ) )
|
if ( !qgsDoubleNear( rotatedLabelX, 0.0 ) && !qgsDoubleNear( rotatedLabelY, 0.0 ) )
|
||||||
lf->setRotatedSize( QSizeF( rotatedLabelX, rotatedLabelY ) );
|
labelFeature->setRotatedSize( QSizeF( rotatedLabelX, rotatedLabelY ) );
|
||||||
mFeatsRegPal++;
|
mFeatsRegPal++;
|
||||||
|
|
||||||
*labelFeature = lf;
|
labelFeature->setHasFixedPosition( hasDataDefinedPosition );
|
||||||
( *labelFeature )->setHasFixedPosition( hasDataDefinedPosition );
|
labelFeature->setFixedPosition( QgsPointXY( xPos, yPos ) );
|
||||||
( *labelFeature )->setFixedPosition( QgsPointXY( xPos, yPos ) );
|
|
||||||
// use layer-level defined rotation, but not if position fixed
|
// use layer-level defined rotation, but not if position fixed
|
||||||
( *labelFeature )->setHasFixedAngle( dataDefinedRotation || ( !hasDataDefinedPosition && !qgsDoubleNear( angle, 0.0 ) ) );
|
labelFeature->setHasFixedAngle( dataDefinedRotation || ( !hasDataDefinedPosition && !qgsDoubleNear( angle, 0.0 ) ) );
|
||||||
( *labelFeature )->setFixedAngle( angle );
|
labelFeature->setFixedAngle( angle );
|
||||||
( *labelFeature )->setQuadOffset( QPointF( quadOffsetX, quadOffsetY ) );
|
labelFeature->setQuadOffset( QPointF( quadOffsetX, quadOffsetY ) );
|
||||||
( *labelFeature )->setPositionOffset( QgsPointXY( offsetX, offsetY ) );
|
labelFeature->setPositionOffset( QgsPointXY( offsetX, offsetY ) );
|
||||||
( *labelFeature )->setOffsetType( offsetType );
|
labelFeature->setOffsetType( offsetType );
|
||||||
( *labelFeature )->setAlwaysShow( alwaysShow );
|
labelFeature->setAlwaysShow( alwaysShow );
|
||||||
( *labelFeature )->setRepeatDistance( repeatDist );
|
labelFeature->setRepeatDistance( repeatDist );
|
||||||
( *labelFeature )->setLabelText( labelText );
|
labelFeature->setLabelText( labelText );
|
||||||
( *labelFeature )->setPermissibleZone( permissibleZone );
|
labelFeature->setPermissibleZone( permissibleZone );
|
||||||
( *labelFeature )->setOverrunDistance( overrunDistanceEval );
|
labelFeature->setOverrunDistance( overrunDistanceEval );
|
||||||
( *labelFeature )->setOverrunSmoothDistance( overrunSmoothDist );
|
labelFeature->setOverrunSmoothDistance( overrunSmoothDist );
|
||||||
( *labelFeature )->setLineAnchorPercent( lineSettings.lineAnchorPercent() );
|
labelFeature->setLineAnchorPercent( lineSettings.lineAnchorPercent() );
|
||||||
( *labelFeature )->setLineAnchorType( lineSettings.anchorType() );
|
labelFeature->setLineAnchorType( lineSettings.anchorType() );
|
||||||
( *labelFeature )->setLabelAllParts( labelAll );
|
labelFeature->setLabelAllParts( labelAll );
|
||||||
( *labelFeature )->setOriginalFeatureCrs( context.coordinateTransform().sourceCrs() );
|
labelFeature->setOriginalFeatureCrs( context.coordinateTransform().sourceCrs() );
|
||||||
( *labelFeature )->setMinimumSize( minimumSize );
|
labelFeature->setMinimumSize( minimumSize );
|
||||||
if ( geom.type() == QgsWkbTypes::PointGeometry && !obstacleGeometry.isNull() )
|
if ( geom.type() == QgsWkbTypes::PointGeometry && !obstacleGeometry.isNull() )
|
||||||
{
|
{
|
||||||
//register symbol size
|
//register symbol size
|
||||||
( *labelFeature )->setSymbolSize( QSizeF( obstacleGeometry.boundingBox().width(),
|
labelFeature->setSymbolSize( QSizeF( obstacleGeometry.boundingBox().width(),
|
||||||
obstacleGeometry.boundingBox().height() ) );
|
obstacleGeometry.boundingBox().height() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2573,15 +2577,15 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
double bottomMargin = 1.0 + labelFontMetrics->descent();
|
double bottomMargin = 1.0 + labelFontMetrics->descent();
|
||||||
QgsMargins vm( 0.0, topMargin, 0.0, bottomMargin );
|
QgsMargins vm( 0.0, topMargin, 0.0, bottomMargin );
|
||||||
vm *= xform->mapUnitsPerPixel();
|
vm *= xform->mapUnitsPerPixel();
|
||||||
( *labelFeature )->setVisualMargin( vm );
|
labelFeature->setVisualMargin( vm );
|
||||||
|
|
||||||
// store the label's calculated font for later use during painting
|
// store the label's calculated font for later use during painting
|
||||||
QgsDebugMsgLevel( QStringLiteral( "PAL font stored definedFont: %1, Style: %2" ).arg( labelFont.toString(), labelFont.styleName() ), 4 );
|
QgsDebugMsgLevel( QStringLiteral( "PAL font stored definedFont: %1, Style: %2" ).arg( labelFont.toString(), labelFont.styleName() ), 4 );
|
||||||
lf->setDefinedFont( labelFont );
|
labelFeature->setDefinedFont( labelFont );
|
||||||
lf->setFontMetrics( *labelFontMetrics );
|
labelFeature->setFontMetrics( *labelFontMetrics );
|
||||||
|
|
||||||
lf->setMaximumCharacterAngleInside( std::clamp( maxcharanglein, 20.0, 60.0 ) * M_PI / 180 );
|
labelFeature->setMaximumCharacterAngleInside( std::clamp( maxcharanglein, 20.0, 60.0 ) * M_PI / 180 );
|
||||||
lf->setMaximumCharacterAngleOutside( std::clamp( maxcharangleout, -95.0, -20.0 ) * M_PI / 180 );
|
labelFeature->setMaximumCharacterAngleOutside( std::clamp( maxcharangleout, -95.0, -20.0 ) * M_PI / 180 );
|
||||||
switch ( placement )
|
switch ( placement )
|
||||||
{
|
{
|
||||||
case QgsPalLayerSettings::AroundPoint:
|
case QgsPalLayerSettings::AroundPoint:
|
||||||
@ -2596,7 +2600,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
|
|
||||||
case QgsPalLayerSettings::Curved:
|
case QgsPalLayerSettings::Curved:
|
||||||
case QgsPalLayerSettings::PerimeterCurved:
|
case QgsPalLayerSettings::PerimeterCurved:
|
||||||
lf->setTextMetrics( QgsTextLabelFeature::calculateTextMetrics( xform, *labelFontMetrics, labelFont.letterSpacing(), labelFont.wordSpacing(), labelText, format().allowHtmlFormatting() ? &doc : nullptr ) );
|
labelFeature->setTextMetrics( QgsTextLabelFeature::calculateTextMetrics( xform, *labelFontMetrics, labelFont.letterSpacing(), labelFont.wordSpacing(), labelText, format().allowHtmlFormatting() ? &doc : nullptr ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2654,17 +2658,17 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
if ( !qgsDoubleNear( distance, 0.0 ) )
|
if ( !qgsDoubleNear( distance, 0.0 ) )
|
||||||
{
|
{
|
||||||
double d = ptOne.distance( ptZero ) * distance;
|
double d = ptOne.distance( ptZero ) * distance;
|
||||||
( *labelFeature )->setDistLabel( d );
|
labelFeature->setDistLabel( d );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ddFixedQuad )
|
if ( ddFixedQuad )
|
||||||
{
|
{
|
||||||
( *labelFeature )->setHasFixedQuadrant( true );
|
labelFeature->setHasFixedQuadrant( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
( *labelFeature )->setArrangementFlags( lineSettings.placementFlags() );
|
labelFeature->setArrangementFlags( lineSettings.placementFlags() );
|
||||||
|
|
||||||
( *labelFeature )->setPolygonPlacementFlags( polygonPlacement );
|
labelFeature->setPolygonPlacementFlags( polygonPlacement );
|
||||||
|
|
||||||
// data defined z-index?
|
// data defined z-index?
|
||||||
double z = zIndex;
|
double z = zIndex;
|
||||||
@ -2673,7 +2677,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
context.expressionContext().setOriginalValueVariable( z );
|
context.expressionContext().setOriginalValueVariable( z );
|
||||||
z = mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::ZIndex, context.expressionContext(), z );
|
z = mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::ZIndex, context.expressionContext(), z );
|
||||||
}
|
}
|
||||||
( *labelFeature )->setZIndex( z );
|
labelFeature->setZIndex( z );
|
||||||
|
|
||||||
// data defined priority?
|
// data defined priority?
|
||||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Priority ) )
|
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Priority ) )
|
||||||
@ -2688,7 +2692,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
{
|
{
|
||||||
priorityD = std::clamp( priorityD, 0.0, 10.0 );
|
priorityD = std::clamp( priorityD, 0.0, 10.0 );
|
||||||
priorityD = 1 - priorityD / 10.0; // convert 0..10 --> 1..0
|
priorityD = 1 - priorityD / 10.0; // convert 0..10 --> 1..0
|
||||||
( *labelFeature )->setPriority( priorityD );
|
labelFeature->setPriority( priorityD );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2697,7 +2701,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
os.setIsObstacle( isObstacle );
|
os.setIsObstacle( isObstacle );
|
||||||
os.updateDataDefinedProperties( mDataDefinedProperties, context.expressionContext() );
|
os.updateDataDefinedProperties( mDataDefinedProperties, context.expressionContext() );
|
||||||
os.setObstacleGeometry( obstacleGeometry );
|
os.setObstacleGeometry( obstacleGeometry );
|
||||||
lf->setObstacleSettings( os );
|
labelFeature->setObstacleSettings( os );
|
||||||
|
|
||||||
QVector< QgsPalLayerSettings::PredefinedPointPosition > positionOrder = predefinedPositionOrder;
|
QVector< QgsPalLayerSettings::PredefinedPointPosition > positionOrder = predefinedPositionOrder;
|
||||||
if ( positionOrder.isEmpty() )
|
if ( positionOrder.isEmpty() )
|
||||||
@ -2712,13 +2716,15 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
|
|||||||
positionOrder = QgsLabelingUtils::decodePredefinedPositionOrder( dataDefinedOrder );
|
positionOrder = QgsLabelingUtils::decodePredefinedPositionOrder( dataDefinedOrder );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
( *labelFeature )->setPredefinedPositionOrder( positionOrder );
|
labelFeature->setPredefinedPositionOrder( positionOrder );
|
||||||
|
|
||||||
// add parameters for data defined labeling to label feature
|
// add parameters for data defined labeling to label feature
|
||||||
lf->setDataDefinedValues( dataDefinedValues );
|
labelFeature->setDataDefinedValues( dataDefinedValues );
|
||||||
|
|
||||||
|
return labelFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsPalLayerSettings::registerObstacleFeature( const QgsFeature &f, QgsRenderContext &context, QgsLabelFeature **obstacleFeature, const QgsGeometry &obstacleGeometry )
|
std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerObstacleFeature( const QgsFeature &f, QgsRenderContext &context, const QgsGeometry &obstacleGeometry )
|
||||||
{
|
{
|
||||||
mCurFeat = &f;
|
mCurFeat = &f;
|
||||||
|
|
||||||
@ -2734,14 +2740,14 @@ void QgsPalLayerSettings::registerObstacleFeature( const QgsFeature &f, QgsRende
|
|||||||
|
|
||||||
if ( geom.isNull() )
|
if ( geom.isNull() )
|
||||||
{
|
{
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't even try to register linestrings with only one vertex as an obstacle
|
// don't even try to register linestrings with only one vertex as an obstacle
|
||||||
if ( const QgsLineString *ls = qgsgeometry_cast< const QgsLineString * >( geom.constGet() ) )
|
if ( const QgsLineString *ls = qgsgeometry_cast< const QgsLineString * >( geom.constGet() ) )
|
||||||
{
|
{
|
||||||
if ( ls->numPoints() < 2 )
|
if ( ls->numPoints() < 2 )
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simplify?
|
// simplify?
|
||||||
@ -2765,18 +2771,19 @@ void QgsPalLayerSettings::registerObstacleFeature( const QgsFeature &f, QgsRende
|
|||||||
geos_geom_clone = QgsGeos::asGeos( geom );
|
geos_geom_clone = QgsGeos::asGeos( geom );
|
||||||
|
|
||||||
if ( !geos_geom_clone )
|
if ( !geos_geom_clone )
|
||||||
return; // invalid geometry
|
return nullptr; // invalid geometry
|
||||||
|
|
||||||
// feature to the layer
|
// feature to the layer
|
||||||
*obstacleFeature = new QgsLabelFeature( f.id(), std::move( geos_geom_clone ), QSizeF( 0, 0 ) );
|
std::unique_ptr< QgsLabelFeature > obstacleFeature = std::make_unique< QgsLabelFeature >( f.id(), std::move( geos_geom_clone ), QSizeF( 0, 0 ) );
|
||||||
( *obstacleFeature )->setFeature( f );
|
obstacleFeature->setFeature( f );
|
||||||
|
|
||||||
QgsLabelObstacleSettings os = mObstacleSettings;
|
QgsLabelObstacleSettings os = mObstacleSettings;
|
||||||
os.setIsObstacle( true );
|
os.setIsObstacle( true );
|
||||||
os.updateDataDefinedProperties( mDataDefinedProperties, context.expressionContext() );
|
os.updateDataDefinedProperties( mDataDefinedProperties, context.expressionContext() );
|
||||||
( *obstacleFeature )->setObstacleSettings( os );
|
obstacleFeature->setObstacleSettings( os );
|
||||||
|
|
||||||
mFeatsRegPal++;
|
mFeatsRegPal++;
|
||||||
|
return obstacleFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsPalLayerSettings::dataDefinedValEval( DataDefinedValueType valType,
|
bool QgsPalLayerSettings::dataDefinedValEval( DataDefinedValueType valType,
|
||||||
|
@ -823,22 +823,37 @@ class CORE_EXPORT QgsPalLayerSettings
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a feature for labeling.
|
* Registers a feature for labeling.
|
||||||
* \param f feature to label
|
* \param f feature to label
|
||||||
* \param context render context. The QgsExpressionContext contained within the render context
|
* \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.
|
* must have already had the feature and fields sets prior to calling this method.
|
||||||
* \param labelFeature if using QgsLabelingEngine, this will receive the label feature. Not available
|
*
|
||||||
* in Python bindings.
|
* \warning This method is designed for use by PyQGIS clients only. C++ code should use the
|
||||||
|
* variant with additional arguments.
|
||||||
|
*/
|
||||||
|
void registerFeature( const QgsFeature &f, QgsRenderContext &context );
|
||||||
|
|
||||||
|
#ifndef SIP_RUN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a feature for labeling.
|
||||||
|
* \param feature feature to label
|
||||||
|
* \param context render context. The QgsExpressionContext contained within the render context
|
||||||
|
* must have already had the feature and fields set prior to calling this method.
|
||||||
* \param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
|
* \param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
|
||||||
* should be used as an obstacle for labels (e.g., if the feature has been rendered with an offset point
|
* should be used as an obstacle for labels (e.g., 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,
|
* 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
|
* the feature's original geometry will be used as an obstacle for labels.
|
||||||
* in Python bindings.
|
|
||||||
* \param symbol feature symbol to label (ownership is not transferred, and \a symbol must exist until the labeling is complete)
|
* \param symbol feature symbol to label (ownership is not transferred, and \a symbol must exist until the labeling is complete)
|
||||||
|
*
|
||||||
|
* \returns QgsLabelFeature representing the registered feature, or NULLPTR if the feature will not be labeled
|
||||||
|
* in this context.
|
||||||
|
*
|
||||||
|
* \note Not available in Python bindings
|
||||||
*/
|
*/
|
||||||
void registerFeature( const QgsFeature &f, QgsRenderContext &context,
|
std::unique_ptr< QgsLabelFeature > registerFeatureWithDetails( const QgsFeature &feature, QgsRenderContext &context,
|
||||||
QgsLabelFeature **labelFeature SIP_PYARGREMOVE = nullptr,
|
QgsGeometry obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr );
|
||||||
QgsGeometry obstacleGeometry SIP_PYARGREMOVE = QgsGeometry(), const QgsSymbol *symbol SIP_PYARGREMOVE = nullptr );
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read settings from a DOM element
|
* Read settings from a DOM element
|
||||||
@ -1090,7 +1105,7 @@ class CORE_EXPORT QgsPalLayerSettings
|
|||||||
/**
|
/**
|
||||||
* Registers a feature as an obstacle only (no label rendered)
|
* Registers a feature as an obstacle only (no label rendered)
|
||||||
*/
|
*/
|
||||||
void registerObstacleFeature( const QgsFeature &f, QgsRenderContext &context, QgsLabelFeature **obstacleFeature, const QgsGeometry &obstacleGeometry = QgsGeometry() );
|
std::unique_ptr< QgsLabelFeature > registerObstacleFeature( const QgsFeature &f, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry() );
|
||||||
|
|
||||||
QMap<Property, QVariant> dataDefinedValues;
|
QMap<Property, QVariant> dataDefinedValues;
|
||||||
|
|
||||||
|
@ -38,10 +38,10 @@ bool QgsRuleBasedLabelProvider::prepare( QgsRenderContext &context, QSet<QString
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsRuleBasedLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
QList<QgsLabelFeature *> QgsRuleBasedLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
||||||
{
|
{
|
||||||
// will register the feature to relevant sub-providers
|
// will register the feature to relevant sub-providers
|
||||||
mRules->rootRule()->registerFeature( feature, context, mSubProviders, obstacleGeometry, symbol );
|
return std::get< 1 >( mRules->rootRule()->registerFeature( feature, context, mSubProviders, obstacleGeometry, symbol ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
|
QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
|
||||||
@ -349,12 +349,13 @@ void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QStrin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerFeature( const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature * > > QgsRuleBasedLabeling::Rule::registerFeature( const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
||||||
{
|
{
|
||||||
|
QList< QgsLabelFeature * > labels;
|
||||||
if ( !isFilterOK( feature, context )
|
if ( !isFilterOK( feature, context )
|
||||||
|| !isScaleOK( context.rendererScale() ) )
|
|| !isScaleOK( context.rendererScale() ) )
|
||||||
{
|
{
|
||||||
return Filtered;
|
return { Filtered, labels };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool registered = false;
|
bool registered = false;
|
||||||
@ -362,7 +363,7 @@ QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerF
|
|||||||
// do we have active subprovider for the rule?
|
// do we have active subprovider for the rule?
|
||||||
if ( subProviders.contains( this ) && mIsActive )
|
if ( subProviders.contains( this ) && mIsActive )
|
||||||
{
|
{
|
||||||
subProviders[this]->registerFeature( feature, context, obstacleGeometry, symbol );
|
labels.append( subProviders[this]->registerFeature( feature, context, obstacleGeometry, symbol ) );
|
||||||
registered = true;
|
registered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,7 +375,10 @@ QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerF
|
|||||||
// Don't process else rules yet
|
// Don't process else rules yet
|
||||||
if ( !rule->isElse() )
|
if ( !rule->isElse() )
|
||||||
{
|
{
|
||||||
RegisterResult res = rule->registerFeature( feature, context, subProviders, obstacleGeometry );
|
RegisterResult res;
|
||||||
|
QList< QgsLabelFeature * > added;
|
||||||
|
std::tie( res, added ) = rule->registerFeature( feature, context, subProviders, obstacleGeometry );
|
||||||
|
labels.append( added );
|
||||||
// consider inactive items as "registered" so the else rule will ignore them
|
// consider inactive items as "registered" so the else rule will ignore them
|
||||||
willRegisterSomething |= ( res == Registered || res == Inactive );
|
willRegisterSomething |= ( res == Registered || res == Inactive );
|
||||||
registered |= willRegisterSomething;
|
registered |= willRegisterSomething;
|
||||||
@ -386,16 +390,20 @@ QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerF
|
|||||||
{
|
{
|
||||||
for ( Rule *rule : std::as_const( mElseRules ) )
|
for ( Rule *rule : std::as_const( mElseRules ) )
|
||||||
{
|
{
|
||||||
registered |= rule->registerFeature( feature, context, subProviders, obstacleGeometry, symbol ) != Filtered;
|
RegisterResult res;
|
||||||
|
QList< QgsLabelFeature * > added;
|
||||||
|
std::tie( res, added ) = rule->registerFeature( feature, context, subProviders, obstacleGeometry, symbol ) ;
|
||||||
|
registered |= res != Filtered;
|
||||||
|
labels.append( added );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !mIsActive )
|
if ( !mIsActive )
|
||||||
return Inactive;
|
return { Inactive, labels };
|
||||||
else if ( registered )
|
else if ( registered )
|
||||||
return Registered;
|
return { Registered, labels };
|
||||||
else
|
else
|
||||||
return Filtered;
|
return { Filtered, labels };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsRuleBasedLabeling::Rule::isFilterOK( const QgsFeature &f, QgsRenderContext &context ) const
|
bool QgsRuleBasedLabeling::Rule::isFilterOK( const QgsFeature &f, QgsRenderContext &context ) const
|
||||||
|
@ -282,10 +282,15 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
|||||||
void prepare( QgsRenderContext &context, QSet<QString> &attributeNames, RuleToProviderMap &subProviders ) SIP_SKIP;
|
void prepare( QgsRenderContext &context, QSet<QString> &attributeNames, RuleToProviderMap &subProviders ) SIP_SKIP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* register individual features
|
* Register individual features
|
||||||
|
*
|
||||||
|
* Returns result of registration, together with a list of all label features which
|
||||||
|
* were created as a result of registering \a feature. Ownership of these label features is not transferred
|
||||||
|
* (it has already been assigned to the label provider).
|
||||||
|
*
|
||||||
* \note not available in Python bindings
|
* \note not available in Python bindings
|
||||||
*/
|
*/
|
||||||
RegisterResult registerFeature( const QgsFeature &feature, QgsRenderContext &context, RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr ) SIP_SKIP;
|
std::tuple< RegisterResult, QList< QgsLabelFeature * > > registerFeature( const QgsFeature &feature, QgsRenderContext &context, RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr ) SIP_SKIP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns TRUE if this rule or any of its children requires advanced composition effects
|
* Returns TRUE if this rule or any of its children requires advanced composition effects
|
||||||
@ -411,7 +416,7 @@ class CORE_EXPORT QgsRuleBasedLabelProvider : public QgsVectorLayerLabelProvider
|
|||||||
|
|
||||||
bool prepare( QgsRenderContext &context, QSet<QString> &attributeNames ) override;
|
bool prepare( QgsRenderContext &context, QSet<QString> &attributeNames ) override;
|
||||||
|
|
||||||
void registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr ) override;
|
QList< QgsLabelFeature * > registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr ) override;
|
||||||
|
|
||||||
//! create a label provider
|
//! create a label provider
|
||||||
virtual QgsVectorLayerLabelProvider *createProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings );
|
virtual QgsVectorLayerLabelProvider *createProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings );
|
||||||
|
@ -190,13 +190,16 @@ QList<QgsLabelFeature *> QgsVectorLayerLabelProvider::labelFeatures( QgsRenderCo
|
|||||||
return mLabels;
|
return mLabels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsVectorLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
QList< QgsLabelFeature * > QgsVectorLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
||||||
{
|
{
|
||||||
QgsLabelFeature *label = nullptr;
|
std::unique_ptr< QgsLabelFeature > label = mSettings.registerFeatureWithDetails( feature, context, obstacleGeometry, symbol );
|
||||||
|
QList< QgsLabelFeature * > res;
|
||||||
mSettings.registerFeature( feature, context, &label, obstacleGeometry, symbol );
|
|
||||||
if ( label )
|
if ( label )
|
||||||
mLabels << label;
|
{
|
||||||
|
res << label.get();
|
||||||
|
mLabels << label.release();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsGeometry QgsVectorLayerLabelProvider::getPointObstacleGeometry( QgsFeature &fet, QgsRenderContext &context, const QgsSymbolList &symbols )
|
QgsGeometry QgsVectorLayerLabelProvider::getPointObstacleGeometry( QgsFeature &fet, QgsRenderContext &context, const QgsSymbolList &symbols )
|
||||||
|
@ -88,8 +88,10 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
|
|||||||
* symbol, the obstacle geometry should represent the bounds of the offset symbol). If not set,
|
* 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.
|
* the feature's original geometry will be used as an obstacle for labels.
|
||||||
* \param symbol feature symbol to label (ownership is not transferred - the symbol must exist until after labeling is complete)
|
* \param symbol feature symbol to label (ownership is not transferred - the symbol must exist until after labeling is complete)
|
||||||
|
* \returns a list of the newly generated label features. Ownership of these label features is not transferred
|
||||||
|
* (it has already been assigned to the label provider).
|
||||||
*/
|
*/
|
||||||
virtual void registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr );
|
virtual QList< QgsLabelFeature * > registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the geometry for a point feature which should be used as an obstacle for labels. This
|
* Returns the geometry for a point feature which should be used as an obstacle for labels. This
|
||||||
|
Loading…
x
Reference in New Issue
Block a user