QGIS API Documentation  3.25.0-Master (10b47c2603)
qgsvectorlayerlabelprovider.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerlabelprovider.cpp
3  --------------------------------------
4  Date : September 2015
5  Copyright : (C) 2015 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include "qgsgeometry.h"
19 #include "qgslabelsearchtree.h"
20 #include "qgspallabeling.h"
21 #include "qgstextlabelfeature.h"
22 #include "qgsvectorlayer.h"
24 #include "qgsrenderer.h"
25 #include "qgspolygon.h"
26 #include "qgslinestring.h"
27 #include "qgsmultipolygon.h"
28 #include "qgslogger.h"
30 #include "qgsmaskidprovider.h"
31 #include "qgstextcharacterformat.h"
32 #include "qgstextfragment.h"
33 #include "qgslabelingresults.h"
34 
35 #include "feature.h"
36 #include "labelposition.h"
37 #include "callouts/qgscallout.h"
38 #include "qgssymbol.h"
39 #include "qgsmarkersymbol.h"
40 
41 #include "pal/layer.h"
42 
43 #include <QPicture>
44 #include <QTextDocument>
45 #include <QTextFragment>
46 
47 using namespace pal;
48 
49 QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName )
50  : QgsAbstractLabelProvider( layer, providerId )
51  , mSettings( settings ? * settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
52  , mLayerGeometryType( layer->geometryType() )
53  , mRenderer( layer->renderer() )
54  , mFields( layer->fields() )
55  , mCrs( layer->crs() )
56 {
57  mName = layerName.isEmpty() ? layer->id() : layerName;
58 
59  if ( withFeatureLoop )
60  {
61  mSource = std::make_unique<QgsVectorLayerFeatureSource>( layer );
62  }
63 
64  init();
65 }
66 
67 QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsWkbTypes::GeometryType geometryType, const QgsFields &fields, const QgsCoordinateReferenceSystem &crs, const QString &providerId, const QgsPalLayerSettings *settings, QgsMapLayer *layer, const QString &layerName )
68  : QgsAbstractLabelProvider( layer, providerId )
69  , mSettings( settings ? * settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
70  , mLayerGeometryType( geometryType )
71  , mRenderer( nullptr )
72  , mFields( fields )
73  , mCrs( crs )
74 {
75  mName = layerName.isEmpty() ? layer->id() : layerName;
76 
77  init();
78 }
79 
81 {
83  mFlags = Flags();
84  if ( mSettings.drawLabels )
85  mFlags |= DrawLabels;
86  if ( mSettings.displayAll )
92 
93  mPriority = 1 - mSettings.priority / 10.0; // convert 0..10 --> 1..0
94 
96  {
97  //override obstacle type to treat any intersection of a label with the point symbol as a high cost conflict
99  }
100  else
101  {
103  }
104 
106 }
107 
108 
110 {
111  qDeleteAll( mLabels );
112 }
113 
114 
115 bool QgsVectorLayerLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
116 {
117  const QgsMapSettings &mapSettings = mEngine->mapSettings();
118 
119  return mSettings.prepare( context, attributeNames, mFields, mapSettings, mCrs );
120 }
121 
123 {
125  mSettings.startRender( context );
126 }
127 
129 {
131  mSettings.stopRender( context );
132 }
133 
135 {
136  if ( !mSource )
137  {
138  // we have created the provider with "own feature loop" == false
139  // so it is assumed that prepare() has been already called followed by registerFeature() calls
140  return mLabels;
141  }
142 
143  QSet<QString> attrNames;
144  if ( !prepare( ctx, attrNames ) )
145  return QList<QgsLabelFeature *>();
146 
147  if ( mRenderer )
148  mRenderer->startRender( ctx, mFields );
149 
150  QgsRectangle layerExtent = ctx.extent();
152  {
153  QgsCoordinateTransform extentTransform = mSettings.ct;
154  extentTransform.setBallparkTransformsAreAppropriate( true );
155  layerExtent = extentTransform.transformBoundingBox( ctx.extent(), Qgis::TransformDirection::Reverse );
156  }
157 
158  QgsFeatureRequest request;
159  request.setFilterRect( layerExtent );
160  request.setSubsetOfAttributes( attrNames, mFields );
161  QgsFeatureIterator fit = mSource->getFeatures( request );
162 
164  ctx.expressionContext().appendScope( symbolScope );
165  QgsFeature fet;
166  while ( fit.nextFeature( fet ) )
167  {
168  QgsGeometry obstacleGeometry;
169  const QgsSymbol *symbol = nullptr;
170  if ( mRenderer )
171  {
172  QgsSymbolList symbols = mRenderer->originalSymbolsForFeature( fet, ctx );
173  if ( !symbols.isEmpty() && fet.geometry().type() == QgsWkbTypes::PointGeometry )
174  {
175  //point feature, use symbol bounds as obstacle
176  obstacleGeometry = QgsVectorLayerLabelProvider::getPointObstacleGeometry( fet, ctx, symbols );
177  }
178  if ( !symbols.isEmpty() )
179  {
180  symbol = symbols.at( 0 );
181  symbolScope = QgsExpressionContextUtils::updateSymbolScope( symbol, symbolScope );
182  }
183  }
184  ctx.expressionContext().setFeature( fet );
185  registerFeature( fet, ctx, obstacleGeometry, symbol );
186  }
187 
188  if ( ctx.expressionContext().lastScope() == symbolScope )
189  delete ctx.expressionContext().popScope();
190 
191  if ( mRenderer )
192  mRenderer->stopRender( ctx );
193 
194  return mLabels;
195 }
196 
197 QList< QgsLabelFeature * > QgsVectorLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
198 {
199  std::unique_ptr< QgsLabelFeature > label = mSettings.registerFeatureWithDetails( feature, context, obstacleGeometry, symbol );
200  QList< QgsLabelFeature * > res;
201  if ( label )
202  {
203  res << label.get();
204  mLabels << label.release();
205  }
206  return res;
207 }
208 
210 {
211  if ( !fet.hasGeometry() || fet.geometry().type() != QgsWkbTypes::PointGeometry )
212  return QgsGeometry();
213 
214  bool isMultiPoint = fet.geometry().constGet()->nCoordinates() > 1;
215  std::unique_ptr< QgsAbstractGeometry > obstacleGeom;
216  if ( isMultiPoint )
217  obstacleGeom = std::make_unique< QgsMultiPolygon >();
218 
219  // for each point
220  for ( int i = 0; i < fet.geometry().constGet()->nCoordinates(); ++i )
221  {
222  QRectF bounds;
223  QgsPoint p = fet.geometry().constGet()->vertexAt( QgsVertexId( i, 0, 0 ) );
224  double x = p.x();
225  double y = p.y();
226  double z = 0; // dummy variable for coordinate transforms
227 
228  //transform point to pixels
229  if ( context.coordinateTransform().isValid() )
230  {
231  try
232  {
233  context.coordinateTransform().transformInPlace( x, y, z );
234  }
235  catch ( QgsCsException & )
236  {
237  return QgsGeometry();
238  }
239  }
240  context.mapToPixel().transformInPlace( x, y );
241 
242  QPointF pt( x, y );
243  const auto constSymbols = symbols;
244  for ( QgsSymbol *symbol : constSymbols )
245  {
246  if ( symbol->type() == Qgis::SymbolType::Marker )
247  {
248  if ( bounds.isValid() )
249  bounds = bounds.united( static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet ) );
250  else
251  bounds = static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet );
252  }
253  }
254 
255  //convert bounds to a geometry
256  QVector< double > bX;
257  bX << bounds.left() << bounds.right() << bounds.right() << bounds.left();
258  QVector< double > bY;
259  bY << bounds.top() << bounds.top() << bounds.bottom() << bounds.bottom();
260  std::unique_ptr< QgsLineString > boundLineString = std::make_unique< QgsLineString >( bX, bY );
261 
262  //then transform back to map units
263  //TODO - remove when labeling is refactored to use screen units
264  for ( int i = 0; i < boundLineString->numPoints(); ++i )
265  {
266  QgsPointXY point = context.mapToPixel().toMapCoordinates( static_cast<int>( boundLineString->xAt( i ) ),
267  static_cast<int>( boundLineString->yAt( i ) ) );
268  boundLineString->setXAt( i, point.x() );
269  boundLineString->setYAt( i, point.y() );
270  }
271  if ( context.coordinateTransform().isValid() )
272  {
273  try
274  {
275  boundLineString->transform( context.coordinateTransform(), Qgis::TransformDirection::Reverse );
276  }
277  catch ( QgsCsException & )
278  {
279  return QgsGeometry();
280  }
281  }
282  boundLineString->close();
283 
284  if ( context.coordinateTransform().isValid() )
285  {
286  // coordinate transforms may have resulted in nan coordinates - if so, strip these out
287  boundLineString->filterVertices( []( const QgsPoint & point )->bool
288  {
289  return std::isfinite( point.x() ) && std::isfinite( point.y() );
290  } );
291  if ( !boundLineString->isRing() )
292  return QgsGeometry();
293  }
294 
295  std::unique_ptr< QgsPolygon > obstaclePolygon = std::make_unique< QgsPolygon >();
296  obstaclePolygon->setExteriorRing( boundLineString.release() );
297 
298  if ( isMultiPoint )
299  {
300  static_cast<QgsMultiPolygon *>( obstacleGeom.get() )->addGeometry( obstaclePolygon.release() );
301  }
302  else
303  {
304  obstacleGeom = std::move( obstaclePolygon );
305  }
306  }
307 
308  return QgsGeometry( std::move( obstacleGeom ) );
309 }
310 
312 {
313  if ( !mSettings.drawLabels )
314  return;
315 
316  // render callout
318  {
319  drawCallout( context, label );
320  }
321 }
322 
323 void QgsVectorLayerLabelProvider::drawCallout( QgsRenderContext &context, pal::LabelPosition *label ) const
324 {
325  bool enabled = mSettings.callout()->enabled();
327  {
328  context.expressionContext().setOriginalValueVariable( enabled );
330  }
331  if ( enabled )
332  {
333  QgsMapToPixel xform = context.mapToPixel();
334  xform.setMapRotation( 0, 0, 0 );
335  QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
336  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
337  QRectF rect( outPt.x(), outPt.y(), outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
338 
340  g.transform( xform.transform() );
341  QgsCallout::QgsCalloutContext calloutContext;
342  calloutContext.allFeaturePartsLabeled = label->getFeaturePart()->feature()->labelAllParts();
343  calloutContext.originalFeatureCrs = label->getFeaturePart()->feature()->originalFeatureCrs();
344  mSettings.callout()->render( context, rect, label->getAlpha() * 180 / M_PI, g, calloutContext );
345 
346  const QList< QgsCalloutPosition > renderedPositions = calloutContext.positions();
347 
348  for ( QgsCalloutPosition position : renderedPositions )
349  {
350  position.layerID = mLayerId;
351  position.featureId = label->getFeaturePart()->featureId();
352  position.providerID = mProviderId;
353  mEngine->results()->mLabelSearchTree->insertCallout( position );
354  }
355  }
356 }
357 
359 {
360  if ( !mSettings.drawLabels )
361  return;
362 
363  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
364 
365  // Copy to temp, editable layer settings
366  // these settings will be changed by any data defined values, then used for rendering label components
367  // settings may be adjusted during rendering of components
368  QgsPalLayerSettings tmpLyr( mSettings );
369 
370  // apply any previously applied data defined settings for the label
371  const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->dataDefinedValues();
372 
373  //font
374  QFont dFont = lf->definedFont();
375  QgsDebugMsgLevel( QStringLiteral( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
376  QgsDebugMsgLevel( QStringLiteral( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
377 
378  QgsTextFormat format = tmpLyr.format();
379  format.setFont( dFont );
380 
381  // size has already been calculated and stored in the defined font - this calculated size
382  // is in pixels
383  format.setSize( dFont.pixelSize() );
385  tmpLyr.setFormat( format );
386 
388  {
389  //calculate font alignment based on label quadrant
390  switch ( label->getQuadrant() )
391  {
392  case LabelPosition::QuadrantAboveLeft:
393  case LabelPosition::QuadrantLeft:
394  case LabelPosition::QuadrantBelowLeft:
396  break;
397  case LabelPosition::QuadrantAbove:
398  case LabelPosition::QuadrantOver:
399  case LabelPosition::QuadrantBelow:
401  break;
402  case LabelPosition::QuadrantAboveRight:
403  case LabelPosition::QuadrantRight:
404  case LabelPosition::QuadrantBelowRight:
406  break;
407  }
408  }
409 
410  // update tmpLyr with any data defined text style values
411  QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
412 
413  // update tmpLyr with any data defined text buffer values
414  QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
415 
416  // update tmpLyr with any data defined text mask values
417  QgsPalLabeling::dataDefinedTextMask( tmpLyr, ddValues );
418 
419  // update tmpLyr with any data defined text formatting values
420  QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
421 
422  // update tmpLyr with any data defined shape background values
423  QgsPalLabeling::dataDefinedShapeBackground( tmpLyr, ddValues );
424 
425  // update tmpLyr with any data defined drop shadow values
426  QgsPalLabeling::dataDefinedDropShadow( tmpLyr, ddValues );
427 
428  // Render the components of a label in reverse order
429  // (backgrounds -> text)
430 
431  // render callout
433  {
434  drawCallout( context, label );
435  }
436 
438  {
439  QgsTextFormat format = tmpLyr.format();
440 
441  if ( tmpLyr.format().background().enabled() && tmpLyr.format().background().type() != QgsTextBackgroundSettings::ShapeMarkerSymbol ) // background shadows not compatible with marker symbol backgrounds
442  {
444  }
445  else if ( tmpLyr.format().buffer().enabled() )
446  {
448  }
449  else
450  {
452  }
453 
454  tmpLyr.setFormat( format );
455  }
456 
457  if ( tmpLyr.format().background().enabled() )
458  {
459  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Background );
460  }
461 
462  if ( tmpLyr.format().buffer().enabled() )
463  {
464  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Buffer );
465  }
466 
467  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Text );
468 
469  // add to the results
470  QString labeltext = label->getFeaturePart()->feature()->labelText();
471  mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, dFont, false, lf->hasFixedPosition(), mProviderId );
472 }
473 
475 {
476  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
477 
478  QgsTextFormat format = mSettings.format();
479  if ( mSettings.drawLabels
482  {
483  QgsPalLayerSettings tmpLyr( mSettings );
484  format = tmpLyr.format();
486  tmpLyr.setFormat( format );
487  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Text );
488  }
489 
490  // add to the results
491  QString labeltext = label->getFeaturePart()->feature()->labelText();
492  mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, format.font(), false, lf->hasFixedPosition(), mProviderId, true );
493 }
494 
496 {
497  // NOTE: this is repeatedly called for multi-part labels
498  QPainter *painter = context.painter();
499 
500  // features are pre-rotated but not scaled/translated,
501  // so we only disable rotation here. Ideally, they'd be
502  // also pre-scaled/translated, as suggested here:
503  // https://github.com/qgis/QGIS/issues/20071
504  QgsMapToPixel xform = context.mapToPixel();
505  xform.setMapRotation( 0, 0, 0 );
506 
507  QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
508 
509  if ( mEngine->engineSettings().testFlag( QgsLabelingEngineSettings::DrawLabelRectOnly ) ) // TODO: this should get directly to labeling engine
510  {
511  //debugging rect
512  if ( drawType != QgsTextRenderer::Text )
513  return;
514 
515  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
516  QRectF rect( 0, 0, outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
517  painter->save();
518  painter->setRenderHint( QPainter::Antialiasing, false );
519  painter->translate( QPointF( outPt.x(), outPt.y() ) );
520  painter->rotate( -label->getAlpha() * 180 / M_PI );
521 
522  if ( label->conflictsWithObstacle() )
523  {
524  painter->setBrush( QColor( 255, 0, 0, 100 ) );
525  painter->setPen( QColor( 255, 0, 0, 150 ) );
526  }
527  else
528  {
529  painter->setBrush( QColor( 0, 255, 0, 100 ) );
530  painter->setPen( QColor( 0, 255, 0, 150 ) );
531  }
532 
533  painter->drawRect( rect );
534  painter->restore();
535 
536  if ( label->nextPart() )
537  drawLabelPrivate( label->nextPart(), context, tmpLyr, drawType, dpiRatio );
538 
539  return;
540  }
541 
542  QgsTextRenderer::Component component;
543  component.dpiRatio = dpiRatio;
544  component.origin = outPt;
545  component.rotation = label->getAlpha();
546 
547  if ( drawType == QgsTextRenderer::Background )
548  {
549  // get rotated label's center point
550  QPointF centerPt( outPt );
551  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth() / 2,
552  label->getY() + label->getHeight() / 2 );
553 
554  double xc = outPt2.x() - outPt.x();
555  double yc = outPt2.y() - outPt.y();
556 
557  double angle = -component.rotation;
558  double xd = xc * std::cos( angle ) - yc * std::sin( angle );
559  double yd = xc * std::sin( angle ) + yc * std::cos( angle );
560 
561  centerPt.setX( centerPt.x() + xd );
562  centerPt.setY( centerPt.y() + yd );
563 
564  component.center = centerPt;
565 
566  {
567  // label size has already been calculated using any symbology reference scale factor -- we need
568  // to temporarily remove the reference scale here or we'll be applying the scaling twice
569  QgsScopedRenderContextReferenceScaleOverride referenceScaleOverride( context, -1.0 );
570 
571  // convert label size to render units
572  double labelWidthPx = context.convertToPainterUnits( label->getWidth(), QgsUnitTypes::RenderMapUnits, QgsMapUnitScale() );
573  double labelHeightPx = context.convertToPainterUnits( label->getHeight(), QgsUnitTypes::RenderMapUnits, QgsMapUnitScale() );
574 
575  component.size = QSizeF( labelWidthPx, labelHeightPx );
576  }
577 
578  QgsTextRenderer::drawBackground( context, component, tmpLyr.format(), QgsTextDocument(), QgsTextRenderer::Label );
579  }
580 
581  else if ( drawType == QgsTextRenderer::Buffer
582  || drawType == QgsTextRenderer::Text )
583  {
584 
585  // TODO: optimize access :)
586  QgsTextLabelFeature *lf = static_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
587  QString txt = lf->text( label->getPartId() );
588  QFontMetricsF *labelfm = lf->labelFontMetrics();
589 
590  if ( auto *lMaskIdProvider = context.maskIdProvider() )
591  {
592  int maskId = lMaskIdProvider->maskId( label->getFeaturePart()->layer()->provider()->layerId(),
593  label->getFeaturePart()->layer()->provider()->providerId() );
594  context.setCurrentMaskId( maskId );
595  }
596 
597  //add the direction symbol if needed
598  if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line &&
599  tmpLyr.lineSettings().addDirectionSymbol() )
600  {
601  bool prependSymb = false;
602  QString symb = tmpLyr.lineSettings().rightDirectionSymbol();
603 
604  if ( label->getReversed() )
605  {
606  prependSymb = true;
607  symb = tmpLyr.lineSettings().leftDirectionSymbol();
608  }
609 
610  if ( tmpLyr.lineSettings().reverseDirectionSymbol() )
611  {
612  if ( symb == tmpLyr.lineSettings().rightDirectionSymbol() )
613  {
614  prependSymb = true;
615  symb = tmpLyr.lineSettings().leftDirectionSymbol();
616  }
617  else
618  {
619  prependSymb = false;
620  symb = tmpLyr.lineSettings().rightDirectionSymbol();
621  }
622  }
623 
624  switch ( tmpLyr.lineSettings().directionSymbolPlacement() )
625  {
627  prependSymb = true;
628  symb = symb + QStringLiteral( "\n" );
629  break;
630 
632  prependSymb = false;
633  symb = QStringLiteral( "\n" ) + symb;
634  break;
635 
637  break;
638  }
639 
640  if ( prependSymb )
641  {
642  txt.prepend( symb );
643  }
644  else
645  {
646  txt.append( symb );
647  }
648  }
649 
653  else if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiRight )
657 
658  QgsTextRenderer::Component component;
659  component.origin = outPt;
660  component.rotation = label->getAlpha();
661 
662  QgsTextDocument document;
663  if ( !tmpLyr.format().allowHtmlFormatting() || tmpLyr.placement == QgsPalLayerSettings::Curved )
664  {
665  const QgsTextCharacterFormat c = lf->characterFormat( label->getPartId() );
666  const QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap );
667  for ( const QString &line : multiLineList )
668  document.append( QgsTextBlock( QgsTextFragment( line, c ) ) );
669  }
670  else
671  {
672  document = lf->document();
673  }
674 
675  QgsTextRenderer::drawTextInternal( drawType, context, tmpLyr.format(), component, document, labelfm,
677 
678  }
679  if ( label->nextPart() )
680  drawLabelPrivate( label->nextPart(), context, tmpLyr, drawType, dpiRatio );
681 }
682 
684 {
685  return mSettings;
686 }
@ NeverShow
Never show unplaced labels, regardless of the engine setting.
@ Marker
Marker symbol.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
The QgsAbstractLabelProvider class is an interface class.
QgsLabelObstacleSettings::ObstacleType mObstacleType
Type of the obstacle of feature geometries.
QString mName
Name of the layer.
virtual void stopRender(QgsRenderContext &context)
To be called after rendering is complete.
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
QString mLayerId
Associated layer's ID, if applicable.
QgsPalLayerSettings::UpsideDownLabels mUpsidedownLabels
How to handle labels that would be upside down.
double mPriority
Default priority of labels.
const QgsLabelingEngine * mEngine
Associated labeling engine.
Flags mFlags
Flags altering drawing and registration of features.
virtual void startRender(QgsRenderContext &context)
To be called before rendering of labels begins.
@ 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.
QString layerId() const
Returns ID of associated layer, or empty string if no layer is associated with the provider.
QString providerId() const
Returns provider ID - useful in case there is more than one label provider within a layer (e....
QgsPalLayerSettings::Placement mPlacement
Placement strategy.
QString mProviderId
Associated provider ID (one layer may have multiple providers, e.g. in rule-based labeling)
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean.
Represents the calculated placement of a map label callout line.
Contains additional contextual information about the context in which a callout is being rendered.
Definition: qgscallout.h:246
bool allFeaturePartsLabeled
true if all parts of associated feature were labeled
Definition: qgscallout.h:249
QList< QgsCalloutPosition > positions() const
Returns the list of rendered callout positions.
Definition: qgscallout.h:283
QgsCoordinateReferenceSystem originalFeatureCrs
Contains the CRS of the original feature associated with this callout.
Definition: qgscallout.h:256
void render(QgsRenderContext &context, const QRectF &rect, const double angle, const QgsGeometry &anchor, QgsCalloutContext &calloutContext)
Renders the callout onto the specified render context.
Definition: qgscallout.cpp:148
@ OrderBelowIndividualLabels
Render callouts below their individual associated labels, some callouts may be drawn over other label...
Definition: qgscallout.h:107
@ OrderBelowAllLabels
Render callouts below all labels.
Definition: qgscallout.h:106
virtual DrawOrder drawOrder() const
Returns the desired drawing order (stacking) to use while rendering this callout.
Definition: qgscallout.cpp:143
bool enabled() const
Returns true if the the callout is enabled.
Definition: qgscallout.h:319
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
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.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
Definition: qgsrenderer.cpp:96
virtual QgsSymbolList originalSymbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:223
Container of fields for a vector layer.
Definition: qgsfields.h:45
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Definition: qgsgeos.cpp:1349
QgsCoordinateReferenceSystem originalFeatureCrs() const
Returns the original layer CRS of the feature associated with the label.
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
QString labelText() const
Text of the label.
GEOSGeometry * geometry() const
Gets access to the associated geometry.
bool labelAllParts() const
Returns true if all parts of the feature should be labeled.
bool reverseDirectionSymbol() const
Returns true if direction symbols should be reversed.
DirectionSymbolPlacement directionSymbolPlacement() const
Returns the placement for direction symbols.
QString leftDirectionSymbol() const
Returns the string to use for left direction arrows.
@ SymbolLeftRight
Place direction symbols on left/right of label.
@ SymbolAbove
Place direction symbols on above label.
@ SymbolBelow
Place direction symbols on below label.
QString rightDirectionSymbol() const
Returns the string to use for right direction arrows.
bool addDirectionSymbol() const
Returns true if '<' or '>' (or custom strings set via leftDirectionSymbol and rightDirectionSymbol) w...
bool mergeLines() const
Returns true if connected line features with identical label text should be merged prior to generatin...
ObstacleType type() const
Returns how features act as obstacles for labels.
bool testFlag(Flag f) const
Test whether a particular flag is enabled.
Flags flags() const
Gets flags of the labeling engine.
@ DrawUnplacedLabels
Whether to render unplaced labels as an indicator/warning for users.
@ DrawLabelRectOnly
Whether to only draw the label rect and not the actual label text (used for unit tests)
QColor unplacedLabelColor() const
Returns the color to use when rendering unplaced labels.
const QgsLabelingEngineSettings & engineSettings() const
Gets associated labeling engine settings.
const QgsMapSettings & mapSettings() const
Gets associated map settings.
QgsLabelingResults * results() const
For internal use by the providers.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
The QgsMapSettings class contains configuration for rendering of the map.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
void setMapRotation(double degrees, double cx, double cy)
Sets map rotation in degrees (clockwise).
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.h:90
void transformInPlace(double &x, double &y) const
Transforms device coordinates to map coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
A marker symbol type, for rendering Point and MultiPoint geometries.
Multi polygon geometry collection.
static QStringList splitToLines(const QString &text, const QString &wrapCharacter, int autoWrapLength=0, bool useMaxLineLengthWhenAutoWrapping=true)
Splits a text string to a list of separate lines, using a specified wrap character (wrapCharacter).
Contains settings for how a map layer will be labeled.
std::unique_ptr< QgsLabelFeature > registerFeatureWithDetails(const QgsFeature &feature, QgsRenderContext &context, QgsGeometry obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Registers a feature for labeling.
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
void startRender(QgsRenderContext &context)
Prepares the label settings for rendering.
bool displayAll
If true, all features will be labelled even when overlaps occur.
QString wrapChar
Wrapping character string.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label's property collection, used for data defined overrides.
QgsCoordinateTransform ct
bool drawLabels
Whether to draw labels for this layer.
QgsCallout * callout() const
Returns the label callout renderer, responsible for drawing label callouts.
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
bool centroidInside
true if centroid positioned labels must be placed inside their corresponding feature polygon,...
int priority
Label priority.
@ MultiJustify
Justified.
MultiLineAlign multilineAlign
Horizontal alignment of multi-line labels.
@ CalloutDraw
Show callout.
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
const QgsLabelObstacleSettings & obstacleSettings() const
Returns the label obstacle settings.
bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames, const QgsFields &fields, const QgsMapSettings &mapSettings, const QgsCoordinateReferenceSystem &crs)
Prepare for registration of features.
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
UpsideDownLabels upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
int autoWrapLength
If non-zero, indicates that label text should be automatically wrapped to (ideally) the specified num...
Qgis::UnplacedLabelVisibility unplacedVisibility() const
Returns the layer's unplaced label visibility.
bool useMaxLineLengthForAutoWrap
If true, indicates that when auto wrapping label text the autoWrapLength length indicates the maximum...
void stopRender(QgsRenderContext &context)
Finalises the label settings after use.
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:169
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
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.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
void setCurrentMaskId(int id)
Stores a mask id as the "current" one.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
const QgsMaskIdProvider * maskIdProvider() const
Returns the mask id provider attached to the context.
Scoped object for temporary override of the symbologyReferenceScale property of a QgsRenderContext.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:93
bool enabled() const
Returns whether the background is enabled.
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
Represents a block of text consisting of one or more QgsTextFragment objects.
Definition: qgstextblock.h:36
bool enabled() const
Returns whether the buffer is enabled.
Stores information relating to individual character formatting.
Represents a document consisting of one or more QgsTextBlock objects.
void append(const QgsTextBlock &block)
Appends a block to the document.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
bool allowHtmlFormatting() const
Returns true if text should be treated as a HTML document and HTML tags should be used for formatting...
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
QgsTextShadowSettings & shadow()
Returns a reference to the text drop shadow settings.
QFont font() const
Returns the font used for rendering text.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
Stores a fragment of text along with formatting overrides to be used when rendering the fragment.
Class that adds extra information to QgsLabelFeature for text labels.
const QMap< QgsPalLayerSettings::Property, QVariant > & dataDefinedValues() const
Gets data-defined values.
QgsTextDocument document() const
Returns the document for the label.
QFont definedFont() const
Font to be used for rendering.
QgsTextCharacterFormat characterFormat(int partId) const
Returns the character format corresponding to the specified label part.
QString text(int partId) const
Returns the text component corresponding to a specified label part.
QFontMetricsF * labelFontMetrics()
Metrics of the font for rendering.
@ AlignTop
Align to top.
TextPart
Components of text.
@ Text
Text component.
@ Buffer
Buffer component.
@ Background
Background shape.
HAlignment
Horizontal alignment.
@ AlignLeft
Left align.
@ AlignRight
Right align.
@ AlignCenter
Center align.
@ AlignJustify
Justify align.
@ Label
Label-specific draw mode.
bool enabled() const
Returns whether the shadow is enabled.
void setShadowPlacement(QgsTextShadowSettings::ShadowPlacement placement)
Sets the placement for the drop shadow.
@ ShadowBuffer
Draw shadow under buffer.
@ ShadowShape
Draw shadow under background shape.
@ ShadowLowest
Draw shadow below all text components.
@ ShadowText
Draw shadow under text.
QgsTextShadowSettings::ShadowPlacement shadowPlacement() const
Returns the placement for the drop shadow.
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
void stopRender(QgsRenderContext &context) override
To be called after rendering is complete.
QgsCoordinateReferenceSystem mCrs
Layer's CRS.
void drawLabelPrivate(pal::LabelPosition *label, QgsRenderContext &context, QgsPalLayerSettings &tmpLyr, QgsTextRenderer::TextPart drawType, double dpiRatio=1.0) const
Internal label drawing method.
virtual bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames)
Prepare for registration of features.
void drawUnplacedLabel(QgsRenderContext &context, pal::LabelPosition *label) const override
Draw an unplaced label.
QList< QgsLabelFeature * > mLabels
List of generated.
QgsVectorLayerLabelProvider(QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName=QString())
Convenience constructor to initialize the provider from given vector layer.
void startRender(QgsRenderContext &context) override
To be called before rendering of labels begins.
const QgsPalLayerSettings & settings() const
Returns the layer's settings.
static QgsGeometry getPointObstacleGeometry(QgsFeature &fet, QgsRenderContext &context, const QgsSymbolList &symbols)
Returns the geometry for a point feature which should be used as an obstacle for labels.
QgsWkbTypes::GeometryType mLayerGeometryType
Geometry type of layer.
QgsPalLayerSettings mSettings
Layer's labeling configuration.
std::unique_ptr< QgsAbstractFeatureSource > mSource
Layer's feature source.
QList< QgsLabelFeature * > labelFeatures(QgsRenderContext &context) override
Returns list of label features (they are owned by the provider and thus deleted on its destruction)
virtual QList< QgsLabelFeature * > registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels.
void init()
initialization method - called from constructors
void drawLabel(QgsRenderContext &context, pal::LabelPosition *label) const override
Draw this label at the position determined by the labeling engine.
void drawLabelBackground(QgsRenderContext &context, pal::LabelPosition *label) const override
Draw the background for the specified label.
Represents a vector layer which manages a vector based data sets.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
QgsFeatureId featureId() const
Returns the unique ID of the feature.
Definition: feature.cpp:161
Layer * layer()
Returns the layer that feature belongs to.
Definition: feature.cpp:156
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:94
LabelPosition is a candidate feature label position.
Definition: labelposition.h:56
double getAlpha() const
Returns the angle to rotate text (in rad).
double getHeight() const
bool getReversed() const
Quadrant getQuadrant() const
bool conflictsWithObstacle() const
Returns whether the position is marked as conflicting with an obstacle feature.
double getWidth() const
LabelPosition * nextPart() const
Returns the next part of this label position (i.e.
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
int getPartId() const
double getX(int i=0) const
Returns the down-left x coordinate.
double getY(int i=0) const
Returns the down-left y coordinate.
QgsAbstractLabelProvider * provider() const
Returns pointer to the associated provider.
Definition: layer.h:166
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:44
const QgsCoordinateReferenceSystem & crs
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31