QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
31 #include "feature.h"
32 #include "labelposition.h"
33 #include "callouts/qgscallout.h"
34 
35 #include <QPicture>
36 
37 using namespace pal;
38 
39 QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName )
40  : QgsAbstractLabelProvider( layer, providerId )
41  , mSettings( settings ? * settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
42  , mLayerGeometryType( layer->geometryType() )
43  , mRenderer( layer->renderer() )
44  , mFields( layer->fields() )
45  , mCrs( layer->crs() )
46 {
47  mName = layerName.isEmpty() ? layer->id() : layerName;
48 
49  if ( withFeatureLoop )
50  {
51  mSource = qgis::make_unique<QgsVectorLayerFeatureSource>( layer );
52  }
53 
54  init();
55 }
56 
58 {
60  mFlags = Flags();
61  if ( mSettings.drawLabels )
62  mFlags |= DrawLabels;
63  if ( mSettings.displayAll )
69 
70  mPriority = 1 - mSettings.priority / 10.0; // convert 0..10 --> 1..0
71 
73  {
74  //override obstacle type to treat any intersection of a label with the point symbol as a high cost conflict
76  }
77  else
78  {
80  }
81 
83 }
84 
85 
87 {
88  qDeleteAll( mLabels );
89 }
90 
91 
92 bool QgsVectorLayerLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
93 {
94  const QgsMapSettings &mapSettings = mEngine->mapSettings();
95 
96  return mSettings.prepare( context, attributeNames, mFields, mapSettings, mCrs );
97 }
98 
100 {
102  mSettings.startRender( context );
103 }
104 
106 {
108  mSettings.stopRender( context );
109 }
110 
112 {
113  if ( !mSource )
114  {
115  // we have created the provider with "own feature loop" == false
116  // so it is assumed that prepare() has been already called followed by registerFeature() calls
117  return mLabels;
118  }
119 
120  QSet<QString> attrNames;
121  if ( !prepare( ctx, attrNames ) )
122  return QList<QgsLabelFeature *>();
123 
124  if ( mRenderer )
125  mRenderer->startRender( ctx, mFields );
126 
127  QgsRectangle layerExtent = ctx.extent();
130 
131  QgsFeatureRequest request;
132  request.setFilterRect( layerExtent );
133  request.setSubsetOfAttributes( attrNames, mFields );
134  QgsFeatureIterator fit = mSource->getFeatures( request );
135 
137  ctx.expressionContext().appendScope( symbolScope );
138  QgsFeature fet;
139  while ( fit.nextFeature( fet ) )
140  {
141  QgsGeometry obstacleGeometry;
142  std::unique_ptr< QgsSymbol > symbol;
143  if ( mRenderer )
144  {
145  QgsSymbolList symbols = mRenderer->originalSymbolsForFeature( fet, ctx );
146  if ( !symbols.isEmpty() && fet.geometry().type() == QgsWkbTypes::PointGeometry )
147  {
148  //point feature, use symbol bounds as obstacle
149  obstacleGeometry = QgsVectorLayerLabelProvider::getPointObstacleGeometry( fet, ctx, symbols );
150  }
151  if ( !symbols.isEmpty() )
152  {
153  symbol.reset( symbols.at( 0 )->clone() );
154  symbolScope = QgsExpressionContextUtils::updateSymbolScope( symbol.get(), symbolScope );
155  }
156  }
157  ctx.expressionContext().setFeature( fet );
158  registerFeature( fet, ctx, obstacleGeometry, symbol.release() );
159  }
160 
161  if ( ctx.expressionContext().lastScope() == symbolScope )
162  delete ctx.expressionContext().popScope();
163 
164  if ( mRenderer )
165  mRenderer->stopRender( ctx );
166 
167  return mLabels;
168 }
169 
170 void QgsVectorLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
171 {
172  QgsLabelFeature *label = nullptr;
173 
174  mSettings.registerFeature( feature, context, &label, obstacleGeometry, symbol );
175  if ( label )
176  mLabels << label;
177 }
178 
180 {
181  if ( !fet.hasGeometry() || fet.geometry().type() != QgsWkbTypes::PointGeometry )
182  return QgsGeometry();
183 
184  bool isMultiPoint = fet.geometry().constGet()->nCoordinates() > 1;
185  std::unique_ptr< QgsAbstractGeometry > obstacleGeom;
186  if ( isMultiPoint )
187  obstacleGeom = qgis::make_unique< QgsMultiPolygon >();
188 
189  // for each point
190  for ( int i = 0; i < fet.geometry().constGet()->nCoordinates(); ++i )
191  {
192  QRectF bounds;
193  QgsPoint p = fet.geometry().constGet()->vertexAt( QgsVertexId( i, 0, 0 ) );
194  double x = p.x();
195  double y = p.y();
196  double z = 0; // dummy variable for coordinate transforms
197 
198  //transform point to pixels
199  if ( context.coordinateTransform().isValid() )
200  {
201  try
202  {
203  context.coordinateTransform().transformInPlace( x, y, z );
204  }
205  catch ( QgsCsException & )
206  {
207  return QgsGeometry();
208  }
209  }
210  context.mapToPixel().transformInPlace( x, y );
211 
212  QPointF pt( x, y );
213  const auto constSymbols = symbols;
214  for ( QgsSymbol *symbol : constSymbols )
215  {
216  if ( symbol->type() == QgsSymbol::Marker )
217  {
218  if ( bounds.isValid() )
219  bounds = bounds.united( static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet ) );
220  else
221  bounds = static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet );
222  }
223  }
224 
225  //convert bounds to a geometry
226  QVector< double > bX;
227  bX << bounds.left() << bounds.right() << bounds.right() << bounds.left();
228  QVector< double > bY;
229  bY << bounds.top() << bounds.top() << bounds.bottom() << bounds.bottom();
230  std::unique_ptr< QgsLineString > boundLineString = qgis::make_unique< QgsLineString >( bX, bY );
231 
232  //then transform back to map units
233  //TODO - remove when labeling is refactored to use screen units
234  for ( int i = 0; i < boundLineString->numPoints(); ++i )
235  {
236  QgsPointXY point = context.mapToPixel().toMapCoordinates( static_cast<int>( boundLineString->xAt( i ) ),
237  static_cast<int>( boundLineString->yAt( i ) ) );
238  boundLineString->setXAt( i, point.x() );
239  boundLineString->setYAt( i, point.y() );
240  }
241  if ( context.coordinateTransform().isValid() )
242  {
243  try
244  {
245  boundLineString->transform( context.coordinateTransform(), QgsCoordinateTransform::ReverseTransform );
246  }
247  catch ( QgsCsException & )
248  {
249  return QgsGeometry();
250  }
251  }
252  boundLineString->close();
253 
254  if ( context.coordinateTransform().isValid() )
255  {
256  // coordinate transforms may have resulted in nan coordinates - if so, strip these out
257  boundLineString->filterVertices( []( const QgsPoint & point )->bool
258  {
259  return std::isfinite( point.x() ) && std::isfinite( point.y() );
260  } );
261  if ( !boundLineString->isRing() )
262  return QgsGeometry();
263  }
264 
265  std::unique_ptr< QgsPolygon > obstaclePolygon = qgis::make_unique< QgsPolygon >();
266  obstaclePolygon->setExteriorRing( boundLineString.release() );
267 
268  if ( isMultiPoint )
269  {
270  static_cast<QgsMultiPolygon *>( obstacleGeom.get() )->addGeometry( obstaclePolygon.release() );
271  }
272  else
273  {
274  obstacleGeom = std::move( obstaclePolygon );
275  }
276  }
277 
278  return QgsGeometry( std::move( obstacleGeom ) );
279 }
280 
282 {
283  if ( !mSettings.drawLabels )
284  return;
285 
286  // render callout
288  {
289  drawCallout( context, label );
290  }
291 }
292 
293 void QgsVectorLayerLabelProvider::drawCallout( QgsRenderContext &context, pal::LabelPosition *label ) const
294 {
295  bool enabled = mSettings.callout()->enabled();
297  {
298  context.expressionContext().setOriginalValueVariable( enabled );
300  }
301  if ( enabled )
302  {
303  QgsMapToPixel xform = context.mapToPixel();
304  xform.setMapRotation( 0, 0, 0 );
305  QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
306  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
307  QRectF rect( outPt.x(), outPt.y(), outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
308 
310  g.transform( xform.transform() );
311  QgsCallout::QgsCalloutContext calloutContext;
312  calloutContext.allFeaturePartsLabeled = label->getFeaturePart()->feature()->labelAllParts();
313  mSettings.callout()->render( context, rect, label->getAlpha() * 180 / M_PI, g, calloutContext );
314  }
315 }
316 
318 {
319  if ( !mSettings.drawLabels )
320  return;
321 
322  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
323 
324  // Copy to temp, editable layer settings
325  // these settings will be changed by any data defined values, then used for rendering label components
326  // settings may be adjusted during rendering of components
327  QgsPalLayerSettings tmpLyr( mSettings );
328 
329  // apply any previously applied data defined settings for the label
330  const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->dataDefinedValues();
331 
332  //font
333  QFont dFont = lf->definedFont();
334  QgsDebugMsgLevel( QStringLiteral( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
335  QgsDebugMsgLevel( QStringLiteral( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
336 
337  QgsTextFormat format = tmpLyr.format();
338  format.setFont( dFont );
339 
340  // size has already been calculated and stored in the defined font - this calculated size
341  // is in pixels
342  format.setSize( dFont.pixelSize() );
344  tmpLyr.setFormat( format );
345 
347  {
348  //calculate font alignment based on label quadrant
349  switch ( label->getQuadrant() )
350  {
351  case LabelPosition::QuadrantAboveLeft:
352  case LabelPosition::QuadrantLeft:
353  case LabelPosition::QuadrantBelowLeft:
355  break;
356  case LabelPosition::QuadrantAbove:
357  case LabelPosition::QuadrantOver:
358  case LabelPosition::QuadrantBelow:
360  break;
361  case LabelPosition::QuadrantAboveRight:
362  case LabelPosition::QuadrantRight:
363  case LabelPosition::QuadrantBelowRight:
365  break;
366  }
367  }
368 
369  // update tmpLyr with any data defined text style values
370  QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
371 
372  // update tmpLyr with any data defined text buffer values
373  QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
374 
375  // update tmpLyr with any data defined text formatting values
376  QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
377 
378  // update tmpLyr with any data defined shape background values
379  QgsPalLabeling::dataDefinedShapeBackground( tmpLyr, ddValues );
380 
381  // update tmpLyr with any data defined drop shadow values
382  QgsPalLabeling::dataDefinedDropShadow( tmpLyr, ddValues );
383 
384  // Render the components of a label in reverse order
385  // (backgrounds -> text)
386 
387  // render callout
389  {
390  drawCallout( context, label );
391  }
392 
394  {
395  QgsTextFormat format = tmpLyr.format();
396 
397  if ( tmpLyr.format().background().enabled() && tmpLyr.format().background().type() != QgsTextBackgroundSettings::ShapeMarkerSymbol ) // background shadows not compatible with marker symbol backgrounds
398  {
400  }
401  else if ( tmpLyr.format().buffer().enabled() )
402  {
404  }
405  else
406  {
408  }
409 
410  tmpLyr.setFormat( format );
411  }
412 
413  if ( tmpLyr.format().background().enabled() )
414  {
415  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Background );
416  }
417 
418  if ( tmpLyr.format().buffer().enabled() )
419  {
420  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Buffer );
421  }
422 
423  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Text );
424 
425  // add to the results
426  QString labeltext = label->getFeaturePart()->feature()->labelText();
427  mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, dFont, false, lf->hasFixedPosition(), mProviderId );
428 }
429 
431 {
432  if ( !mSettings.drawLabels )
433  return;
434 
435  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
436 
437  QgsPalLayerSettings tmpLyr( mSettings );
438  QgsTextFormat format = tmpLyr.format();
440  tmpLyr.setFormat( format );
441  drawLabelPrivate( label, context, tmpLyr, QgsTextRenderer::Text );
442 
443  // add to the results
444  QString labeltext = label->getFeaturePart()->feature()->labelText();
445  mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, tmpLyr.format().font(), false, lf->hasFixedPosition(), mProviderId, true );
446 }
447 
449 {
450  // NOTE: this is repeatedly called for multi-part labels
451  QPainter *painter = context.painter();
452 
453  // features are pre-rotated but not scaled/translated,
454  // so we only disable rotation here. Ideally, they'd be
455  // also pre-scaled/translated, as suggested here:
456  // https://github.com/qgis/QGIS/issues/20071
457  QgsMapToPixel xform = context.mapToPixel();
458  xform.setMapRotation( 0, 0, 0 );
459 
460  QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
461 
462  if ( mEngine->engineSettings().testFlag( QgsLabelingEngineSettings::DrawLabelRectOnly ) ) // TODO: this should get directly to labeling engine
463  {
464  //debugging rect
465  if ( drawType != QgsTextRenderer::Text )
466  return;
467 
468  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
469  QRectF rect( 0, 0, outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
470  painter->save();
471  painter->setRenderHint( QPainter::Antialiasing, false );
472  painter->translate( QPointF( outPt.x(), outPt.y() ) );
473  painter->rotate( -label->getAlpha() * 180 / M_PI );
474 
475  if ( label->conflictsWithObstacle() )
476  {
477  painter->setBrush( QColor( 255, 0, 0, 100 ) );
478  painter->setPen( QColor( 255, 0, 0, 150 ) );
479  }
480  else
481  {
482  painter->setBrush( QColor( 0, 255, 0, 100 ) );
483  painter->setPen( QColor( 0, 255, 0, 150 ) );
484  }
485 
486  painter->drawRect( rect );
487  painter->restore();
488 
489  if ( label->getNextPart() )
490  drawLabelPrivate( label->getNextPart(), context, tmpLyr, drawType, dpiRatio );
491 
492  return;
493  }
494 
495  QgsTextRenderer::Component component;
496  component.dpiRatio = dpiRatio;
497  component.origin = outPt;
498  component.rotation = label->getAlpha();
499 
500 
501 
502  if ( drawType == QgsTextRenderer::Background )
503  {
504  // get rotated label's center point
505  QPointF centerPt( outPt );
506  QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth() / 2,
507  label->getY() + label->getHeight() / 2 );
508 
509  double xc = outPt2.x() - outPt.x();
510  double yc = outPt2.y() - outPt.y();
511 
512  double angle = -component.rotation;
513  double xd = xc * std::cos( angle ) - yc * std::sin( angle );
514  double yd = xc * std::sin( angle ) + yc * std::cos( angle );
515 
516  centerPt.setX( centerPt.x() + xd );
517  centerPt.setY( centerPt.y() + yd );
518 
519  component.center = centerPt;
520 
521  // convert label size to render units
522  double labelWidthPx = context.convertToPainterUnits( label->getWidth(), QgsUnitTypes::RenderMapUnits, QgsMapUnitScale() );
523  double labelHeightPx = context.convertToPainterUnits( label->getHeight(), QgsUnitTypes::RenderMapUnits, QgsMapUnitScale() );
524 
525  component.size = QSizeF( labelWidthPx, labelHeightPx );
526 
527  QgsTextRenderer::drawBackground( context, component, tmpLyr.format(), QStringList(), QgsTextRenderer::Label );
528  }
529 
530  else if ( drawType == QgsTextRenderer::Buffer
531  || drawType == QgsTextRenderer::Text )
532  {
533 
534  // TODO: optimize access :)
535  QgsTextLabelFeature *lf = static_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
536  QString txt = lf->text( label->getPartId() );
537  QFontMetricsF *labelfm = lf->labelFontMetrics();
538 
539  //add the direction symbol if needed
540  if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line &&
541  tmpLyr.addDirectionSymbol )
542  {
543  bool prependSymb = false;
544  QString symb = tmpLyr.rightDirectionSymbol;
545 
546  if ( label->getReversed() )
547  {
548  prependSymb = true;
549  symb = tmpLyr.leftDirectionSymbol;
550  }
551 
552  if ( tmpLyr.reverseDirectionSymbol )
553  {
554  if ( symb == tmpLyr.rightDirectionSymbol )
555  {
556  prependSymb = true;
557  symb = tmpLyr.leftDirectionSymbol;
558  }
559  else
560  {
561  prependSymb = false;
562  symb = tmpLyr.rightDirectionSymbol;
563  }
564  }
565 
567  {
568  prependSymb = true;
569  symb = symb + QStringLiteral( "\n" );
570  }
572  {
573  prependSymb = false;
574  symb = QStringLiteral( "\n" ) + symb;
575  }
576 
577  if ( prependSymb )
578  {
579  txt.prepend( symb );
580  }
581  else
582  {
583  txt.append( symb );
584  }
585  }
586 
587  //QgsDebugMsgLevel( "drawLabel " + txt, 4 );
588  QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap );
589 
593  else if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiRight )
595 
596  QgsTextRenderer::Component component;
597  component.origin = outPt;
598  component.rotation = label->getAlpha();
599 
600  QgsTextRenderer::drawTextInternal( drawType, context, tmpLyr.format(), component, multiLineList, labelfm,
601  hAlign, QgsTextRenderer::Label );
602 
603  }
604 
605  // NOTE: this used to be within above multi-line loop block, at end. (a mistake since 2010? [LS])
606  if ( label->getNextPart() )
607  drawLabelPrivate( label->getNextPart(), context, tmpLyr, drawType, dpiRatio );
608 }
609 
611 {
612  return mSettings;
613 }
QList< QgsLabelFeature * > mLabels
List of generated.
QColor unplacedLabelColor() const
Returns the color to use when rendering unplaced labels.
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
Wrapper for iterator of features from vector data provider or vector layer.
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.
QString labelText() const
Text of the label.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
double y
Definition: qgspoint.h:42
QString leftDirectionSymbol
String to use for left direction arrows.
QgsWkbTypes::GeometryType mLayerGeometryType
Geometry type of layer.
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
QgsTextShadowSettings::ShadowPlacement shadowPlacement() const
Returns the placement for the drop shadow.
QgsPalLayerSettings::Placement mPlacement
Placement strategy.
void registerFeature(const QgsFeature &f, QgsRenderContext &context, QgsLabelFeature **labelFeature=nullptr, QgsGeometry obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Register a feature for labeling.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
Definition: feature.cpp:151
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
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:109
std::unique_ptr< QgsAbstractFeatureSource > mSource
Layer&#39;s feature source.
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:118
virtual bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames)
Prepare for registration of features.
const QgsLabelingEngine * mEngine
Associated labeling engine.
Contains additional contextual information about the context in which a callout is being rendered...
Definition: qgscallout.h:195
Draw shadow under buffer.
UpsideDownLabels upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
Place direction symbols on below label.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
double mPriority
Default priority of labels.
QgsTextShadowSettings & shadow()
Returns a reference to the text drop shadow settings.
double getY(int i=0) const
Returns the down-left y coordinate.
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
HAlignment
Horizontal alignment.
void setFont(const QFont &font)
Sets the font used for rendering text.
void stopRender(QgsRenderContext &context) override
To be called after rendering is complete.
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > & dataDefinedValues() const
Gets data-defined values.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Class that adds extra information to QgsLabelFeature for text labels.
GEOSGeometry * geometry() const
Gets access to the associated geometry.
bool addDirectionSymbol
If true, &#39;<&#39; or &#39;>&#39; (or custom strings set via leftDirectionSymbol and rightDirectionSymbol) will be ...
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
Whether to only draw the label rect and not the actual label text (used for unit tests) ...
bool drawLabels
Whether to draw labels for this layer.
bool mergeLines
true if connected line features with identical label text should be merged prior to generating label ...
MultiLineAlign multilineAlign
Horizontal alignment of multi-line labels.
FeaturePart * getFeaturePart()
Returns the feature corresponding to this labelposition.
virtual DrawOrder drawOrder() const
Returns the desired drawing order (stacking) to use while rendering this callout. ...
Definition: qgscallout.cpp:104
Label-specific draw mode.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
const QgsCoordinateReferenceSystem & crs
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
int autoWrapLength
If non-zero, indicates that label text should be automatically wrapped to (ideally) the specified num...
QgsCoordinateTransform ct
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
bool reverseDirectionSymbol
True if direction symbols should be reversed.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:860
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
virtual QgsSymbolList originalSymbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Whether adjacent lines (with the same label text) should be merged.
The QgsMapSettings class contains configuration for rendering of the map.
QList< QgsLabelFeature * > labelFeatures(QgsRenderContext &context) override
Returns list of label features (they are owned by the provider and thus deleted on its destruction) ...
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
void init()
initialization method - called from constructors
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
ObstacleType obstacleType
Controls how features act as obstacles for labels.
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:44
bool displayAll
If true, all features will be labelled even when overlaps occur.
void setSize(double size)
Sets the size for rendered text.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
const QgsLabelingEngineSettings & engineSettings() const
Gets associated labeling engine settings.
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Definition: qgsgeos.cpp:1081
Utility class for identifying a unique vertex within a geometry.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Render callouts below their individual associated labels, some callouts may be drawn over other label...
Definition: qgscallout.h:82
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent...
Buffer component.
double getHeight() const
QgsPalLayerSettings mSettings
Layer&#39;s labeling configuration.
const QgsPalLayerSettings & settings() const
Returns the layer&#39;s settings.
LabelPosition * getNextPart() const
void setColor(const QColor &color)
Sets the color that text will be rendered in.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Flags mFlags
Flags altering drawing and registration of features.
Draw shadow under text.
Whether location of centroid must be inside of polygons.
bool allFeaturePartsLabeled
true if all parts of associated feature were labeled
Definition: qgscallout.h:198
Quadrant getQuadrant() const
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
QString text(int partId) const
Returns the text component corresponding to a specified label part.
Whether all features will be labelled even though overlaps occur.
Single scope for storing variables and functions for use within a QgsExpressionContext.
Render callouts below all labels.
Definition: qgscallout.h:81
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
The QgsAbstractLabelProvider class is an interface class.
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc...
double x
Definition: qgspointxy.h:47
Place direction symbols on above label.
Draw shadow below all text components.
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...
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsExpressionContext & expressionContext()
Gets the expression context.
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...
QString wrapChar
Wrapping character string.
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...
TextPart
Components of text.
QgsFields mFields
Layer&#39;s fields.
QString rightDirectionSymbol
String to use for right direction arrows.
Marker symbol.
Definition: qgssymbol.h:85
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon&#39;...
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
QFont definedFont()
Font to be used for rendering.
bool enabled() const
Returns true if the the callout is enabled.
Definition: qgscallout.h:228
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
QPainter * painter()
Returns the destination QPainter for the render operation.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
const QgsMapToPixel & mapToPixel() const
Returns the context&#39;s map to pixel transform, which transforms between map coordinates and device coo...
Transform from destination to source CRS.
double getAlpha() const
Returns the angle to rotate text (in rad).
Multi polygon geometry collection.
QString mName
Name of the layer.
bool enabled() const
Returns whether the shadow is enabled.
Struct for storing maximum and minimum scales for measurements in map units.
QgsCoordinateReferenceSystem mCrs
Layer&#39;s CRS.
double getWidth() const
bool conflictsWithObstacle() const
Returns whether the position is marked as conflicting with an obstacle feature.
double getX(int i=0) const
Returns the down-left x coordinate.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
Definition: qgsrenderer.cpp:93
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
const QgsMapSettings & mapSettings() const
Gets associated map settings.
bool enabled() const
Returns whether the background is enabled.
bool testFlag(Flag f) const
Test whether a particular flag is enabled.
QgsLabelingResults * results() const
For internal use by the providers.
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QString mProviderId
Associated provider ID (one layer may have multiple providers, e.g. in rule-based labeling) ...
LabelPosition is a candidate feature label position.
Definition: labelposition.h:55
QgsPalLayerSettings::ObstacleType mObstacleType
Type of the obstacle of feature geometries.
virtual void startRender(QgsRenderContext &context)
To be called before rendering of labels begins.
bool enabled() const
Returns whether the buffer is enabled.
QgsPalLayerSettings::UpsideDownLabels mUpsidedownLabels
How to handle labels that would be upside down.
void setShadowPlacement(QgsTextShadowSettings::ShadowPlacement placement)
Sets the placement for the drop shadow.
Draw shadow under background shape.
void startRender(QgsRenderContext &context)
Prepares the label settings for rendering.
QgsCallout * callout() const
Returns the label callout renderer, responsible for drawing label callouts.
Whether the labels should be rendered.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:126
QgsGeometry geometry
Definition: qgsfeature.h:67
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
bool getReversed() const
bool nextFeature(QgsFeature &f)
void drawLabelBackground(QgsRenderContext &context, pal::LabelPosition *label) const override
Draw the background for the specified label.
void startRender(QgsRenderContext &context) override
To be called before rendering of labels begins.
Container for all settings relating to text rendering.
QFontMetricsF * labelFontMetrics()
Metrics of the font for rendering.
bool centroidInside
true if centroid positioned labels must be placed inside their corresponding feature polygon...
virtual void stopRender(QgsRenderContext &context)
To be called after rendering is complete.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Represents a vector layer which manages a vector based data sets.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
QString mLayerId
Associated layer&#39;s ID, if applicable.
bool labelAllParts() const
Returns true if all parts of the feature should be labeled.
QFont font() const
Returns the font used for rendering text.
bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames, const QgsFields &fields, const QgsMapSettings &mapSettings, const QgsCoordinateReferenceSystem &crs)
Prepare for registration of features.
int priority
Label priority.
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
void drawLabel(QgsRenderContext &context, pal::LabelPosition *label) const override
Draw this label at the position determined by the labeling engine.
void drawLabelPrivate(pal::LabelPosition *label, QgsRenderContext &context, QgsPalLayerSettings &tmpLyr, QgsTextRenderer::TextPart drawType, double dpiRatio=1.0) const
Internal label drawing method.
bool useMaxLineLengthForAutoWrap
If true, indicates that when auto wrapping label text the autoWrapLength length indicates the maximum...
int getPartId() const
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)...
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.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label&#39;s property collection, used for data defined overrides.
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.
void stopRender(QgsRenderContext &context)
Finalises the label settings after use.
DirectionSymbols placeDirectionSymbol
Placement option for direction symbols.
void drawUnplacedLabel(QgsRenderContext &context, pal::LabelPosition *label) const override
Draw an unplaced label.
double x
Definition: qgspoint.h:41