QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 #include "qgssymbol.h"
31 
32 // helper function for checking for job cancellation within PAL
33 static bool _palIsCanceled( void *ctx )
34 {
35  return ( reinterpret_cast< QgsRenderContext * >( ctx ) )->renderingStopped();
36 }
37 
44 {
45  public:
46 
47  explicit QgsLabelSorter( const QgsMapSettings &mapSettings )
48  : mMapSettings( mapSettings )
49  {}
50 
52  {
53  QgsLabelFeature *lf1 = lp1->getFeaturePart()->feature();
54  QgsLabelFeature *lf2 = lp2->getFeaturePart()->feature();
55 
56  if ( !qgsDoubleNear( lf1->zIndex(), lf2->zIndex() ) )
57  return lf1->zIndex() < lf2->zIndex();
58 
59  //equal z-index, so fallback to respecting layer render order
60  QStringList layerIds = mMapSettings.layerIds();
61  int layer1Pos = layerIds.indexOf( lf1->provider()->layerId() );
62  int layer2Pos = layerIds.indexOf( lf2->provider()->layerId() );
63  if ( layer1Pos != layer2Pos && layer1Pos >= 0 && layer2Pos >= 0 )
64  return layer1Pos > layer2Pos; //higher positions are rendered first
65 
66  //same layer, so render larger labels first
67  return lf1->size().width() * lf1->size().height() > lf2->size().width() * lf2->size().height();
68  }
69 
70  private:
71 
72  const QgsMapSettings &mMapSettings;
73 };
74 
75 //
76 // QgsLabelingEngine
77 //
78 
80  : mResults( new QgsLabelingResults )
81 {}
82 
84 {
85  qDeleteAll( mProviders );
86  qDeleteAll( mSubProviders );
87 }
88 
90 {
92  if ( mResults )
93  mResults->setMapSettings( mapSettings );
94 }
95 
96 QList< QgsMapLayer * > QgsLabelingEngine::participatingLayers() const
97 {
98  QList< QgsMapLayer * > layers;
99 
100  // try to return layers sorted in the desired z order for rendering
101  QList< QgsAbstractLabelProvider * > providersByZ = mProviders;
102  std::sort( providersByZ.begin(), providersByZ.end(),
103  []( const QgsAbstractLabelProvider * a, const QgsAbstractLabelProvider * b ) -> bool
104  {
105  const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
106  const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
107 
108  if ( providerA && providerB )
109  {
110  return providerA->settings().zIndex < providerB->settings().zIndex ;
111  }
112  return false;
113  } );
114 
115  QList< QgsAbstractLabelProvider * > subProvidersByZ = mSubProviders;
116  std::sort( subProvidersByZ.begin(), subProvidersByZ.end(),
117  []( const QgsAbstractLabelProvider * a, const QgsAbstractLabelProvider * b ) -> bool
118  {
119  const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
120  const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
121 
122  if ( providerA && providerB )
123  {
124  return providerA->settings().zIndex < providerB->settings().zIndex ;
125  }
126  return false;
127  } );
128 
129  for ( QgsAbstractLabelProvider *provider : qgis::as_const( providersByZ ) )
130  {
131  if ( provider->layer() && !layers.contains( provider->layer() ) )
132  layers << provider->layer();
133  }
134  for ( QgsAbstractLabelProvider *provider : qgis::as_const( subProvidersByZ ) )
135  {
136  if ( provider->layer() && !layers.contains( provider->layer() ) )
137  layers << provider->layer();
138  }
139  return layers;
140 }
141 
143 {
144  QStringList layers;
145 
146  // try to return layers sorted in the desired z order for rendering
147  QList< QgsAbstractLabelProvider * > providersByZ = mProviders;
148  std::sort( providersByZ.begin(), providersByZ.end(),
149  []( const QgsAbstractLabelProvider * a, const QgsAbstractLabelProvider * b ) -> bool
150  {
151  const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
152  const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
153 
154  if ( providerA && providerB )
155  {
156  return providerA->settings().zIndex < providerB->settings().zIndex ;
157  }
158  return false;
159  } );
160 
161  QList< QgsAbstractLabelProvider * > subProvidersByZ = mSubProviders;
162  std::sort( subProvidersByZ.begin(), subProvidersByZ.end(),
163  []( const QgsAbstractLabelProvider * a, const QgsAbstractLabelProvider * b ) -> bool
164  {
165  const QgsVectorLayerLabelProvider *providerA = dynamic_cast<const QgsVectorLayerLabelProvider *>( a );
166  const QgsVectorLayerLabelProvider *providerB = dynamic_cast<const QgsVectorLayerLabelProvider *>( b );
167 
168  if ( providerA && providerB )
169  {
170  return providerA->settings().zIndex < providerB->settings().zIndex ;
171  }
172  return false;
173  } );
174 
175  for ( QgsAbstractLabelProvider *provider : qgis::as_const( providersByZ ) )
176  {
177  if ( !layers.contains( provider->layerId() ) )
178  layers << provider->layerId();
179  }
180  for ( QgsAbstractLabelProvider *provider : qgis::as_const( subProvidersByZ ) )
181  {
182  if ( !layers.contains( provider->layerId() ) )
183  layers << provider->layerId();
184  }
185  return layers;
186 }
187 
189 {
190  provider->setEngine( this );
191  mProviders << provider;
192 }
193 
195 {
196  int idx = mProviders.indexOf( provider );
197  if ( idx >= 0 )
198  {
199  delete mProviders.takeAt( idx );
200  }
201 }
202 
204 {
205  QgsAbstractLabelProvider::Flags flags = provider->flags();
206 
207  // create the pal layer
208  pal::Layer *l = p.addLayer( provider,
209  provider->name(),
210  provider->placement(),
211  provider->priority(),
212  true,
213  flags.testFlag( QgsAbstractLabelProvider::DrawLabels ),
214  flags.testFlag( QgsAbstractLabelProvider::DrawAllLabels ) );
215 
216  // set whether adjacent lines should be merged
218 
219  // set obstacle type
220  l->setObstacleType( provider->obstacleType() );
221 
222  // set whether location of centroid must be inside of polygons
224 
225  // set how to show upside-down labels
227  switch ( provider->upsidedownLabels() )
228  {
230  upsdnlabels = pal::Layer::Upright;
231  break;
233  upsdnlabels = pal::Layer::ShowDefined;
234  break;
236  upsdnlabels = pal::Layer::ShowAll;
237  break;
238  }
239  l->setUpsidedownLabels( upsdnlabels );
240 
241 
242  const QList<QgsLabelFeature *> features = provider->labelFeatures( context );
243 
244  for ( QgsLabelFeature *feature : features )
245  {
246  try
247  {
248  l->registerFeature( feature );
249  }
250  catch ( std::exception &e )
251  {
252  Q_UNUSED( e )
253  QgsDebugMsgLevel( QStringLiteral( "Ignoring feature %1 due PAL exception:" ).arg( feature->id() ) + QString::fromLatin1( e.what() ), 4 );
254  continue;
255  }
256  }
257 
258  // any sub-providers?
259  const auto subproviders = provider->subProviders();
260  for ( QgsAbstractLabelProvider *subProvider : subproviders )
261  {
262  mSubProviders << subProvider;
263  processProvider( subProvider, context, p );
264  }
265 }
266 
268 {
270 
271  mPal = qgis::make_unique< pal::Pal >();
272 
273  mPal->setMaximumLineCandidatesPerMapUnit( settings.maximumLineCandidatesPerCm() / context.convertToMapUnits( 10, QgsUnitTypes::RenderMillimeters ) );
274  mPal->setMaximumPolygonCandidatesPerMapUnitSquared( settings.maximumPolygonCandidatesPerCmSquared() / std::pow( context.convertToMapUnits( 10, QgsUnitTypes::RenderMillimeters ), 2 ) );
275 
276  mPal->setShowPartialLabels( settings.testFlag( QgsLabelingEngineSettings::UsePartialCandidates ) );
277  mPal->setPlacementVersion( settings.placementVersion() );
278 
279  // for each provider: get labels and register them in PAL
280  for ( QgsAbstractLabelProvider *provider : qgis::as_const( mProviders ) )
281  {
282  std::unique_ptr< QgsExpressionContextScopePopper > layerScopePopper;
283  if ( QgsMapLayer *ml = provider->layer() )
284  {
285  layerScopePopper = qgis::make_unique< QgsExpressionContextScopePopper >( context.expressionContext(), QgsExpressionContextUtils::layerScope( ml ) );
286  }
287  processProvider( provider, context, *mPal );
288  }
289 }
290 
292 {
293  Q_ASSERT( mPal.get() );
294 
295  // NOW DO THE LAYOUT (from QgsPalLabeling::drawLabeling)
297 
298  QPainter *painter = context.painter();
299 
301  QPolygonF visiblePoly = mMapSettings.visiblePolygon();
302  visiblePoly.append( visiblePoly.at( 0 ) ); //close polygon
303 
304  // get map label boundary geometry - if one hasn't been explicitly set, we use the whole of the map's visible polygon
306 
307  // label blocking regions work by "chopping away" those regions from the permissible labeling area
308  const QList< QgsLabelBlockingRegion > blockingRegions = mMapSettings.labelBlockingRegions();
309  for ( const QgsLabelBlockingRegion &region : blockingRegions )
310  {
311  mapBoundaryGeom = mapBoundaryGeom.difference( region.geometry );
312  }
313 
315  {
316  // draw map boundary
317  QgsFeature f;
318  f.setGeometry( mapBoundaryGeom );
319  QgsStringMap properties;
320  properties.insert( QStringLiteral( "style" ), QStringLiteral( "no" ) );
321  properties.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
322  properties.insert( QStringLiteral( "color_border" ), QStringLiteral( "#0000ff" ) );
323  properties.insert( QStringLiteral( "width_border" ), QStringLiteral( "0.3" ) );
324  properties.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
325  std::unique_ptr< QgsFillSymbol > boundarySymbol( QgsFillSymbol::createSimple( properties ) );
326  boundarySymbol->startRender( context );
327  boundarySymbol->renderFeature( f, context );
328  boundarySymbol->stopRender( context );
329  }
330 
331  if ( !qgsDoubleNear( mMapSettings.rotation(), 0.0 ) )
332  {
333  //PAL features are prerotated, so extent also needs to be unrotated
335  // yes - this is rotated in the opposite direction... phew, this is confusing!
336  mapBoundaryGeom.rotate( mMapSettings.rotation(), mMapSettings.visibleExtent().center() );
337  }
338 
339  QgsRectangle extent = extentGeom.boundingBox();
340 
341  mPal->registerCancellationCallback( &_palIsCanceled, reinterpret_cast< void * >( &context ) );
342 
343  QElapsedTimer t;
344  t.start();
345 
346  // do the labeling itself
347  try
348  {
349  mProblem = mPal->extractProblem( extent, mapBoundaryGeom );
350  }
351  catch ( std::exception &e )
352  {
353  Q_UNUSED( e )
354  QgsDebugMsgLevel( "PAL EXCEPTION :-( " + QString::fromLatin1( e.what() ), 4 );
355  return;
356  }
357 
358  if ( context.renderingStopped() )
359  {
360  return; // it has been canceled
361  }
362 
363 #if 1 // XXX strk
364  // features are pre-rotated but not scaled/translated,
365  // so we only disable rotation here. Ideally, they'd be
366  // also pre-scaled/translated, as suggested here:
367  // https://github.com/qgis/QGIS/issues/20071
369  xform.setMapRotation( 0, 0, 0 );
370 #else
371  const QgsMapToPixel &xform = mMapSettings->mapToPixel();
372 #endif
373 
374  // draw rectangles with all candidates
375  // this is done before actual solution of the problem
376  // before number of candidates gets reduced
377  // TODO mCandidates.clear();
379  {
380  painter->setBrush( Qt::NoBrush );
381  for ( int i = 0; i < static_cast< int >( mProblem->featureCount() ); i++ )
382  {
383  for ( int j = 0; j < mProblem->featureCandidateCount( i ); j++ )
384  {
385  pal::LabelPosition *lp = mProblem->featureCandidate( i, j );
386 
387  QgsPalLabeling::drawLabelCandidateRect( lp, painter, &xform );
388  }
389  }
390  }
391 
392  // find the solution
394 
395  // sort labels
396  std::sort( mLabels.begin(), mLabels.end(), QgsLabelSorter( mMapSettings ) );
397 
398  QgsDebugMsgLevel( QStringLiteral( "LABELING work: %1 ms ... labels# %2" ).arg( t.elapsed() ).arg( mLabels.size() ), 4 );
399 }
400 
401 void QgsLabelingEngine::drawLabels( QgsRenderContext &context, const QString &layerId )
402 {
403  QElapsedTimer t;
404  t.start();
405 
407  QPainter *painter = context.painter();
408  if ( context.flags() & QgsRenderContext::Antialiasing )
409  painter->setRenderHint( QPainter::Antialiasing );
410 
411  // prepare for rendering
412  for ( QgsAbstractLabelProvider *provider : qgis::as_const( mProviders ) )
413  {
414  if ( !layerId.isEmpty() && provider->layerId() != layerId )
415  continue;
416 
417  // provider will require the correct layer scope for expression preparation - at this stage, the existing expression context
418  // only contains generic scopes
420  provider->startRender( context );
421  }
422 
424  std::unique_ptr< QgsExpressionContextScopePopper > symbolScopePopper = qgis::make_unique< QgsExpressionContextScopePopper >( context.expressionContext(), symbolScope );
425 
426  // draw label backgrounds
427  for ( pal::LabelPosition *label : qgis::as_const( mLabels ) )
428  {
429  if ( context.renderingStopped() )
430  break;
431 
432  QgsLabelFeature *lf = label->getFeaturePart()->feature();
433  if ( !lf )
434  {
435  continue;
436  }
437 
438  if ( !layerId.isEmpty() && lf->provider()->layerId() != layerId )
439  continue;
440 
441  context.expressionContext().setFeature( lf->feature() );
442  context.expressionContext().setFields( lf->feature().fields() );
443  if ( lf->symbol() )
444  {
445  symbolScope = QgsExpressionContextUtils::updateSymbolScope( lf->symbol(), symbolScope );
446  }
447  lf->provider()->drawLabelBackground( context, label );
448  }
449 
450  // draw the labels
451  for ( pal::LabelPosition *label : qgis::as_const( mLabels ) )
452  {
453  if ( context.renderingStopped() )
454  break;
455 
456  QgsLabelFeature *lf = label->getFeaturePart()->feature();
457  if ( !lf )
458  {
459  continue;
460  }
461 
462  if ( !layerId.isEmpty() && lf->provider()->layerId() != layerId )
463  continue;
464 
465  context.expressionContext().setFeature( lf->feature() );
466  context.expressionContext().setFields( lf->feature().fields() );
467  if ( lf->symbol() )
468  {
469  symbolScope = QgsExpressionContextUtils::updateSymbolScope( lf->symbol(), symbolScope );
470  }
471  lf->provider()->drawLabel( context, label );
472  // finished with symbol -- we can't keep it around after this, it may be deleted
473  lf->setSymbol( nullptr );
474  }
475 
476  // draw unplaced labels. These are always rendered on top
478  {
479  for ( pal::LabelPosition *label : qgis::as_const( mUnlabeled ) )
480  {
481  if ( context.renderingStopped() )
482  break;
483  QgsLabelFeature *lf = label->getFeaturePart()->feature();
484  if ( !lf )
485  {
486  continue;
487  }
488 
489  if ( !layerId.isEmpty() && lf->provider()->layerId() != layerId )
490  continue;
491 
492  context.expressionContext().setFeature( lf->feature() );
493  context.expressionContext().setFields( lf->feature().fields() );
494  if ( lf->symbol() )
495  {
496  symbolScope = QgsExpressionContextUtils::updateSymbolScope( lf->symbol(), symbolScope );
497  }
498  lf->provider()->drawUnplacedLabel( context, label );
499  // finished with symbol -- we can't keep it around after this, it may be deleted
500  lf->setSymbol( nullptr );
501  }
502  }
503 
504  symbolScopePopper.reset();
505 
506  // cleanup
507  for ( QgsAbstractLabelProvider *provider : qgis::as_const( mProviders ) )
508  {
509  if ( !layerId.isEmpty() && provider->layerId() != layerId )
510  continue;
511 
512  provider->stopRender( context );
513  }
514 
515  // Reset composition mode for further drawing operations
516  painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
517 
518  QgsDebugMsgLevel( QStringLiteral( "LABELING draw: %1 ms" ).arg( t.elapsed() ), 4 );
519 }
520 
522 {
523  mUnlabeled.clear();
524  mLabels.clear();
525  mProblem.reset();
526  mPal.reset();
527 }
528 
530 {
531  return mResults.release();
532 }
533 
534 
535 //
536 // QgsDefaultLabelingEngine
537 //
538 
541 {
542 
543 }
544 
546 {
547  registerLabels( context );
548  if ( context.renderingStopped() )
549  {
550  cleanup();
551  return; // it has been canceled
552  }
553 
554  solve( context );
555  if ( context.renderingStopped() )
556  {
557  cleanup();
558  return;
559  }
560 
561  drawLabels( context );
562  cleanup();
563 }
564 
565 
566 //
567 // QgsStagedRenderLabelingEngine
568 //
569 
572 {
573 
574 }
575 
577 {
578  registerLabels( context );
579  if ( context.renderingStopped() )
580  {
581  cleanup();
582  return; // it has been canceled
583  }
584 
585  solve( context );
586  if ( context.renderingStopped() )
587  {
588  cleanup();
589  return;
590  }
591 }
592 
593 
595 {
596  drawLabels( context, layerId );
597 }
598 
600 {
601  cleanup();
602 }
603 
604 
606 
608 {
609  return mLayer ? mLayer->provider() : nullptr;
610 
611 }
612 
614  : mLayerId( layer ? layer->id() : QString() )
615  , mLayer( layer )
616  , mProviderId( providerId )
617  , mFlags( DrawLabels )
618  , mPlacement( QgsPalLayerSettings::AroundPoint )
619  , mPriority( 0.5 )
620  , mUpsidedownLabels( QgsPalLayerSettings::Upright )
621 {
622 }
623 
625 {
626 
627 }
628 
630 {
631 
632 }
633 
635 {
636  const auto subproviders = subProviders();
637  for ( QgsAbstractLabelProvider *subProvider : subproviders )
638  {
639  subProvider->startRender( context );
640  }
641 }
642 
644 {
645  const auto subproviders = subProviders();
646  for ( QgsAbstractLabelProvider *subProvider : subproviders )
647  {
648  subProvider->stopRender( context );
649  }
650 }
651 
652 //
653 // QgsLabelingUtils
654 //
655 
656 QString QgsLabelingUtils::encodePredefinedPositionOrder( const QVector<QgsPalLayerSettings::PredefinedPointPosition> &positions )
657 {
658  QStringList predefinedOrderString;
659  const auto constPositions = positions;
660  for ( QgsPalLayerSettings::PredefinedPointPosition position : constPositions )
661  {
662  switch ( position )
663  {
665  predefinedOrderString << QStringLiteral( "TL" );
666  break;
668  predefinedOrderString << QStringLiteral( "TSL" );
669  break;
671  predefinedOrderString << QStringLiteral( "T" );
672  break;
674  predefinedOrderString << QStringLiteral( "TSR" );
675  break;
677  predefinedOrderString << QStringLiteral( "TR" );
678  break;
680  predefinedOrderString << QStringLiteral( "L" );
681  break;
683  predefinedOrderString << QStringLiteral( "R" );
684  break;
686  predefinedOrderString << QStringLiteral( "BL" );
687  break;
689  predefinedOrderString << QStringLiteral( "BSL" );
690  break;
692  predefinedOrderString << QStringLiteral( "B" );
693  break;
695  predefinedOrderString << QStringLiteral( "BSR" );
696  break;
698  predefinedOrderString << QStringLiteral( "BR" );
699  break;
700  }
701  }
702  return predefinedOrderString.join( ',' );
703 }
704 
705 QVector<QgsPalLayerSettings::PredefinedPointPosition> QgsLabelingUtils::decodePredefinedPositionOrder( const QString &positionString )
706 {
707  QVector<QgsPalLayerSettings::PredefinedPointPosition> result;
708  const QStringList predefinedOrderList = positionString.split( ',' );
709  result.reserve( predefinedOrderList.size() );
710  for ( const QString &position : predefinedOrderList )
711  {
712  QString cleaned = position.trimmed().toUpper();
713  if ( cleaned == QLatin1String( "TL" ) )
715  else if ( cleaned == QLatin1String( "TSL" ) )
717  else if ( cleaned == QLatin1String( "T" ) )
719  else if ( cleaned == QLatin1String( "TSR" ) )
721  else if ( cleaned == QLatin1String( "TR" ) )
723  else if ( cleaned == QLatin1String( "L" ) )
725  else if ( cleaned == QLatin1String( "R" ) )
727  else if ( cleaned == QLatin1String( "BL" ) )
729  else if ( cleaned == QLatin1String( "BSL" ) )
731  else if ( cleaned == QLatin1String( "B" ) )
733  else if ( cleaned == QLatin1String( "BSR" ) )
735  else if ( cleaned == QLatin1String( "BR" ) )
737  }
738  return result;
739 }
740 
741 QString QgsLabelingUtils::encodeLinePlacementFlags( QgsLabeling::LinePlacementFlags flags )
742 {
743  QStringList parts;
744  if ( flags & QgsLabeling::LinePlacementFlag::OnLine )
745  parts << QStringLiteral( "OL" );
746  if ( flags & QgsLabeling::LinePlacementFlag::AboveLine )
747  parts << QStringLiteral( "AL" );
748  if ( flags & QgsLabeling::LinePlacementFlag::BelowLine )
749  parts << QStringLiteral( "BL" );
750  if ( !( flags & QgsLabeling::LinePlacementFlag::MapOrientation ) )
751  parts << QStringLiteral( "LO" );
752  return parts.join( ',' );
753 }
754 
755 QgsLabeling::LinePlacementFlags QgsLabelingUtils::decodeLinePlacementFlags( const QString &string )
756 {
757  QgsLabeling::LinePlacementFlags flags = QgsLabeling::LinePlacementFlags();
758  const QStringList flagList = string.split( ',' );
759  bool foundLineOrientationFlag = false;
760  for ( const QString &flag : flagList )
761  {
762  QString cleaned = flag.trimmed().toUpper();
763  if ( cleaned == QLatin1String( "OL" ) )
764  flags |= QgsLabeling::LinePlacementFlag::OnLine;
765  else if ( cleaned == QLatin1String( "AL" ) )
766  flags |= QgsLabeling::LinePlacementFlag::AboveLine;
767  else if ( cleaned == QLatin1String( "BL" ) )
768  flags |= QgsLabeling::LinePlacementFlag::BelowLine;
769  else if ( cleaned == QLatin1String( "LO" ) )
770  foundLineOrientationFlag = true;
771  }
772  if ( !foundLineOrientationFlag )
773  flags |= QgsLabeling::LinePlacementFlag::MapOrientation;
774  return flags;
775 }
776 
QgsMapSettings::labelingEngineSettings
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns the global configuration of the labeling engine.
Definition: qgsmapsettings.h:535
QgsLabelingEngine::addProvider
void addProvider(QgsAbstractLabelProvider *provider)
Add provider of label features. Takes ownership of the provider.
Definition: qgslabelingengine.cpp:188
qgsexpressioncontextutils.h
QgsAbstractLabelProvider::drawLabel
virtual void drawLabel(QgsRenderContext &context, pal::LabelPosition *label) const =0
Draw this label at the position determined by the labeling engine.
QgsExpressionContextScopePopper
Definition: qgsexpressioncontextutils.h:354
pal::Layer::ShowAll
@ ShowAll
Definition: layer.h:75
QgsAbstractLabelProvider::stopRender
virtual void stopRender(QgsRenderContext &context)
To be called after rendering is complete.
Definition: qgslabelingengine.cpp:643
QgsLabelingEngine::processProvider
void processProvider(QgsAbstractLabelProvider *provider, QgsRenderContext &context, pal::Pal &p)
Definition: qgslabelingengine.cpp:203
pal::Layer::setUpsidedownLabels
void setUpsidedownLabels(UpsideDownLabels ud)
Sets how upside down labels will be handled within the layer.
Definition: layer.h:272
QgsLabelFeature::provider
QgsAbstractLabelProvider * provider() const
Returns provider of this instance.
Definition: qgslabelingengine.cpp:607
QgsAbstractLabelProvider::layerId
QString layerId() const
Returns ID of associated layer, or empty string if no layer is associated with the provider.
Definition: qgslabelingengine.h:127
QgsLabelingEngine::mPal
std::unique_ptr< pal::Pal > mPal
Definition: qgslabelingengine.h:320
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:580
QgsAbstractLabelProvider::upsidedownLabels
QgsPalLayerSettings::UpsideDownLabels upsidedownLabels() const
How to handle labels that would be upside down.
Definition: qgslabelingengine.h:152
QgsLabelingEngine::participatingLayerIds
QStringList participatingLayerIds() const
Returns a list of layer IDs for layers with providers in the engine.
Definition: qgslabelingengine.cpp:142
QgsLabelingEngine::drawLabels
void drawLabels(QgsRenderContext &context, const QString &layerId=QString())
Draws labels to the specified render context.
Definition: qgslabelingengine.cpp:401
QgsStagedRenderLabelingEngine::run
void run(QgsRenderContext &context) override
Runs the labeling job.
Definition: qgslabelingengine.cpp:576
QgsLabelingUtils::encodePredefinedPositionOrder
static QString encodePredefinedPositionOrder(const QVector< QgsPalLayerSettings::PredefinedPointPosition > &positions)
Encodes an ordered list of predefined point label positions to a string.
Definition: qgslabelingengine.cpp:656
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
labelposition.h
QgsPalLayerSettings
Definition: qgspallabeling.h:205
pal::Layer::setCentroidInside
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:287
QgsLabelingEngineSettings::DrawCandidates
@ DrawCandidates
Whether to draw rectangles of generated candidates (good for debugging)
Definition: qgslabelingenginesettings.h:41
QgsLabelingEngine::mProviders
QList< QgsAbstractLabelProvider * > mProviders
List of providers (the are owned by the labeling engine)
Definition: qgslabelingengine.h:314
QgsLabelingEngine::removeProvider
void removeProvider(QgsAbstractLabelProvider *provider)
Remove provider if the provider's initialization failed. Provider instance is deleted.
Definition: qgslabelingengine.cpp:194
QgsAbstractLabelProvider::DrawLabels
@ DrawLabels
Whether the labels should be rendered.
Definition: qgslabelingengine.h:61
pal::LabelPosition
LabelPosition is a candidate feature label position.
Definition: labelposition.h:55
QgsExpressionContextUtils::layerScope
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Definition: qgsexpressioncontextutils.cpp:264
pal::Layer::provider
QgsAbstractLabelProvider * provider() const
Returns pointer to the associated provider.
Definition: layer.h:166
QgsLabelingResults
Definition: qgspallabeling.h:1224
QgsPalLayerSettings::MiddleRight
@ MiddleRight
Label on right of point.
Definition: qgspallabeling.h:243
QgsAbstractLabelProvider::obstacleType
QgsLabelObstacleSettings::ObstacleType obstacleType() const
How the feature geometries will work as obstacles.
Definition: qgslabelingengine.h:149
QgsLabelSorter::operator()
bool operator()(pal::LabelPosition *lp1, pal::LabelPosition *lp2) const
Definition: qgslabelingengine.cpp:51
QgsRenderContext::convertToMapUnits
double convertToMapUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
Definition: qgsrendercontext.cpp:349
QgsPalLayerSettings::TopRight
@ TopRight
Label on top-right of point.
Definition: qgspallabeling.h:241
QgsLabelingEngine::mUnlabeled
QList< pal::LabelPosition * > mUnlabeled
Definition: qgslabelingengine.h:322
QgsRenderContext
Definition: qgsrendercontext.h:57
QgsGeometry::rotate
OperationResult rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
Definition: qgsgeometry.cpp:803
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QgsLabelSorter::QgsLabelSorter
QgsLabelSorter(const QgsMapSettings &mapSettings)
Definition: qgslabelingengine.cpp:47
QgsLabelingEngineSettings::placementVersion
PlacementEngineVersion placementVersion() const
Returns the placement engine version, which dictates how the label placement problem is solved.
Definition: qgslabelingenginesettings.cpp:88
QgsLabelingEngine::QgsLabelingEngine
QgsLabelingEngine()
Construct the labeling engine with default settings.
Definition: qgslabelingengine.cpp:79
QgsExpressionContext::setFields
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
Definition: qgsexpressioncontext.cpp:553
layer.h
QgsLabelingEngine::mSubProviders
QList< QgsAbstractLabelProvider * > mSubProviders
Definition: qgslabelingengine.h:315
QgsAbstractLabelProvider::drawUnplacedLabel
virtual void drawUnplacedLabel(QgsRenderContext &context, pal::LabelPosition *label) const
Draw an unplaced label.
Definition: qgslabelingengine.cpp:624
QgsLabelingEngine::setMapSettings
void setMapSettings(const QgsMapSettings &mapSettings)
Associate map settings instance.
Definition: qgslabelingengine.cpp:89
QgsPalLayerSettings::TopSlightlyRight
@ TopSlightlyRight
Label on top of point, slightly right of center.
Definition: qgspallabeling.h:240
QgsLabelingEngineSettings::flags
Flags flags() const
Gets flags of the labeling engine.
Definition: qgslabelingenginesettings.h:80
QgsRectangle
Definition: qgsrectangle.h:41
QgsAbstractLabelProvider::priority
double priority() const
Default priority of labels (may be overridden by individual labels)
Definition: qgslabelingengine.h:146
pal::LabelPosition::getFeaturePart
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
Definition: labelposition.cpp:371
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:229
QgsLabelingUtils::decodePredefinedPositionOrder
static QVector< QgsPalLayerSettings::PredefinedPointPosition > decodePredefinedPositionOrder(const QString &positionString)
Decodes a string to an ordered list of predefined point label positions.
Definition: qgslabelingengine.cpp:705
QgsPalLayerSettings::TopMiddle
@ TopMiddle
Label directly above point.
Definition: qgspallabeling.h:239
problem.h
QgsAbstractLabelProvider::placement
QgsPalLayerSettings::Placement placement() const
What placement strategy to use for the labels.
Definition: qgslabelingengine.h:143
QgsPalLayerSettings::BottomMiddle
@ BottomMiddle
Label directly below point.
Definition: qgspallabeling.h:246
pal::Pal::addLayer
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:78
QgsRenderContext::renderingStopped
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
Definition: qgsrendercontext.h:325
feature.h
QgsAbstractLabelProvider::MergeConnectedLines
@ MergeConnectedLines
Whether adjacent lines (with the same label text) should be merged.
Definition: qgslabelingengine.h:63
QgsMapSettings::rotation
double rotation() const
Returns the rotation of the resulting map image, in degrees clockwise.
Definition: qgsmapsettings.cpp:101
QgsAbstractLabelProvider
The QgsAbstractLabelProvider class is an interface class. Implementations return list of labels and t...
Definition: qgslabelingengine.h:47
QgsAbstractLabelProvider::CentroidMustBeInside
@ CentroidMustBeInside
Whether location of centroid must be inside of polygons.
Definition: qgslabelingengine.h:64
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
QgsLabelingUtils::encodeLinePlacementFlags
static QString encodeLinePlacementFlags(QgsLabeling::LinePlacementFlags flags)
Encodes line placement flags to a string.
Definition: qgslabelingengine.cpp:741
QgsLabelFeature::symbol
const QgsSymbol * symbol()
Returns the feature symbol associated with this label.
Definition: qgslabelfeature.h:382
QgsLabelingEngineSettings
Definition: qgslabelingenginesettings.h:30
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsPalLayerSettings::TopSlightlyLeft
@ TopSlightlyLeft
Label on top of point, slightly left of center.
Definition: qgspallabeling.h:238
QgsLabelingEngineSettings::testFlag
bool testFlag(Flag f) const
Test whether a particular flag is enabled.
Definition: qgslabelingenginesettings.h:82
QgsPalLayerSettings::BottomSlightlyLeft
@ BottomSlightlyLeft
Label below point, slightly left of center.
Definition: qgspallabeling.h:245
QgsStagedRenderLabelingEngine::finalize
void finalize()
Finalizes and cleans up the engine following the rendering of labels for the last layer to be labeled...
Definition: qgslabelingengine.cpp:599
QgsAbstractLabelProvider::setEngine
void setEngine(const QgsLabelingEngine *engine)
Associate provider with a labeling engine (should be only called internally from QgsLabelingEngine)
Definition: qgslabelingengine.h:57
QgsStagedRenderLabelingEngine::QgsStagedRenderLabelingEngine
QgsStagedRenderLabelingEngine()
Construct the labeling engine with default settings.
Definition: qgslabelingengine.cpp:570
QgsAbstractLabelProvider::labelFeatures
virtual QList< QgsLabelFeature * > labelFeatures(QgsRenderContext &context)=0
Returns list of label features (they are owned by the provider and thus deleted on its destruction)
qgsmaplayer.h
QgsLabelingEngine::cleanup
void cleanup()
Cleans up the engine following a call to registerLabels() or solve().
Definition: qgslabelingengine.cpp:521
QgsMapSettings::visiblePolygon
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
Definition: qgsmapsettings.cpp:375
pal::Layer::setMergeConnectedLines
void setMergeConnectedLines(bool merge)
Sets whether connected lines should be merged before labeling.
Definition: layer.h:259
QgsAbstractLabelProvider::name
QString name() const
Name of the layer (for statistics, debugging etc.) - does not need to be unique.
Definition: qgslabelingengine.h:124
qgsrendercontext.h
QgsAbstractLabelProvider::subProviders
virtual QList< QgsAbstractLabelProvider * > subProviders()
Returns list of child providers - useful if the provider needs to put labels into more layers with di...
Definition: qgslabelingengine.h:121
QgsPalLayerSettings::Upright
@ Upright
Upside-down labels (90 <= angle < 270) are shown upright.
Definition: qgspallabeling.h:297
QgsPalLayerSettings::MiddleLeft
@ MiddleLeft
Label on left of point.
Definition: qgspallabeling.h:242
QgsPalLayerSettings::PredefinedPointPosition
PredefinedPointPosition
Positions for labels when using the QgsPalLabeling::OrderedPositionsAroundPoint placement mode.
Definition: qgspallabeling.h:235
QgsStagedRenderLabelingEngine::renderLabelsForLayer
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...
Definition: qgslabelingengine.cpp:594
QgsPalLayerSettings::ShowDefined
@ ShowDefined
Show upside down when rotation is layer- or data-defined.
Definition: qgspallabeling.h:298
QgsLabelFeature::feature
QgsFeature feature() const
Returns the original feature associated with this label.
Definition: qgslabelfeature.cpp:59
QgsMapSettings::labelBlockingRegions
QList< QgsLabelBlockingRegion > labelBlockingRegions() const
Returns the list of regions to avoid placing labels within.
Definition: qgsmapsettings.h:579
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:125
QgsLabelingEngine::~QgsLabelingEngine
virtual ~QgsLabelingEngine()
Clean up everything (especially the registered providers)
Definition: qgslabelingengine.cpp:83
QgsLabelingEngine::participatingLayers
QList< QgsMapLayer * > participatingLayers() const
Returns a list of layers with providers in the engine.
Definition: qgslabelingengine.cpp:96
QgsPalLayerSettings::BottomSlightlyRight
@ BottomSlightlyRight
Label below point, slightly right of center.
Definition: qgspallabeling.h:247
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext....
Definition: qgsexpressioncontext.h:111
QgsAbstractLabelProvider::drawLabelBackground
virtual void drawLabelBackground(QgsRenderContext &context, pal::LabelPosition *label) const
Draw the background for the specified label.
Definition: qgslabelingengine.cpp:629
QgsLabelingEngine::mProblem
std::unique_ptr< pal::Problem > mProblem
Definition: qgslabelingengine.h:321
QgsLabelingEngine
The QgsLabelingEngine class provides map labeling functionality. The input for the engine is a list o...
Definition: qgslabelingengine.h:214
QgsAbstractLabelProvider::startRender
virtual void startRender(QgsRenderContext &context)
To be called before rendering of labels begins.
Definition: qgslabelingengine.cpp:634
QgsAbstractLabelProvider::DrawAllLabels
@ DrawAllLabels
Whether all features will be labelled even though overlaps occur.
Definition: qgslabelingengine.h:62
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:714
QgsPalLayerSettings::TopLeft
@ TopLeft
Label on top-left of point.
Definition: qgspallabeling.h:237
QgsDefaultLabelingEngine::QgsDefaultLabelingEngine
QgsDefaultLabelingEngine()
Construct the labeling engine with default settings.
Definition: qgslabelingengine.cpp:539
QgsLabelFeature::zIndex
double zIndex() const
Returns the label's z-index.
Definition: qgslabelfeature.h:161
QgsLabelingEngine::takeResults
QgsLabelingResults * takeResults()
Returns pointer to recently computed results and pass the ownership of results to the caller.
Definition: qgslabelingengine.cpp:529
QgsLabelFeature::setSymbol
void setSymbol(const QgsSymbol *symbol)
Sets the feature symbol associated with this label.
Definition: qgslabelfeature.h:391
QgsExpressionContextUtils::updateSymbolScope
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
Definition: qgsexpressioncontextutils.cpp:458
QgsRectangle::center
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:230
QgsLabelingEngine::mapSettings
const QgsMapSettings & mapSettings() const
Gets associated map settings.
Definition: qgslabelingengine.h:230
QgsLabelFeature::size
QSizeF size(double angle=0.0) const
Size of the label (in map units)
Definition: qgslabelfeature.cpp:64
QgsGeometry
Definition: qgsgeometry.h:122
QgsLabelingEngineSettings::UsePartialCandidates
@ UsePartialCandidates
Whether to use also label candidates that are partially outside of the map view.
Definition: qgslabelingenginesettings.h:37
QgsMapToPixel
Definition: qgsmaptopixel.h:37
QgsLabelingEngineSettings::maximumPolygonCandidatesPerCmSquared
double maximumPolygonCandidatesPerCmSquared() const
Returns the maximum number of polygon label candidate positions per centimeter squared.
Definition: qgslabelingenginesettings.h:108
pal::Layer::Upright
@ Upright
Definition: layer.h:73
QgsMapLayer
Definition: qgsmaplayer.h:81
pal::Layer::setObstacleType
void setObstacleType(QgsLabelObstacleSettings::ObstacleType obstacleType)
Sets the obstacle type, which controls how features within the layer act as obstacles for labels.
Definition: layer.h:237
QgsLabelingUtils::decodeLinePlacementFlags
static QgsLabeling::LinePlacementFlags decodeLinePlacementFlags(const QString &string)
Decodes a string to set of line placement flags.
Definition: qgslabelingengine.cpp:755
pal::Pal
Main Pal labeling class.
Definition: pal.h:79
QgsLabelingEngineSettings::maximumLineCandidatesPerCm
double maximumLineCandidatesPerCm() const
Returns the maximum number of line label candidate positions per centimeter.
Definition: qgslabelingenginesettings.h:92
QgsLabelingEngine::mResults
std::unique_ptr< QgsLabelingResults > mResults
Resulting labeling layout.
Definition: qgslabelingengine.h:318
QgsLabelingEngine::mMapSettings
QgsMapSettings mMapSettings
Associated map settings instance.
Definition: qgslabelingengine.h:311
QgsRenderContext::Antialiasing
@ Antialiasing
Use antialiasing while drawing.
Definition: qgsrendercontext.h:78
pal::Layer
A set of features which influence the labeling process.
Definition: layer.h:61
qgsvectorlayerlabelprovider.h
QgsAbstractLabelProvider::flags
Flags flags() const
Flags associated with the provider.
Definition: qgslabelingengine.h:140
QgsPalLayerSettings::BottomRight
@ BottomRight
Label on bottom right of point.
Definition: qgspallabeling.h:248
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:962
QgsFeature::fields
QgsFields fields
Definition: qgsfeature.h:70
pal.h
QgsLabelBlockingRegion
Definition: qgsmapsettings.h:52
QgsGeometry::fromQPolygonF
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Definition: qgsgeometry.cpp:3095
QgsFeature
Definition: qgsfeature.h:55
QgsLabelingEngine::solve
void solve(QgsRenderContext &context)
Solves the label problem.
Definition: qgslabelingengine.cpp:291
QgsFillSymbol::createSimple
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgssymbol.cpp:1440
QgsLabelFeature
The QgsLabelFeature class describes a feature that should be used within the labeling engine....
Definition: qgslabelfeature.h:56
QgsDefaultLabelingEngine::run
void run(QgsRenderContext &context) override
Runs the labeling job.
Definition: qgslabelingengine.cpp:545
qgslogger.h
QgsMapSettings::labelBoundaryGeometry
QgsGeometry labelBoundaryGeometry() const
Returns the label boundary geometry, which restricts where in the rendered map labels are permitted t...
Definition: qgsmapsettings.cpp:675
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:174
QgsLabelingEngine::registerLabels
void registerLabels(QgsRenderContext &context)
Runs the label registration step.
Definition: qgslabelingengine.cpp:267
QgsLabelFeature::mLayer
pal::Layer * mLayer
Pointer to PAL layer (assigned when registered to PAL)
Definition: qgslabelfeature.h:472
QgsMapSettings
Definition: qgsmapsettings.h:86
QgsMapSettings::visibleExtent
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
Definition: qgsmapsettings.cpp:370
pal::FeaturePart::feature
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:117
QgsLabelingEngineSettings::UseAllLabels
@ UseAllLabels
Whether to draw all labels even if there would be collisions.
Definition: qgslabelingenginesettings.h:36
QgsMapToPixel::setMapRotation
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
Definition: qgsmaptopixel.cpp:133
qgssymbol.h
QgsMapSettings::mapToPixel
const QgsMapToPixel & mapToPixel() const
Definition: qgsmapsettings.h:433
pal::Layer::UpsideDownLabels
UpsideDownLabels
Definition: layer.h:71
QgsGeometry::difference
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
Definition: qgsgeometry.cpp:2456
QgsLabelSorter
Definition: qgslabelingengine.cpp:43
QgsLabelingEngineSettings::DrawUnplacedLabels
@ DrawUnplacedLabels
Whether to render unplaced labels as an indicator/warning for users.
Definition: qgslabelingenginesettings.h:42
pal::Layer::ShowDefined
@ ShowDefined
Definition: layer.h:74
QgsMapSettings::layerIds
QStringList layerIds() const
Gets list of layer IDs for map rendering The layers are stored in the reverse order of how they are r...
Definition: qgsmapsettings.cpp:275
qgslabelingengine.h
QgsPalLayerSettings::ShowAll
@ ShowAll
Show upside down for all labels, including dynamic ones.
Definition: qgspallabeling.h:299
QgsRenderContext::flags
Flags flags() const
Returns combination of flags used for rendering.
Definition: qgsrendercontext.cpp:160
QgsLabelingEngine::mLabels
QList< pal::LabelPosition * > mLabels
Definition: qgslabelingengine.h:323
QgsPalLabeling::drawLabelCandidateRect
static void drawLabelCandidateRect(pal::LabelPosition *lp, QPainter *painter, const QgsMapToPixel *xform, QList< QgsLabelCandidate > *candidates=nullptr)
Definition: qgspallabeling.cpp:4242
QgsPalLayerSettings::BottomLeft
@ BottomLeft
Label on bottom-left of point.
Definition: qgspallabeling.h:244
QgsAbstractLabelProvider::QgsAbstractLabelProvider
QgsAbstractLabelProvider(QgsMapLayer *layer, const QString &providerId=QString())
Construct the provider with default values.
Definition: qgslabelingengine.cpp:613
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:521
pal::Layer::registerFeature
bool registerFeature(QgsLabelFeature *label)
Register a feature in the layer.
Definition: layer.cpp:85