35 static bool _palIsCanceled(
void *ctx )
37 return (
reinterpret_cast< QgsRenderContext *
>( ctx ) )->renderingStopped();
50 : mMapSettings( mapSettings )
62 QStringList layerIds = mMapSettings.
layerIds();
65 if ( layer1Pos != layer2Pos && layer1Pos >= 0 && layer2Pos >= 0 )
66 return layer1Pos > layer2Pos;
69 return lf1->
size().width() * lf1->
size().height() > lf2->
size().width() * lf2->
size().height();
100 QList< QgsMapLayer * > layers;
103 QList< QgsAbstractLabelProvider * > providersByZ =
mProviders;
104 std::sort( providersByZ.begin(), providersByZ.end(),
107 const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
108 const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
110 if ( providerA && providerB )
112 return providerA->settings().zIndex < providerB->settings().zIndex ;
117 QList< QgsAbstractLabelProvider * > subProvidersByZ = mSubProviders;
118 std::sort( subProvidersByZ.begin(), subProvidersByZ.end(),
121 const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
122 const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
124 if ( providerA && providerB )
126 return providerA->settings().zIndex < providerB->settings().zIndex ;
133 if ( provider->layer() && !layers.contains( provider->layer() ) )
134 layers << provider->layer();
138 if ( provider->layer() && !layers.contains( provider->layer() ) )
139 layers << provider->layer();
149 QList< QgsAbstractLabelProvider * > providersByZ =
mProviders;
150 std::sort( providersByZ.begin(), providersByZ.end(),
153 const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
154 const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
156 if ( providerA && providerB )
158 return providerA->settings().zIndex < providerB->settings().zIndex ;
163 QList< QgsAbstractLabelProvider * > subProvidersByZ = mSubProviders;
164 std::sort( subProvidersByZ.begin(), subProvidersByZ.end(),
167 const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
168 const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
170 if ( providerA && providerB )
172 return providerA->settings().zIndex < providerB->settings().zIndex ;
179 if ( !layers.contains( provider->layerId() ) )
180 layers << provider->layerId();
184 if ( !layers.contains( provider->layerId() ) )
185 layers << provider->layerId();
207 QgsAbstractLabelProvider::Flags flags = provider->
flags();
244 const QList<QgsLabelFeature *> features = provider->
labelFeatures( context );
252 catch ( std::exception &e )
255 QgsDebugMsgLevel( QStringLiteral(
"Ignoring feature %1 due PAL exception:" ).arg( feature->id() ) + QString::fromLatin1( e.what() ), 4 );
273 mPal = std::make_unique< pal::Pal >();
284 std::unique_ptr< QgsExpressionContextScopePopper > layerScopePopper;
295 Q_ASSERT(
mPal.get() );
300 QPainter *painter = context.
painter();
304 visiblePoly.append( visiblePoly.at( 0 ) );
313 mapBoundaryGeom = mapBoundaryGeom.
difference( region.geometry );
321 QVariantMap properties;
322 properties.insert( QStringLiteral(
"style" ), QStringLiteral(
"no" ) );
323 properties.insert( QStringLiteral(
"style_border" ), QStringLiteral(
"solid" ) );
324 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"#0000ff" ) );
325 properties.insert( QStringLiteral(
"width_border" ), QStringLiteral(
"0.3" ) );
326 properties.insert( QStringLiteral(
"joinstyle" ), QStringLiteral(
"miter" ) );
328 boundarySymbol->startRender( context );
329 boundarySymbol->renderFeature( f, context );
330 boundarySymbol->stopRender( context );
343 mPal->registerCancellationCallback( &_palIsCanceled,
reinterpret_cast< void *
>( &context ) );
351 mProblem =
mPal->extractProblem( extent, mapBoundaryGeom );
353 catch ( std::exception &e )
356 QgsDebugMsgLevel(
"PAL EXCEPTION :-( " + QString::fromLatin1( e.what() ), 4 );
382 painter->setBrush( Qt::NoBrush );
383 for (
int i = 0; i < static_cast< int >(
mProblem->featureCount() ); i++ )
385 for (
int j = 0; j <
mProblem->featureCandidateCount( i ); j++ )
402 QgsDebugMsgLevel( QStringLiteral(
"LABELING work: %1 ms ... labels# %2" ).arg( t.elapsed() ).arg(
mLabels.size() ), 4 );
413 QPainter *painter = context.
painter();
418 if ( !layerId.isEmpty() && provider->layerId() != layerId )
424 provider->startRender( context );
428 std::unique_ptr< QgsExpressionContextScopePopper > symbolScopePopper = std::make_unique< QgsExpressionContextScopePopper >( context.
expressionContext(), symbolScope );
508 symbolScopePopper.reset();
513 if ( !layerId.isEmpty() && provider->layerId() != layerId )
516 provider->stopRender( context );
520 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
522 QgsDebugMsgLevel( QStringLiteral(
"LABELING draw: %1 ms" ).arg( t.elapsed() ), 4 );
618 : mLayerId( layer ? layer->id() : QString() )
620 , mProviderId( providerId )
621 , mFlags( DrawLabels )
643 subProvider->startRender( context );
652 subProvider->stopRender( context );
662 QStringList predefinedOrderString;
663 const auto constPositions = positions;
669 predefinedOrderString << QStringLiteral(
"TL" );
672 predefinedOrderString << QStringLiteral(
"TSL" );
675 predefinedOrderString << QStringLiteral(
"T" );
678 predefinedOrderString << QStringLiteral(
"TSR" );
681 predefinedOrderString << QStringLiteral(
"TR" );
684 predefinedOrderString << QStringLiteral(
"L" );
687 predefinedOrderString << QStringLiteral(
"R" );
690 predefinedOrderString << QStringLiteral(
"BL" );
693 predefinedOrderString << QStringLiteral(
"BSL" );
696 predefinedOrderString << QStringLiteral(
"B" );
699 predefinedOrderString << QStringLiteral(
"BSR" );
702 predefinedOrderString << QStringLiteral(
"BR" );
706 return predefinedOrderString.join(
',' );
711 QVector<QgsPalLayerSettings::PredefinedPointPosition> result;
712 const QStringList predefinedOrderList = positionString.split(
',' );
713 result.reserve( predefinedOrderList.size() );
714 for (
const QString &position : predefinedOrderList )
716 QString cleaned = position.trimmed().toUpper();
717 if ( cleaned == QLatin1String(
"TL" ) )
719 else if ( cleaned == QLatin1String(
"TSL" ) )
721 else if ( cleaned == QLatin1String(
"T" ) )
723 else if ( cleaned == QLatin1String(
"TSR" ) )
725 else if ( cleaned == QLatin1String(
"TR" ) )
727 else if ( cleaned == QLatin1String(
"L" ) )
729 else if ( cleaned == QLatin1String(
"R" ) )
731 else if ( cleaned == QLatin1String(
"BL" ) )
733 else if ( cleaned == QLatin1String(
"BSL" ) )
735 else if ( cleaned == QLatin1String(
"B" ) )
737 else if ( cleaned == QLatin1String(
"BSR" ) )
739 else if ( cleaned == QLatin1String(
"BR" ) )
748 if ( flags & QgsLabeling::LinePlacementFlag::OnLine )
749 parts << QStringLiteral(
"OL" );
750 if ( flags & QgsLabeling::LinePlacementFlag::AboveLine )
751 parts << QStringLiteral(
"AL" );
752 if ( flags & QgsLabeling::LinePlacementFlag::BelowLine )
753 parts << QStringLiteral(
"BL" );
754 if ( !( flags & QgsLabeling::LinePlacementFlag::MapOrientation ) )
755 parts << QStringLiteral(
"LO" );
756 return parts.join(
',' );
761 QgsLabeling::LinePlacementFlags flags = QgsLabeling::LinePlacementFlags();
762 const QStringList flagList =
string.split(
',' );
763 bool foundLineOrientationFlag =
false;
764 for (
const QString &flag : flagList )
766 QString cleaned = flag.trimmed().toUpper();
767 if ( cleaned == QLatin1String(
"OL" ) )
768 flags |= QgsLabeling::LinePlacementFlag::OnLine;
769 else if ( cleaned == QLatin1String(
"AL" ) )
770 flags |= QgsLabeling::LinePlacementFlag::AboveLine;
771 else if ( cleaned == QLatin1String(
"BL" ) )
772 flags |= QgsLabeling::LinePlacementFlag::BelowLine;
773 else if ( cleaned == QLatin1String(
"LO" ) )
774 foundLineOrientationFlag =
true;
776 if ( !foundLineOrientationFlag )
777 flags |= QgsLabeling::LinePlacementFlag::MapOrientation;
The QgsAbstractLabelProvider class is an interface class.
virtual void drawUnplacedLabel(QgsRenderContext &context, pal::LabelPosition *label) const
Draw an unplaced label.
virtual void stopRender(QgsRenderContext &context)
To be called after rendering is complete.
void setEngine(const QgsLabelingEngine *engine)
Associate provider with a labeling engine (should be only called internally from QgsLabelingEngine)
virtual void drawLabel(QgsRenderContext &context, pal::LabelPosition *label) const =0
Draw this label at the position determined by the labeling engine.
QgsPalLayerSettings::Placement placement() const
What placement strategy to use for the labels.
virtual QList< QgsLabelFeature * > labelFeatures(QgsRenderContext &context)=0
Returns list of label features (they are owned by the provider and thus deleted on its destruction)
double priority() const
Default priority of labels (may be overridden by individual labels)
virtual void drawLabelBackground(QgsRenderContext &context, pal::LabelPosition *label) const
Draw the background for the specified label.
QString name() const
Name of the layer (for statistics, debugging etc.) - does not need to be unique.
virtual void startRender(QgsRenderContext &context)
To be called before rendering of labels begins.
Flags flags() const
Flags associated with the provider.
QgsLabelObstacleSettings::ObstacleType obstacleType() const
How the feature geometries will work as obstacles.
@ DrawAllLabels
Whether all features will be labelled even though overlaps occur.
@ MergeConnectedLines
Whether adjacent lines (with the same label text) should be merged.
@ DrawLabels
Whether the labels should be rendered.
@ CentroidMustBeInside
Whether location of centroid must be inside of polygons.
QgsPalLayerSettings::UpsideDownLabels upsidedownLabels() const
How to handle labels that would be upside down.
virtual QList< QgsAbstractLabelProvider * > subProviders()
Returns list of child providers - useful if the provider needs to put labels into more layers with di...
QString layerId() const
Returns ID of associated layer, or empty string if no layer is associated with the provider.
QgsAbstractLabelProvider(QgsMapLayer *layer, const QString &providerId=QString())
Construct the provider with default values.
QgsDefaultLabelingEngine()
Construct the labeling engine with default settings.
void run(QgsRenderContext &context) override
Runs the labeling job.
RAII class to pop scope from an expression context on destruction.
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
A geometry is the spatial representation of a feature.
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
OperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Label blocking region (in map coordinates and CRS).
The QgsLabelFeature class describes a feature that should be used within the labeling engine.
QSizeF size(double angle=0.0) const
Size of the label (in map units)
QgsAbstractLabelProvider * provider() const
Returns provider of this instance.
const QgsSymbol * symbol()
Returns the feature symbol associated with this label.
void setSymbol(const QgsSymbol *symbol)
Sets the feature symbol associated with this label.
pal::Layer * mLayer
Pointer to PAL layer (assigned when registered to PAL)
QgsFeature feature() const
Returns the original feature associated with this label.
double zIndex() const
Returns the label's z-index.
Helper class for sorting labels into correct draw order.
QgsLabelSorter(const QgsMapSettings &mapSettings)
bool operator()(pal::LabelPosition *lp1, pal::LabelPosition *lp2) const
Stores global configuration for labeling engine.
bool testFlag(Flag f) const
Test whether a particular flag is enabled.
Flags flags() const
Gets flags of the labeling engine.
@ UseAllLabels
Whether to draw all labels even if there would be collisions.
@ UsePartialCandidates
Whether to use also label candidates that are partially outside of the map view.
@ CollectUnplacedLabels
Whether unplaced labels should be collected in the labeling results (regardless of whether they are b...
@ DrawUnplacedLabels
Whether to render unplaced labels as an indicator/warning for users.
@ DrawCandidates
Whether to draw rectangles of generated candidates (good for debugging)
PlacementEngineVersion placementVersion() const
Returns the placement engine version, which dictates how the label placement problem is solved.
double maximumPolygonCandidatesPerCmSquared() const
Returns the maximum number of polygon label candidate positions per centimeter squared.
double maximumLineCandidatesPerCm() const
Returns the maximum number of line label candidate positions per centimeter.
The QgsLabelingEngine class provides map labeling functionality.
std::unique_ptr< pal::Pal > mPal
std::unique_ptr< QgsLabelingResults > mResults
Resulting labeling layout.
QgsMapSettings mMapSettings
Associated map settings instance.
void solve(QgsRenderContext &context)
Solves the label problem.
QList< pal::LabelPosition * > mUnlabeled
std::unique_ptr< pal::Problem > mProblem
const QgsMapSettings & mapSettings() const
Gets associated map settings.
QList< pal::LabelPosition * > mLabels
QgsLabelingResults * takeResults()
Returns pointer to recently computed results and pass the ownership of results to the caller.
void cleanup()
Cleans up the engine following a call to registerLabels() or solve().
void setMapSettings(const QgsMapSettings &mapSettings)
Associate map settings instance.
void registerLabels(QgsRenderContext &context)
Runs the label registration step.
QList< QgsAbstractLabelProvider * > mSubProviders
void addProvider(QgsAbstractLabelProvider *provider)
Add provider of label features. Takes ownership of the provider.
void drawLabels(QgsRenderContext &context, const QString &layerId=QString())
Draws labels to the specified render context.
QStringList participatingLayerIds() const
Returns a list of layer IDs for layers with providers in the engine.
QList< QgsMapLayer * > participatingLayers() const
Returns a list of layers with providers in the engine.
void processProvider(QgsAbstractLabelProvider *provider, QgsRenderContext &context, pal::Pal &p)
QgsLabelingEngine()
Construct the labeling engine with default settings.
void removeProvider(QgsAbstractLabelProvider *provider)
Remove provider if the provider's initialization failed. Provider instance is deleted.
QList< QgsAbstractLabelProvider * > mProviders
List of providers (the are owned by the labeling engine)
virtual ~QgsLabelingEngine()
Clean up everything (especially the registered providers)
Class that stores computed placement from labeling engine.
static QVector< QgsPalLayerSettings::PredefinedPointPosition > decodePredefinedPositionOrder(const QString &positionString)
Decodes a string to an ordered list of predefined point label positions.
static QString encodeLinePlacementFlags(QgsLabeling::LinePlacementFlags flags)
Encodes line placement flags to a string.
static QString encodePredefinedPositionOrder(const QVector< QgsPalLayerSettings::PredefinedPointPosition > &positions)
Encodes an ordered list of predefined point label positions to a string.
static QgsLabeling::LinePlacementFlags decodeLinePlacementFlags(const QString &string)
Decodes a string to set of line placement flags.
Base class for all map layer types.
The QgsMapSettings class contains configuration for rendering of the map.
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
QStringList layerIds() const
Returns the list of layer IDs which will be rendered in the map.
QgsGeometry labelBoundaryGeometry() const
Returns the label boundary geometry, which restricts where in the rendered map labels are permitted t...
QList< QgsLabelBlockingRegion > labelBlockingRegions() const
Returns the list of regions to avoid placing labels within.
const QgsMapToPixel & mapToPixel() const
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns the global configuration of the labeling engine.
double rotation() const
Returns the rotation of the resulting map image, in degrees clockwise.
Perform transforms between map coordinates and device coordinates.
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
static void drawLabelCandidateRect(pal::LabelPosition *lp, QPainter *painter, const QgsMapToPixel *xform, QList< QgsLabelCandidate > *candidates=nullptr)
Contains settings for how a map layer will be labeled.
@ ShowDefined
Show upside down when rotation is layer- or data-defined.
@ Upright
Upside-down labels (90 <= angle < 270) are shown upright.
@ ShowAll
Show upside down for all labels, including dynamic ones.
PredefinedPointPosition
Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode.
@ BottomSlightlyLeft
Label below point, slightly left of center.
@ BottomMiddle
Label directly below point.
@ BottomSlightlyRight
Label below point, slightly right of center.
@ MiddleLeft
Label on left of point.
@ TopSlightlyRight
Label on top of point, slightly right of center.
@ TopSlightlyLeft
Label on top of point, slightly left of center.
@ MiddleRight
Label on right of point.
@ TopMiddle
Label directly above point.
@ BottomRight
Label on bottom right of point.
@ BottomLeft
Label on bottom-left of point.
@ TopRight
Label on top-right of point.
@ TopLeft
Label on top-left of point.
A rectangle specified with double values.
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToMapUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
void finalize()
Finalizes and cleans up the engine following the rendering of labels for the last layer to be labeled...
void run(QgsRenderContext &context) override
Runs the labeling job.
QgsStagedRenderLabelingEngine()
Construct the labeling engine with default settings.
void renderLabelsForLayer(QgsRenderContext &context, const QString &layerId)
Renders all the labels which belong only to the layer with matching layerId to the specified render c...
@ RenderMillimeters
Millimeters.
QgsLabelFeature * feature()
Returns the parent feature.
LabelPosition is a candidate feature label position.
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
A set of features which influence the labeling process.
void setUpsidedownLabels(UpsideDownLabels ud)
Sets how upside down labels will be handled within the layer.
bool registerFeature(QgsLabelFeature *label)
Register a feature in the layer.
void setObstacleType(QgsLabelObstacleSettings::ObstacleType obstacleType)
Sets the obstacle type, which controls how features within the layer act as obstacles for labels.
void setMergeConnectedLines(bool merge)
Sets whether connected lines should be merged before labeling.
QgsAbstractLabelProvider * provider() const
Returns pointer to the associated provider.
void setCentroidInside(bool forceInside)
Sets whether labels placed at the centroid of features within the layer are forced to be placed insid...
Layer * addLayer(QgsAbstractLabelProvider *provider, const QString &layerName, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, bool displayAll=false)
add a new layer
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define QgsDebugMsgLevel(str, level)