QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgslabelingengine.cpp
Go to the documentation of this file.
1 
2 /***************************************************************************
3  qgslabelingengine.cpp
4  --------------------------------------
5  Date : September 2015
6  Copyright : (C) 2015 by Martin Dobias
7  Email : wonder dot sk at gmail dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgslabelingengine.h"
18 
19 #include "qgslogger.h"
20 
21 #include "feature.h"
22 #include "labelposition.h"
23 #include "layer.h"
24 #include "pal.h"
25 #include "problem.h"
26 #include "qgsrendercontext.h"
27 #include "qgsmaplayer.h"
28 
29 
30 // helper function for checking for job cancellation within PAL
31 static bool _palIsCanceled( void *ctx )
32 {
33  return ( reinterpret_cast< QgsRenderContext * >( ctx ) )->renderingStopped();
34 }
35 
42 {
43  public:
44 
45  explicit QgsLabelSorter( const QgsMapSettings &mapSettings )
46  : mMapSettings( mapSettings )
47  {}
48 
50  {
51  QgsLabelFeature *lf1 = lp1->getFeaturePart()->feature();
52  QgsLabelFeature *lf2 = lp2->getFeaturePart()->feature();
53 
54  if ( !qgsDoubleNear( lf1->zIndex(), lf2->zIndex() ) )
55  return lf1->zIndex() < lf2->zIndex();
56 
57  //equal z-index, so fallback to respecting layer render order
58  QStringList layerIds = mMapSettings.layerIds();
59  int layer1Pos = layerIds.indexOf( lf1->provider()->layerId() );
60  int layer2Pos = layerIds.indexOf( lf2->provider()->layerId() );
61  if ( layer1Pos != layer2Pos && layer1Pos >= 0 && layer2Pos >= 0 )
62  return layer1Pos > layer2Pos; //higher positions are rendered first
63 
64  //same layer, so render larger labels first
65  return lf1->size().width() * lf1->size().height() > lf2->size().width() * lf2->size().height();
66  }
67 
68  private:
69 
70  const QgsMapSettings &mMapSettings;
71 };
72 
73 
75  : mResults( new QgsLabelingResults )
76 {}
77 
79 {
80  qDeleteAll( mProviders );
81  qDeleteAll( mSubProviders );
82 }
83 
85 {
87  if ( mResults )
88  mResults->setMapSettings( mapSettings );
89 }
90 
91 QList< QgsMapLayer * > QgsLabelingEngine::participatingLayers() const
92 {
93  QSet< QgsMapLayer * > layers;
94  Q_FOREACH ( QgsAbstractLabelProvider *provider, mProviders )
95  {
96  if ( provider->layer() )
97  layers << provider->layer();
98  }
99  Q_FOREACH ( QgsAbstractLabelProvider *provider, mSubProviders )
100  {
101  if ( provider->layer() )
102  layers << provider->layer();
103  }
104  return layers.toList();
105 }
106 
108 {
109  provider->setEngine( this );
110  mProviders << provider;
111 }
112 
114 {
115  int idx = mProviders.indexOf( provider );
116  if ( idx >= 0 )
117  {
118  delete mProviders.takeAt( idx );
119  }
120 }
121 
123 {
124  QgsAbstractLabelProvider::Flags flags = provider->flags();
125 
126  // create the pal layer
127  pal::Layer *l = p.addLayer( provider,
128  provider->name(),
129  provider->placement(),
130  provider->priority(),
131  true,
132  flags.testFlag( QgsAbstractLabelProvider::DrawLabels ),
133  flags.testFlag( QgsAbstractLabelProvider::DrawAllLabels ) );
134 
135  // set label mode (label per feature is the default)
137 
138  // set whether adjacent lines should be merged
140 
141  // set obstacle type
142  l->setObstacleType( provider->obstacleType() );
143 
144  // set whether location of centroid must be inside of polygons
146 
147  // set how to show upside-down labels
148  pal::Layer::UpsideDownLabels upsdnlabels;
149  switch ( provider->upsidedownLabels() )
150  {
152  upsdnlabels = pal::Layer::Upright;
153  break;
155  upsdnlabels = pal::Layer::ShowDefined;
156  break;
158  upsdnlabels = pal::Layer::ShowAll;
159  break;
160  default:
161  Q_ASSERT( "unsupported upside-down label setting" && false );
162  return;
163  }
164  l->setUpsidedownLabels( upsdnlabels );
165 
166 
167  QList<QgsLabelFeature *> features = provider->labelFeatures( context );
168 
169  Q_FOREACH ( QgsLabelFeature *feature, features )
170  {
171  try
172  {
173  l->registerFeature( feature );
174  }
175  catch ( std::exception &e )
176  {
177  Q_UNUSED( e );
178  QgsDebugMsgLevel( QStringLiteral( "Ignoring feature %1 due PAL exception:" ).arg( feature->id() ) + QString::fromLatin1( e.what() ), 4 );
179  continue;
180  }
181  }
182 
183  // any sub-providers?
184  Q_FOREACH ( QgsAbstractLabelProvider *subProvider, provider->subProviders() )
185  {
186  mSubProviders << subProvider;
187  processProvider( subProvider, context, p );
188  }
189 }
190 
191 
193 {
195 
196  pal::Pal p;
198  switch ( settings.searchMethod() )
199  {
200  default:
202  s = pal::CHAIN;
203  break;
205  s = pal::POPMUSIC_TABU;
206  break;
209  break;
212  break;
214  s = pal::FALP;
215  break;
216  }
217  p.setSearch( s );
218 
219  // set number of candidates generated per feature
220  int candPoint, candLine, candPolygon;
221  settings.numCandidatePositions( candPoint, candLine, candPolygon );
222  p.setPointP( candPoint );
223  p.setLineP( candLine );
224  p.setPolyP( candPolygon );
225 
227 
228 
229  // for each provider: get labels and register them in PAL
230  Q_FOREACH ( QgsAbstractLabelProvider *provider, mProviders )
231  {
232  bool appendedLayerScope = false;
233  if ( QgsMapLayer *ml = provider->layer() )
234  {
235  appendedLayerScope = true;
237  }
238  processProvider( provider, context, p );
239  if ( appendedLayerScope )
240  delete context.expressionContext().popScope();
241  }
242 
243 
244  // NOW DO THE LAYOUT (from QgsPalLabeling::drawLabeling)
245 
246  QPainter *painter = context.painter();
247 
249  QPolygonF visiblePoly = mMapSettings.visiblePolygon();
250  visiblePoly.append( visiblePoly.at( 0 ) ); //close polygon
251  QgsGeometry mapBoundaryGeom = QgsGeometry::fromQPolygonF( visiblePoly );
252 
253  if ( !qgsDoubleNear( mMapSettings.rotation(), 0.0 ) )
254  {
255  //PAL features are prerotated, so extent also needs to be unrotated
257  // yes - this is rotated in the opposite direction... phew, this is confusing!
258  mapBoundaryGeom.rotate( mMapSettings.rotation(), mMapSettings.visibleExtent().center() );
259  }
260 
261  QgsRectangle extent = extentGeom.boundingBox();
262 
263 
264  p.registerCancelationCallback( &_palIsCanceled, reinterpret_cast< void * >( &context ) );
265 
266  QTime t;
267  t.start();
268 
269  // do the labeling itself
270  std::unique_ptr< pal::Problem > problem;
271  try
272  {
273  problem = p.extractProblem( extent, mapBoundaryGeom );
274  }
275  catch ( std::exception &e )
276  {
277  Q_UNUSED( e );
278  QgsDebugMsgLevel( "PAL EXCEPTION :-( " + QString::fromLatin1( e.what() ), 4 );
279  return;
280  }
281 
282  if ( context.renderingStopped() )
283  {
284  return; // it has been canceled
285  }
286 
287 #if 1 // XXX strk
288  // features are pre-rotated but not scaled/translated,
289  // so we only disable rotation here. Ideally, they'd be
290  // also pre-scaled/translated, as suggested here:
291  // https://issues.qgis.org/issues/11856
293  xform.setMapRotation( 0, 0, 0 );
294 #else
295  const QgsMapToPixel &xform = mMapSettings->mapToPixel();
296 #endif
297 
298  // draw rectangles with all candidates
299  // this is done before actual solution of the problem
300  // before number of candidates gets reduced
301  // TODO mCandidates.clear();
302  if ( settings.testFlag( QgsLabelingEngineSettings::DrawCandidates ) && problem )
303  {
304  painter->setBrush( Qt::NoBrush );
305  for ( int i = 0; i < problem->getNumFeatures(); i++ )
306  {
307  for ( int j = 0; j < problem->getFeatureCandidateCount( i ); j++ )
308  {
309  pal::LabelPosition *lp = problem->getFeatureCandidate( i, j );
310 
311  QgsPalLabeling::drawLabelCandidateRect( lp, painter, &xform );
312  }
313  }
314  }
315 
316  // find the solution
317  QList<pal::LabelPosition *> labels = p.solveProblem( problem.get(), settings.testFlag( QgsLabelingEngineSettings::UseAllLabels ) );
318 
319  QgsDebugMsgLevel( QStringLiteral( "LABELING work: %1 ms ... labels# %2" ).arg( t.elapsed() ).arg( labels.size() ), 4 );
320  t.restart();
321 
322  if ( context.renderingStopped() )
323  {
324  return;
325  }
326  painter->setRenderHint( QPainter::Antialiasing );
327 
328  // sort labels
329  std::sort( labels.begin(), labels.end(), QgsLabelSorter( mMapSettings ) );
330 
331  // draw the labels
332  for ( pal::LabelPosition *label : qgis::as_const( labels ) )
333  {
334  if ( context.renderingStopped() )
335  break;
336 
337  QgsLabelFeature *lf = label->getFeaturePart()->feature();
338  if ( !lf )
339  {
340  continue;
341  }
342 
343  lf->provider()->drawLabel( context, label );
344  }
345 
346  // Reset composition mode for further drawing operations
347  painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
348 
349  QgsDebugMsgLevel( QStringLiteral( "LABELING draw: %1 ms" ).arg( t.elapsed() ), 4 );
350 }
351 
353 {
354  return mResults.release();
355 }
356 
357 
359 
361 {
362  return mLayer ? mLayer->provider() : nullptr;
363 
364 }
365 
367  : mLayerId( layer ? layer->id() : QString() )
368  , mLayer( layer )
369  , mProviderId( providerId )
370  , mFlags( DrawLabels )
371  , mPlacement( QgsPalLayerSettings::AroundPoint )
372  , mPriority( 0.5 )
373  , mObstacleType( QgsPalLayerSettings::PolygonInterior )
374  , mUpsidedownLabels( QgsPalLayerSettings::Upright )
375 {
376 }
377 
378 
379 //
380 // QgsLabelingUtils
381 //
382 
383 QString QgsLabelingUtils::encodePredefinedPositionOrder( const QVector<QgsPalLayerSettings::PredefinedPointPosition> &positions )
384 {
385  QStringList predefinedOrderString;
386  Q_FOREACH ( QgsPalLayerSettings::PredefinedPointPosition position, positions )
387  {
388  switch ( position )
389  {
391  predefinedOrderString << QStringLiteral( "TL" );
392  break;
394  predefinedOrderString << QStringLiteral( "TSL" );
395  break;
397  predefinedOrderString << QStringLiteral( "T" );
398  break;
400  predefinedOrderString << QStringLiteral( "TSR" );
401  break;
403  predefinedOrderString << QStringLiteral( "TR" );
404  break;
406  predefinedOrderString << QStringLiteral( "L" );
407  break;
409  predefinedOrderString << QStringLiteral( "R" );
410  break;
412  predefinedOrderString << QStringLiteral( "BL" );
413  break;
415  predefinedOrderString << QStringLiteral( "BSL" );
416  break;
418  predefinedOrderString << QStringLiteral( "B" );
419  break;
421  predefinedOrderString << QStringLiteral( "BSR" );
422  break;
424  predefinedOrderString << QStringLiteral( "BR" );
425  break;
426  }
427  }
428  return predefinedOrderString.join( QStringLiteral( "," ) );
429 }
430 
431 QVector<QgsPalLayerSettings::PredefinedPointPosition> QgsLabelingUtils::decodePredefinedPositionOrder( const QString &positionString )
432 {
433  QVector<QgsPalLayerSettings::PredefinedPointPosition> result;
434  QStringList predefinedOrderList = positionString.split( ',' );
435  Q_FOREACH ( const QString &position, predefinedOrderList )
436  {
437  QString cleaned = position.trimmed().toUpper();
438  if ( cleaned == QLatin1String( "TL" ) )
440  else if ( cleaned == QLatin1String( "TSL" ) )
442  else if ( cleaned == QLatin1String( "T" ) )
444  else if ( cleaned == QLatin1String( "TSR" ) )
446  else if ( cleaned == QLatin1String( "TR" ) )
448  else if ( cleaned == QLatin1String( "L" ) )
450  else if ( cleaned == QLatin1String( "R" ) )
452  else if ( cleaned == QLatin1String( "BL" ) )
454  else if ( cleaned == QLatin1String( "BSL" ) )
456  else if ( cleaned == QLatin1String( "B" ) )
458  else if ( cleaned == QLatin1String( "BSR" ) )
460  else if ( cleaned == QLatin1String( "BR" ) )
462  }
463  return result;
464 }
465 
466 QString QgsLabelingUtils::encodeLinePlacementFlags( pal::LineArrangementFlags flags )
467 {
468  QStringList parts;
469  if ( flags & pal::FLAG_ON_LINE )
470  parts << QStringLiteral( "OL" );
471  if ( flags & pal::FLAG_ABOVE_LINE )
472  parts << QStringLiteral( "AL" );
473  if ( flags & pal::FLAG_BELOW_LINE )
474  parts << QStringLiteral( "BL" );
475  if ( !( flags & pal::FLAG_MAP_ORIENTATION ) )
476  parts << QStringLiteral( "LO" );
477  return parts.join( ',' );
478 }
479 
480 pal::LineArrangementFlags QgsLabelingUtils::decodeLinePlacementFlags( const QString &string )
481 {
482  pal::LineArrangementFlags flags = nullptr;
483  const QStringList flagList = string.split( ',' );
484  bool foundLineOrientationFlag = false;
485  for ( const QString &flag : flagList )
486  {
487  QString cleaned = flag.trimmed().toUpper();
488  if ( cleaned == QLatin1String( "OL" ) )
489  flags |= pal::FLAG_ON_LINE;
490  else if ( cleaned == QLatin1String( "AL" ) )
491  flags |= pal::FLAG_ABOVE_LINE;
492  else if ( cleaned == QLatin1String( "BL" ) )
493  flags |= pal::FLAG_BELOW_LINE;
494  else if ( cleaned == QLatin1String( "LO" ) )
495  foundLineOrientationFlag = true;
496  }
497  if ( !foundLineOrientationFlag )
498  flags |= pal::FLAG_MAP_ORIENTATION;
499  return flags;
500 }
Label below point, slightly right of center.
void processProvider(QgsAbstractLabelProvider *provider, QgsRenderContext &context, pal::Pal &p)
Layer * addLayer(QgsAbstractLabelProvider *provider, const QString &layerName, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, bool displayAll=false)
add a new layer
Definition: pal.cpp:103
QString name() const
Name of the layer (for statistics, debugging etc.) - does not need to be unique.
A rectangle specified with double values.
Definition: qgsrectangle.h:40
Base class for all map layer types.
Definition: qgsmaplayer.h:63
Label on bottom-left of point.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns the global configuration of the labeling engine.
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
void addProvider(QgsAbstractLabelProvider *provider)
Add provider of label features. Takes ownership of the provider.
QList< QgsAbstractLabelProvider * > mProviders
List of providers (the are owned by the labeling engine)
Definition: pal.h:65
void removeProvider(QgsAbstractLabelProvider *provider)
Remove provider if the provider&#39;s initialization failed. Provider instance is deleted.
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:118
Label on top-left of point.
QgsAbstractLabelProvider(QgsMapLayer *layer, const QString &providerId=QString())
Construct the provider with default values.
static void drawLabelCandidateRect(pal::LabelPosition *lp, QPainter *painter, const QgsMapToPixel *xform, QList< QgsLabelCandidate > *candidates=nullptr)
QgsAbstractLabelProvider * provider() const
Returns provider of this instance.
A set of features which influence the labeling process.
Definition: layer.h:63
PredefinedPointPosition
Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:278
OperationResult rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
bool operator()(pal::LabelPosition *lp1, pal::LabelPosition *lp2) const
Whether to use also label candidates that are partially outside of the map view.
QgsLabelingEngine()
Construct the labeling engine with default settings.
QList< QgsAbstractLabelProvider * > mSubProviders
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
Main Pal labeling class.
Definition: pal.h:87
Is slower and best than TABU, worse and faster than TABU_CHAIN.
Definition: pal.h:64
UpsideDownLabels
Definition: layer.h:74
Label on top of point, slightly right of center.
void setMapSettings(const QgsMapSettings &mapSettings)
Associate map settings instance.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
void setUpsidedownLabels(UpsideDownLabels ud)
Sets how upside down labels will be handled within the layer.
Definition: layer.h:210
const QgsMapToPixel & mapToPixel() const
Search searchMethod() const
Which search method to use for removal collisions between labels.
void setShowPartial(bool show)
Set flag show partial label.
Definition: pal.cpp:532
Whether to label each part of multi-part features separately.
double rotation() const
Returns the rotation of the resulting map image, in degrees clockwise.
FeaturePart * getFeaturePart()
Returns the feature corresponding to this labelposition.
virtual QList< QgsLabelFeature * > labelFeatures(QgsRenderContext &context)=0
Returns list of label features (they are owned by the provider and thus deleted on its destruction) ...
QgsPalLayerSettings::UpsideDownLabels upsidedownLabels() const
How to handle labels that would be upside down.
void setObstacleType(QgsPalLayerSettings::ObstacleType obstacleType)
Sets the obstacle type, which controls how features within the layer act as obstacles for labels...
Definition: layer.h:162
void setCentroidInside(bool forceInside)
Sets whether labels placed at the centroid of features within the layer are forced to be placed insid...
Definition: layer.h:225
Is a little bit better than CHAIN but slower.
Definition: pal.h:63
Whether adjacent lines (with the same label text) should be merged.
std::unique_ptr< Problem > extractProblem(const QgsRectangle &extent, const QgsGeometry &mapBoundary)
Extracts the labeling problem for the specified map extent - only features within this extent will be...
Definition: pal.cpp:450
The QgsMapSettings class contains configuration for rendering of the map.
QSizeF size() const
Size of the label (in map units)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:36
Whether to draw all labels even if there would be collisions.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
static pal::LineArrangementFlags decodeLinePlacementFlags(const QString &string)
Decodes a string to set of line placement flags.
QList< QgsMapLayer * > participatingLayers() const
Returns a list of layers with providers in the engine.
QgsPalLayerSettings::Placement placement() const
What placement strategy to use for the labels.
Label on left of point.
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
bool renderingStopped() const
Returns TRUE if the rendering operation has been stopped and any ongoing rendering should be canceled...
bool testFlag(Flag f) const
Test whether a particular flag is enabled.
Show upside down for all labels, including dynamic ones.
Is the best but slowest.
Definition: pal.h:62
QStringList layerIds() const
Gets list of layer IDs for map rendering The layers are stored in the reverse order of how they are r...
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:229
void setPointP(int point_p)
set # candidates to generate for points features Higher the value is, longer Pal::labeller will spend...
Definition: pal.cpp:480
Whether location of centroid must be inside of polygons.
double priority() const
Default priority of labels (may be overridden by individual labels)
void setLineP(int line_p)
set maximum # candidates to generate for lines features Higher the value is, longer Pal::labeller wil...
Definition: pal.cpp:486
Upside-down labels (90 <= angle < 270) are shown upright.
Flags flags() const
Flags associated with the provider.
Whether all features will be labelled even though overlaps occur.
The QgsAbstractLabelProvider class is an interface class.
Whether to draw rectangles of generated candidates (good for debugging)
static QString encodeLinePlacementFlags(pal::LineArrangementFlags flags)
Encodes line placement flags to a string.
QString layerId() const
Returns ID of associated layer, or empty string if no layer is associated with the provider...
QgsLabelSorter(const QgsMapSettings &mapSettings)
const QgsMapSettings & mapSettings() const
Gets associated map settings.
QgsExpressionContext & expressionContext()
Gets the expression context.
double zIndex() const
Returns the label&#39;s z-index.
~QgsLabelingEngine()
Clean up everything (especially the registered providers)
bool registerFeature(QgsLabelFeature *label)
Register a feature in the layer.
Definition: layer.cpp:92
static QString encodePredefinedPositionOrder(const QVector< QgsPalLayerSettings::PredefinedPointPosition > &positions)
Encodes an ordered list of predefined point label positions to a string.
void run(QgsRenderContext &context)
compute the labeling with given map settings and providers
virtual QList< QgsAbstractLabelProvider * > subProviders()
Returns list of child providers - useful if the provider needs to put labels into more layers with di...
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
std::unique_ptr< QgsLabelingResults > mResults
Resulting labeling layout.
void setPolyP(int poly_p)
set maximum # candidates to generate for polygon features Higher the value is, longer Pal::labeller w...
Definition: pal.cpp:492
QgsMapSettings mMapSettings
Associated map settings instance.
void registerCancelationCallback(FnIsCanceled fnCanceled, void *context)
Register a function that returns whether this job has been canceled - PAL calls it during the computa...
Definition: pal.cpp:444
QgsPalLayerSettings::ObstacleType obstacleType() const
How the feature geometries will work as obstacles.
QgsLabelingResults * takeResults()
Returns pointer to recently computed results and pass the ownership of results to the caller...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Stores global configuration for labeling engine.
QList< LabelPosition * > solveProblem(Problem *prob, bool displayAll)
Definition: pal.cpp:455
void setLabelMode(LabelMode mode)
Sets the layer&#39;s labeling mode.
Definition: layer.h:184
Label below point, slightly left of center.
Helper class for sorting labels into correct draw order.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
LabelPosition is a candidate feature label position.
Definition: labelposition.h:55
Label on top of point, slightly left of center.
Label on right of point.
void numCandidatePositions(int &candPoint, int &candLine, int &candPolygon) const
Gets number of candidate positions that will be generated for each label feature (default to 8) ...
Whether the labels should be rendered.
Class that stores computed placement from labeling engine.
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
static QVector< QgsPalLayerSettings::PredefinedPointPosition > decodePredefinedPositionOrder(const QString &positionString)
Decodes a string to an ordered list of predefined point label positions.
SearchMethod
Search method to use.
Definition: pal.h:59
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Show upside down when rotation is layer- or data-defined.
virtual void drawLabel(QgsRenderContext &context, pal::LabelPosition *label) const =0
draw this label at the position determined by the labeling engine
Is the worst but fastest method.
Definition: pal.h:61
void setSearch(SearchMethod method)
Select the search method to use.
Definition: pal.cpp:572
void setEngine(const QgsLabelingEngine *engine)
Associate provider with a labeling engine (should be only called internally from QgsLabelingEngine) ...
void setMergeConnectedLines(bool merge)
Sets whether connected lines should be merged before labeling.
Definition: layer.h:197
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)