QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
34 #include "feature.h"
35 #include "labelposition.h"
36 #include "callouts/qgscallout.h"
37 
38 #include "pal/layer.h"
39 
40 #include <QPicture>
41 #include <QTextDocument>
42 #include <QTextFragment>
43 
44 using namespace pal;
45 
46 QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName )
47  : QgsAbstractLabelProvider( layer, providerId )
48  , mSettings( settings ? * settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
49  , mLayerGeometryType( layer->geometryType() )
50  , mRenderer( layer->renderer() )
51  , mFields( layer->fields() )
52  , mCrs( layer->crs() )
53 {
54  mName = layerName.isEmpty() ? layer->id() : layerName;
55 
56  if ( withFeatureLoop )
57  {
58  mSource = qgis::make_unique<QgsVectorLayerFeatureSource>( layer );
59  }
60 
61  init();
62 }
63 
64 QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsWkbTypes::GeometryType geometryType, const QgsFields &fields, const QgsCoordinateReferenceSystem &crs, const QString &providerId, const QgsPalLayerSettings *settings, QgsMapLayer *layer, const QString &layerName )
65  : QgsAbstractLabelProvider( layer, providerId )
66  , mSettings( settings ? * settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
67  , mLayerGeometryType( geometryType )
68  , mRenderer( nullptr )
69  , mFields( fields )
70  , mCrs( crs )
71 {
72  mName = layerName.isEmpty() ? layer->id() : layerName;
73 
74  init();
75 }
76 
78 {
80  mFlags = Flags();
81  if ( mSettings.drawLabels )
82  mFlags |= DrawLabels;
83  if ( mSettings.displayAll )
89 
90  mPriority = 1 - mSettings.priority / 10.0; // convert 0..10 --> 1..0
91 
93  {
94  //override obstacle type to treat any intersection of a label with the point symbol as a high cost conflict
96  }
97  else
98  {
100  }
101 
103 }
104 
105 
107 {
108  qDeleteAll( mLabels );
109 }
110 
111 
112 bool QgsVectorLayerLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
113 {
114  const QgsMapSettings &mapSettings = mEngine->mapSettings();
115 
116  return mSettings.prepare( context, attributeNames, mFields, mapSettings, mCrs );
117 }
118 
120 {
122  mSettings.startRender( context );
123 }
124 
126 {
128  mSettings.stopRender( context );
129 }
130 
132 {
133  if ( !mSource )
134  {
135  // we have created the provider with "own feature loop" == false
136  // so it is assumed that prepare() has been already called followed by registerFeature() calls
137  return mLabels;
138  }
139 
140  QSet<QString> attrNames;
141  if ( !prepare( ctx, attrNames ) )
142  return QList<QgsLabelFeature *>();
143 
144  if ( mRenderer )
145  mRenderer->startRender( ctx, mFields );
146 
147  QgsRectangle layerExtent = ctx.extent();
150 
151  QgsFeatureRequest request;
152  request.setFilterRect( layerExtent );
153  request.setSubsetOfAttributes( attrNames, mFields );
154  QgsFeatureIterator fit = mSource->getFeatures( request );
155 
157  ctx.expressionContext().appendScope( symbolScope );
158  QgsFeature fet;
159  while ( fit.nextFeature( fet ) )
160  {
161  QgsGeometry obstacleGeometry;
162  const QgsSymbol *symbol = nullptr;
163  if ( mRenderer )
164  {
165  QgsSymbolList symbols = mRenderer->originalSymbolsForFeature( fet, ctx );
166  if ( !symbols.isEmpty() && fet.geometry().type() == QgsWkbTypes::PointGeometry )
167  {
168  //point feature, use symbol bounds as obstacle
169  obstacleGeometry = QgsVectorLayerLabelProvider::getPointObstacleGeometry( fet, ctx, symbols );
170  }
171  if ( !symbols.isEmpty() )
172  {
173  symbol = symbols.at( 0 );
174  symbolScope = QgsExpressionContextUtils::updateSymbolScope( symbol, symbolScope );
175  }
176  }
177  ctx.expressionContext().setFeature( fet );
178  registerFeature( fet, ctx, obstacleGeometry, symbol );
179  }
180 
181  if ( ctx.expressionContext().lastScope() == symbolScope )
182  delete ctx.expressionContext().popScope();
183 
184  if ( mRenderer )
185  mRenderer->stopRender( ctx );
186 
187  return mLabels;
188 }
189 
190 void QgsVectorLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
191 {
192  QgsLabelFeature *label = nullptr;
193 
194  mSettings.registerFeature( feature, context, &label, obstacleGeometry, symbol );
195  if ( label )
196  mLabels << label;
197 }
198 
200 {
201  if ( !fet.hasGeometry() || fet.geometry().type() != QgsWkbTypes::PointGeometry )
202  return QgsGeometry();
203 
204  bool isMultiPoint = fet.geometry().constGet()->nCoordinates() > 1;
205  std::unique_ptr< QgsAbstractGeometry > obstacleGeom;
206  if ( isMultiPoint )
207  obstacleGeom = qgis::make_unique< QgsMultiPolygon >();
208 
209  // for each point
210  for ( int i = 0; i < fet.geometry().constGet()->nCoordinates(); ++i )
211  {
212  QRectF bounds;
213  QgsPoint p = fet.geometry().constGet()->vertexAt( QgsVertexId( i, 0, 0 ) );
214  double x = p.x();
215  double y = p.y();
216  double z = 0; // dummy variable for coordinate transforms
217 
218  //transform point to pixels
219  if ( context.coordinateTransform().isValid() )
220  {
221  try
222  {
223  context.coordinateTransform().transformInPlace( x, y, z );
224  }
225  catch ( QgsCsException & )
226  {
227  return QgsGeometry();
228  }
229  }
230  context.mapToPixel().transformInPlace( x, y );
231 
232  QPointF pt( x, y );
233  const auto constSymbols = symbols;
234  for ( QgsSymbol *symbol : constSymbols )
235  {
236  if ( symbol->type() == QgsSymbol::Marker )
237  {
238  if ( bounds.isValid() )
239  bounds = bounds.united( static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet ) );
240  else
241  bounds = static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet );
242  }
243  }
244 
245  //convert bounds to a geometry
246  QVector< double > bX;
247  bX << bounds.left() << bounds.right() << bounds.right() << bounds.left();
248  QVector< double > bY;
249  bY << bounds.top() << bounds.top() << bounds.bottom() << bounds.bottom();
250  std::unique_ptr< QgsLineString > boundLineString = qgis::make_unique< QgsLineString >( bX, bY );
251 
252  //then transform back to map units
253  //TODO - remove when labeling is refactored to use screen units
254  for ( int i = 0; i < boundLineString->numPoints(); ++i )
255  {
256  QgsPointXY point = context.mapToPixel().toMapCoordinates( static_cast<int>( boundLineString->xAt( i ) ),
257  static_cast<int>( boundLineString->yAt( i ) ) );
258  boundLineString->setXAt( i, point.x() );
259  boundLineString->setYAt( i, point.y() );
260  }
261  if ( context.coordinateTransform().isValid() )
262  {
263  try
264  {
265  boundLineString->transform( context.coordinateTransform(), QgsCoordinateTransform::ReverseTransform );
266  }
267  catch ( QgsCsException & )
268  {
269  return QgsGeometry();
270  }
271  }
272  boundLineString->close();
273 
274  if ( context.coordinateTransform().isValid() )
275  {
276  // coordinate transforms may have resulted in nan coordinates - if so, strip these out
277  boundLineString->filterVertices( []( const QgsPoint & point )->bool
278  {
279  return std::isfinite( point.x() ) && std::isfinite( point.y() );
280  } );
281  if ( !boundLineString->isRing() )
282  return QgsGeometry();
283  }
284 
285  std::unique_ptr< QgsPolygon > obstaclePolygon = qgis::make_unique< QgsPolygon >();
286  obstaclePolygon->setExteriorRing( boundLineString.release() );
287 
288  if ( isMultiPoint )
289  {
290  static_cast<QgsMultiPolygon *>( obstacleGeom.get() )->addGeometry( obstaclePolygon.release() );
291  }
292  else
293  {
294  obstacleGeom = std::move( obstaclePolygon );
295  }
296  }
297 
298  return QgsGeometry( std::move( obstacleGeom ) );
299 }
300 
302 {
303  if ( !mSettings.drawLabels )
304  return;
305 
306  // render callout
308  {
309  drawCallout( context, label );
310  }
311 }
312 
313 void QgsVectorLayerLabelProvider::drawCallout( QgsRenderContext &context, pal::LabelPosition *label ) const
314 {
315  bool enabled = mSettings.callout()->enabled();
317  {
318  context.expressionContext().setOriginalValueVariable( enabled );
320  }
321  if ( enabled )
322  {
323  QgsMapToPixel xform = context.mapToPixel();
324  xform.setMapRotation( 0, 0, 0 );
325  QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
326  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
327  QRectF rect( outPt.x(), outPt.y(), outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
328 
330  g.transform( xform.transform() );
331  QgsCallout::QgsCalloutContext calloutContext;
332  calloutContext.allFeaturePartsLabeled = label->getFeaturePart()->feature()->labelAllParts();
333  mSettings.callout()->render( context, rect, label->getAlpha() * 180 / M_PI, g, calloutContext );
334  }
335 }
336 
338 {
339  if ( !mSettings.drawLabels )
340  return;
341 
342  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
343 
344  // Copy to temp, editable layer settings
345  // these settings will be changed by any data defined values, then used for rendering label components
346  // settings may be adjusted during rendering of components
347  QgsPalLayerSettings tmpLyr( mSettings );
348 
349  // apply any previously applied data defined settings for the label
350  const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->dataDefinedValues();
351 
352  //font
353  QFont dFont = lf->definedFont();
354  QgsDebugMsgLevel( QStringLiteral( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
355  QgsDebugMsgLevel( QStringLiteral( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
356 
357  QgsTextFormat format = tmpLyr.format();
358  format.setFont( dFont );
359 
360  // size has already been calculated and stored in the defined font - this calculated size
361  // is in pixels
362  format.setSize( dFont.pixelSize() );
364  tmpLyr.setFormat( format );
365 
367  {
368  //calculate font alignment based on label quadrant
369  switch ( label->getQuadrant() )
370  {
371  case LabelPosition::QuadrantAboveLeft:
372  case LabelPosition::QuadrantLeft:
373  case LabelPosition::QuadrantBelowLeft:
375  break;
376  case LabelPosition::QuadrantAbove:
377  case LabelPosition::QuadrantOver:
378  case LabelPosition::QuadrantBelow:
380  break;
381  case LabelPosition::QuadrantAboveRight:
382  case LabelPosition::QuadrantRight:
383  case LabelPosition::QuadrantBelowRight:
385  break;
386  }
387  }
388 
389  // update tmpLyr with any data defined text style values
390  QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
391 
392  // update tmpLyr with any data defined text buffer values
393  QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
394 
395  // update tmpLyr with any data defined text mask values
396  QgsPalLabeling::dataDefinedTextMask( tmpLyr, ddValues );
397 
398  // update tmpLyr with any data defined text formatting values
399  QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
400 
401  // update tmpLyr with any data defined shape background values
402  QgsPalLabeling::dataDefinedShapeBackground( tmpLyr, ddValues );
403 
404  // update tmpLyr with any data defined drop shadow values
405  QgsPalLabeling::dataDefinedDropShadow( tmpLyr, ddValues );
406 
407  // Render the components of a label in reverse order
408  // (backgrounds -> text)
409 
410  // render callout
412  {
413  drawCallout( context, label );
414  }
415 
417  {
418  QgsTextFormat format = tmpLyr.format();
419 
420  if ( tmpLyr.format().background().enabled() && tmpLyr.format().background().type() != QgsTextBackgroundSettings::ShapeMarkerSymbol ) // background shadows not compatible with marker symbol backgrounds
421  {
423  }
424  else if ( tmpLyr.format().buffer().enabled() )
425  {
427  }
428  else
429  {
431  }
432 
433  tmpLyr.setFormat( format );
434  }
435 
436  if ( tmpLyr.format().background().enabled() )
437  {
438  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Background );
439  }
440 
441  if ( tmpLyr.format().buffer().enabled() )
442  {
443  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Buffer );
444  }
445 
446  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Text );
447 
448  // add to the results
449  QString labeltext = label->getFeaturePart()->feature()->labelText();
450  mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, dFont, false, lf->hasFixedPosition(), mProviderId );
451 }
452 
454 {
455  if ( !mSettings.drawLabels )
456  return;
457 
458  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
459 
460  QgsPalLayerSettings tmpLyr( mSettings );
461  QgsTextFormat format = tmpLyr.format();
463  tmpLyr.setFormat( format );
464  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Text );
465 
466  // add to the results
467  QString labeltext = label->getFeaturePart()->feature()->labelText();
468  mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, tmpLyr.format().font(), false, lf->hasFixedPosition(), mProviderId, true );
469 }
470 
472 {
473  // NOTE: this is repeatedly called for multi-part labels
474  QPainter *painter = context.painter();
475 
476  // features are pre-rotated but not scaled/translated,
477  // so we only disable rotation here. Ideally, they'd be
478  // also pre-scaled/translated, as suggested here:
479  // https://github.com/qgis/QGIS/issues/20071
480  QgsMapToPixel xform = context.mapToPixel();
481  xform.setMapRotation( 0, 0, 0 );
482 
483  QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
484 
485  if ( mEngine->engineSettings().testFlag( QgsLabelingEngineSettings::DrawLabelRectOnly ) ) // TODO: this should get directly to labeling engine
486  {
487  //debugging rect
488  if ( drawType != QgsTextRenderer::Text )
489  return;
490 
491  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
492  QRectF rect( 0, 0, outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
493  painter->save();
494  painter->setRenderHint( QPainter::Antialiasing, false );
495  painter->translate( QPointF( outPt.x(), outPt.y() ) );
496  painter->rotate( -label->getAlpha() * 180 / M_PI );
497 
498  if ( label->conflictsWithObstacle() )
499  {
500  painter->setBrush( QColor( 255, 0, 0, 100 ) );
501  painter->setPen( QColor( 255, 0, 0, 150 ) );
502  }
503  else
504  {
505  painter->setBrush( QColor( 0, 255, 0, 100 ) );
506  painter->setPen( QColor( 0, 255, 0, 150 ) );
507  }
508 
509  painter->drawRect( rect );
510  painter->restore();
511 
512  if ( label->nextPart() )
513  drawLabelPrivate( label->nextPart(), context, tmpLyr, drawType, dpiRatio );
514 
515  return;
516  }
517 
518  QgsTextRenderer::Component component;
519  component.dpiRatio = dpiRatio;
520  component.origin = outPt;
521  component.rotation = label->getAlpha();
522 
523  if ( drawType == QgsTextRenderer::Background )
524  {
525  // get rotated label's center point
526  QPointF centerPt( outPt );
527  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth() / 2,
528  label->getY() + label->getHeight() / 2 );
529 
530  double xc = outPt2.x() - outPt.x();
531  double yc = outPt2.y() - outPt.y();
532 
533  double angle = -component.rotation;
534  double xd = xc * std::cos( angle ) - yc * std::sin( angle );
535  double yd = xc * std::sin( angle ) + yc * std::cos( angle );
536 
537  centerPt.setX( centerPt.x() + xd );
538  centerPt.setY( centerPt.y() + yd );
539 
540  component.center = centerPt;
541 
542  // convert label size to render units
543  double labelWidthPx = context.convertToPainterUnits( label->getWidth(), QgsUnitTypes::RenderMapUnits, QgsMapUnitScale() );
544  double labelHeightPx = context.convertToPainterUnits( label->getHeight(), QgsUnitTypes::RenderMapUnits, QgsMapUnitScale() );
545 
546  component.size = QSizeF( labelWidthPx, labelHeightPx );
547 
548  QgsTextRenderer::drawBackground( context, component, tmpLyr.format(), QgsTextDocument(), QgsTextRenderer::Label );
549  }
550 
551  else if ( drawType == QgsTextRenderer::Buffer
552  || drawType == QgsTextRenderer::Text )
553  {
554 
555  // TODO: optimize access :)
556  QgsTextLabelFeature *lf = static_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
557  QString txt = lf->text( label->getPartId() );
558  QFontMetricsF *labelfm = lf->labelFontMetrics();
559 
560  if ( auto *lMaskIdProvider = context.maskIdProvider() )
561  {
562  int maskId = lMaskIdProvider->maskId( label->getFeaturePart()->layer()->provider()->layerId(),
563  label->getFeaturePart()->layer()->provider()->providerId() );
564  context.setCurrentMaskId( maskId );
565  }
566 
567  //add the direction symbol if needed
568  if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line &&
569  tmpLyr.lineSettings().addDirectionSymbol() )
570  {
571  bool prependSymb = false;
572  QString symb = tmpLyr.lineSettings().rightDirectionSymbol();
573 
574  if ( label->getReversed() )
575  {
576  prependSymb = true;
577  symb = tmpLyr.lineSettings().leftDirectionSymbol();
578  }
579 
580  if ( tmpLyr.lineSettings().reverseDirectionSymbol() )
581  {
582  if ( symb == tmpLyr.lineSettings().rightDirectionSymbol() )
583  {
584  prependSymb = true;
585  symb = tmpLyr.lineSettings().leftDirectionSymbol();
586  }
587  else
588  {
589  prependSymb = false;
590  symb = tmpLyr.lineSettings().rightDirectionSymbol();
591  }
592  }
593 
594  switch ( tmpLyr.lineSettings().directionSymbolPlacement() )
595  {
597  prependSymb = true;
598  symb = symb + QStringLiteral( "\n" );
599  break;
600 
602  prependSymb = false;
603  symb = QStringLiteral( "\n" ) + symb;
604  break;
605 
607  break;
608  }
609 
610  if ( prependSymb )
611  {
612  txt.prepend( symb );
613  }
614  else
615  {
616  txt.append( symb );
617  }
618  }
619 
620 
624  else if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiRight )
628 
629  QgsTextRenderer::Component component;
630  component.origin = outPt;
631  component.rotation = label->getAlpha();
632 
633  QgsTextDocument document;
634  if ( !tmpLyr.format().allowHtmlFormatting() || tmpLyr.placement == QgsPalLayerSettings::Curved )
635  {
636  const QgsTextCharacterFormat c = lf->characterFormat( label->getPartId() );
637  const QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap );
638  for ( const QString &line : multiLineList )
639  document.append( QgsTextBlock( QgsTextFragment( line, c ) ) );
640  }
641  else
642  {
643  document = lf->document();
644  }
645 
646  QgsTextRenderer::drawTextInternal( drawType, context, tmpLyr.format(), component, document, labelfm,
648 
649  }
650  if ( label->nextPart() )
651  drawLabelPrivate( label->nextPart(), context, tmpLyr, drawType, dpiRatio );
652 }
653 
655 {
656  return mSettings;
657 }
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.
void render(QgsRenderContext &context, QRectF rect, const double angle, const QgsGeometry &anchor, QgsCalloutContext &calloutContext)
Renders the callout onto the specified render context.
Definition: qgscallout.cpp:118
@ OrderBelowIndividualLabels
Render callouts below their individual associated labels, some callouts may be drawn over other label...
Definition: qgscallout.h:83
@ OrderBelowAllLabels
Render callouts below all labels.
Definition: qgscallout.h:82
virtual DrawOrder drawOrder() const
Returns the desired drawing order (stacking) to use while rendering this callout.
Definition: qgscallout.cpp:113
bool enabled() const
Returns true if the the callout is enabled.
Definition: qgscallout.h:247
This class represents a coordinate reference system (CRS).
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent.
@ ReverseTransform
Transform from destination to source CRS.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
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:94
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 id, geometry and a list of field/values...
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:204
Container of fields for a vector layer.
Definition: qgsfields.h:45
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:127
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Definition: qgsgeos.cpp:1098
The QgsLabelFeature class describes a feature that should be used within the labeling engine.
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.
@ 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:85
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)
Set map rotation in degrees (clockwise)
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transform the point p from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.h:82
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.
Definition: qgssymbol.h:1004
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.
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.
void registerFeature(const QgsFeature &f, QgsRenderContext &context, QgsLabelFeature **labelFeature=nullptr, QgsGeometry obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Register a feature for labeling.
@ 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...
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:44
double y
Definition: qgspointxy.h:48
Q_GADGET double x
Definition: qgspointxy.h:47
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:154
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
Q_GADGET double x
Definition: qgspoint.h:41
double y
Definition: qgspoint.h:42
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...
void setCurrentMaskId(int id)
Stores a mask id as the "current" one.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
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.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:65
@ Marker
Marker symbol.
Definition: qgssymbol.h:88
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.
QgsTextDocument document() const
Returns the document for the label.
QFont definedFont()
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.
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > & dataDefinedValues() const
Gets data-defined values.
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:170
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:169
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.
virtual void 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.
QList< QgsLabelFeature * > labelFeatures(QgsRenderContext &context) override
Returns list of label features (they are owned by the provider and thus deleted on its destruction)
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:157
Layer * layer()
Returns the layer that feature belongs to.
Definition: feature.cpp:152
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:118
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:45
const QgsCoordinateReferenceSystem & crs
Contains additional contextual information about the context in which a callout is being rendered.
Definition: qgscallout.h:215
bool allFeaturePartsLabeled
true if all parts of associated feature were labeled
Definition: qgscallout.h:217
Utility class for identifying a unique vertex within a geometry.