QGIS API Documentation 4.3.0-Master (0cfde48c85b)
Loading...
Searching...
No Matches
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 "callouts/qgscallout.h"
19#include "feature.h"
20#include "labelposition.h"
21#include "pal/layer.h"
23#include "qgsgeometry.h"
24#include "qgslabelingresults.h"
25#include "qgslabelsearchtree.h"
26#include "qgslinestring.h"
27#include "qgslogger.h"
28#include "qgsmarkersymbol.h"
29#include "qgsmaskidprovider.h"
30#include "qgsmultipolygon.h"
31#include "qgspallabeling.h"
32#include "qgspolygon.h"
33#include "qgsrenderer.h"
34#include "qgssymbol.h"
36#include "qgstextfragment.h"
37#include "qgstextlabelfeature.h"
38#include "qgstextrenderer.h"
39#include "qgsvectorlayer.h"
41
42#include <QPicture>
43#include <QString>
44#include <QTextDocument>
45#include <QTextFragment>
46
47using namespace Qt::StringLiterals;
48
49using namespace pal;
50
51//
52// QgsLabelFeatureDetails
53//
54
56{
57 return mObstacleGeometry;
58}
59
61{
62 mObstacleGeometry = geometry;
63}
64
66{
67 return mSymbol;
68}
69
71{
72 mSymbol = symbol;
73}
74
76{
77 return mIsSelected;
78}
79
81{
82 mIsSelected = isSelected;
83}
84
85//
86// QgsVectorLayerLabelProvider
87//
88
89QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName )
91 , mSettings( settings ? *settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
92 , mLayerGeometryType( layer->geometryType() )
93 , mRenderer( layer->renderer() )
94 , mFields( layer->fields() )
95 , mCrs( layer->crs() )
96{
97 mName = layerName.isEmpty() ? layer->id() : layerName;
98
99 if ( withFeatureLoop )
100 {
101 mSource = std::make_unique<QgsVectorLayerFeatureSource>( layer );
102 }
103
104 init();
105}
106
108 Qgis::GeometryType geometryType, const QgsFields &fields, const QgsCoordinateReferenceSystem &crs, const QString &providerId, const QgsPalLayerSettings *settings, QgsMapLayer *layer, const QString &layerName
109)
111 , mSettings( settings ? *settings : QgsPalLayerSettings() ) // TODO: all providers should have valid settings?
112 , mLayerGeometryType( geometryType )
113 , mFields( fields )
114 , mCrs( crs )
115{
116 mName = layerName.isEmpty() ? layer->id() : layerName;
117
118 init();
119}
120
122{
123 mPlacement = mSettings.placement;
124
125 mFlags = Flags();
126 if ( mSettings.drawLabels )
128 if ( mSettings.lineSettings().mergeLines() && !mSettings.lineSettings().addDirectionSymbol() )
130 if ( mSettings.centroidInside )
132
133 mPriority = 1 - mSettings.priority / 10.0; // convert 0..10 --> 1..0
134
136 {
137 //override obstacle type to treat any intersection of a label with the point symbol as a high cost conflict
139 }
140 else
141 {
142 mObstacleType = mSettings.obstacleSettings().type();
143 }
144
145 mUpsidedownLabels = mSettings.upsidedownLabels;
146}
147
148
153
154
155bool QgsVectorLayerLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
156{
157 const QgsMapSettings &mapSettings = mEngine->mapSettings();
158
159 return mSettings.prepare( context, attributeNames, mFields, mapSettings, mCrs );
160}
161
163{
165 mSettings.startRender( context );
166}
167
169{
171 mSettings.stopRender( context );
172}
173
175{
176 if ( !mSource )
177 {
178 // we have created the provider with "own feature loop" == false
179 // so it is assumed that prepare() has been already called followed by registerFeature() calls
180 return mLabels;
181 }
182
183 QSet<QString> attrNames;
184 if ( !prepare( ctx, attrNames ) )
185 return QList<QgsLabelFeature *>();
186
187 if ( mRenderer )
188 mRenderer->startRender( ctx, mFields );
189
190 QgsRectangle layerExtent = ctx.extent();
191 if ( mSettings.ct.isValid() && !mSettings.ct.isShortCircuited() )
192 {
193 QgsCoordinateTransform extentTransform = mSettings.ct;
194 extentTransform.setBallparkTransformsAreAppropriate( true );
195 layerExtent = extentTransform.transformBoundingBox( ctx.extent(), Qgis::TransformDirection::Reverse );
196 }
197
198 QgsFeatureRequest request;
199 request.setFilterRect( layerExtent );
200 request.setSubsetOfAttributes( attrNames, mFields );
201 QgsFeatureIterator fit = mSource->getFeatures( request );
202
204 ctx.expressionContext().appendScope( symbolScope );
205 QgsFeature fet;
206 while ( fit.nextFeature( fet ) )
207 {
209 if ( mRenderer )
210 {
211 QgsSymbolList symbols = mRenderer->originalSymbolsForFeature( fet, ctx );
212 if ( !symbols.isEmpty() && fet.geometry().type() == Qgis::GeometryType::Point )
213 {
214 //point feature, use symbol bounds as obstacle
216 }
217 if ( !symbols.isEmpty() )
218 {
219 details.setSymbol( symbols.at( 0 ) );
220 symbolScope = QgsExpressionContextUtils::updateSymbolScope( details.symbol(), symbolScope );
221 }
222 }
223 ctx.expressionContext().setFeature( fet );
224 registerFeature( fet, ctx, details );
225 }
226
227 if ( ctx.expressionContext().lastScope() == symbolScope )
228 delete ctx.expressionContext().popScope();
229
230 if ( mRenderer )
231 mRenderer->stopRender( ctx );
232
233 return mLabels;
234}
235
236QList< QgsLabelFeature * > QgsVectorLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsLabelFeatureDetails &details )
237{
238 std::vector< std::unique_ptr< QgsLabelFeature > > labels = mSettings.registerFeatureWithDetails( feature, context, details );
239 QList< QgsLabelFeature * > res;
240 for ( auto &it : labels )
241 {
242 if ( it )
243 {
244 res << it.get();
245 mLabels << it.release();
246 }
247 }
248 return res;
249}
250
252{
253 if ( !fet.hasGeometry() || fet.geometry().type() != Qgis::GeometryType::Point )
254 return QgsGeometry();
255
256 bool isMultiPoint = fet.geometry().constGet()->nCoordinates() > 1;
257 std::unique_ptr< QgsAbstractGeometry > obstacleGeom;
258 if ( isMultiPoint )
259 obstacleGeom = std::make_unique< QgsMultiPolygon >();
260
261 // for each point
262 for ( int i = 0; i < fet.geometry().constGet()->nCoordinates(); ++i )
263 {
264 QRectF bounds;
265 QgsPoint p = fet.geometry().constGet()->vertexAt( QgsVertexId( i, 0, 0 ) );
266 double x = p.x();
267 double y = p.y();
268 double z = 0; // dummy variable for coordinate transforms
269
270 //transform point to pixels
271 if ( context.coordinateTransform().isValid() )
272 {
273 try
274 {
275 context.coordinateTransform().transformInPlace( x, y, z );
276 }
277 catch ( QgsCsException & )
278 {
279 return QgsGeometry();
280 }
281 }
282 context.mapToPixel().transformInPlace( x, y );
283
284 QPointF pt( x, y );
285 const auto constSymbols = symbols;
286 for ( QgsSymbol *symbol : constSymbols )
287 {
288 if ( symbol->type() == Qgis::SymbolType::Marker )
289 {
290 if ( bounds.isValid() )
291 bounds = bounds.united( static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet ) );
292 else
293 bounds = static_cast< QgsMarkerSymbol * >( symbol )->bounds( pt, context, fet );
294 }
295 }
296
297 //convert bounds to a geometry
298 QVector< double > bX;
299 bX << bounds.left() << bounds.right() << bounds.right() << bounds.left();
300 QVector< double > bY;
301 bY << bounds.top() << bounds.top() << bounds.bottom() << bounds.bottom();
302 auto boundLineString = std::make_unique< QgsLineString >( bX, bY );
303
304 //then transform back to map units
305 //TODO - remove when labeling is refactored to use screen units
306 for ( int i = 0; i < boundLineString->numPoints(); ++i )
307 {
308 QgsPointXY point = context.mapToPixel().toMapCoordinates( static_cast<int>( boundLineString->xAt( i ) ), static_cast<int>( boundLineString->yAt( i ) ) );
309 boundLineString->setXAt( i, point.x() );
310 boundLineString->setYAt( i, point.y() );
311 }
312 if ( context.coordinateTransform().isValid() )
313 {
314 try
315 {
316 boundLineString->transform( context.coordinateTransform(), Qgis::TransformDirection::Reverse );
317 }
318 catch ( QgsCsException & )
319 {
320 return QgsGeometry();
321 }
322 }
323 boundLineString->close();
324
325 if ( context.coordinateTransform().isValid() )
326 {
327 // coordinate transforms may have resulted in nan coordinates - if so, strip these out
328 boundLineString->filterVertices( []( const QgsPoint &point ) -> bool { return std::isfinite( point.x() ) && std::isfinite( point.y() ); } );
329 if ( !boundLineString->isRing() )
330 return QgsGeometry();
331 }
332
333 auto obstaclePolygon = std::make_unique< QgsPolygon >();
334 obstaclePolygon->setExteriorRing( boundLineString.release() );
335
336 if ( isMultiPoint )
337 {
338 static_cast<QgsMultiPolygon *>( obstacleGeom.get() )->addGeometry( obstaclePolygon.release() );
339 }
340 else
341 {
342 obstacleGeom = std::move( obstaclePolygon );
343 }
344 }
345
346 return QgsGeometry( std::move( obstacleGeom ) );
347}
348
350{
351 if ( !mSettings.drawLabels )
352 return;
353
354 // render callout
355 if ( mSettings.callout() && mSettings.callout()->drawOrder() == QgsCallout::OrderBelowAllLabels )
356 {
357 drawCallout( context, label );
358 }
359}
360
361void QgsVectorLayerLabelProvider::drawCallout( QgsRenderContext &context, pal::LabelPosition *label ) const
362{
363 bool enabled = mSettings.callout()->enabled();
365 {
366 context.expressionContext().setOriginalValueVariable( enabled );
368 }
369 if ( enabled )
370 {
371 QgsMapToPixel xform = context.mapToPixel();
372 xform.setMapRotation( 0, 0, 0 );
373 QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
374 QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth(), label->getY() + label->getHeight() );
375 QRectF rect( outPt.x(), outPt.y(), outPt2.x() - outPt.x(), outPt2.y() - outPt.y() );
376
377 QgsGeometry g( QgsGeos::fromGeos( label->getFeaturePart()->feature()->geometry() ) );
378 g.transform( xform.transform() );
379 QgsCallout::QgsCalloutContext calloutContext;
381 calloutContext.originalFeatureCrs = label->getFeaturePart()->feature()->originalFeatureCrs();
382 mSettings.callout()->render( context, rect, label->getAlpha() * 180 / M_PI, g, calloutContext );
383
384 const QList< QgsCalloutPosition > renderedPositions = calloutContext.positions();
385
386 for ( QgsCalloutPosition position : renderedPositions )
387 {
388 position.layerID = mLayerId;
389 position.featureId = label->getFeaturePart()->featureId();
390 position.providerID = mProviderId;
391 mEngine->results()->insertCallout( position );
392 }
393 }
394}
395
397{
398 if ( !mSettings.drawLabels )
399 return;
400
401 QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
402 if ( !lf )
403 return;
404
405 // Copy to temp, editable layer settings
406 // these settings will be changed by any data defined values, then used for rendering label components
407 // settings may be adjusted during rendering of components
409
410 // apply any previously applied data defined settings for the label
411 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->dataDefinedValues();
412
413 //font
414 QFont dFont = lf->definedFont();
415 QgsDebugMsgLevel( u"PAL font tmpLyr: %1, Style: %2"_s.arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
416 QgsDebugMsgLevel( u"PAL font definedFont: %1, Style: %2"_s.arg( dFont.toString(), dFont.styleName() ), 4 );
417
418 QgsTextFormat format = tmpLyr.format();
419 format.setFont( dFont );
420
421 // size has already been calculated and stored in the defined font - this calculated size
422 // is in pixels
423 format.setSize( dFont.pixelSize() );
425 tmpLyr.setFormat( format );
426
428 {
429 //calculate font alignment based on label quadrant
430 switch ( label->quadrant() )
431 {
436 break;
441 break;
446 break;
447 }
448 }
449
450 // update tmpLyr with any data defined text style values
451 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
452
453 // update tmpLyr with any data defined text buffer values
454 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
455
456 // update tmpLyr with any data defined text mask values
457 QgsPalLabeling::dataDefinedTextMask( tmpLyr, ddValues );
458
459 // update tmpLyr with any data defined text formatting values
460 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
461
462 // update tmpLyr with any data defined shape background values
463 QgsPalLabeling::dataDefinedShapeBackground( tmpLyr, ddValues );
464
465 // update tmpLyr with any data defined drop shadow values
466 QgsPalLabeling::dataDefinedDropShadow( tmpLyr, ddValues );
467
468 // Render the components of a label in reverse order
469 // (backgrounds -> text)
470
471 // render callout
472 if ( mSettings.callout() && mSettings.callout()->drawOrder() == QgsCallout::OrderBelowIndividualLabels )
473 {
474 drawCallout( context, label );
475 }
476
478 {
479 QgsTextFormat format = tmpLyr.format();
480
481 if ( tmpLyr.format().background().enabled() && tmpLyr.format().background().type() != QgsTextBackgroundSettings::ShapeMarkerSymbol ) // background shadows not compatible with marker symbol backgrounds
482 {
484 }
485 else if ( tmpLyr.format().buffer().enabled() )
486 {
488 }
489 else
490 {
492 }
493
494 tmpLyr.setFormat( format );
495 }
496
497 if ( tmpLyr.format().background().enabled() )
498 {
499 drawLabelPrivate( label, context, tmpLyr, Qgis::TextComponent::Background );
500 }
501
502 if ( tmpLyr.format().buffer().enabled() )
503 {
504 drawLabelPrivate( label, context, tmpLyr, Qgis::TextComponent::Buffer );
505 }
506
507 drawLabelPrivate( label, context, tmpLyr, Qgis::TextComponent::Text );
508
509 // add to the results
510 const QString labeltext = label->getFeaturePart()->feature()->labelText();
511 mEngine->results()->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, dFont, false, lf->hasFixedPosition(), mProviderId, false, 0, 0, label->getFeaturePart()->subPartId() );
512}
513
515{
516 QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
517 if ( !lf )
518 return;
519
520 QgsTextFormat format = mSettings.format();
521 if ( mSettings.drawLabels && mSettings.unplacedVisibility() != Qgis::UnplacedLabelVisibility::NeverShow && mEngine->engineSettings().flags() & Qgis::LabelingFlag::DrawUnplacedLabels )
522 {
524 format = tmpLyr.format();
525 format.setColor( mEngine->engineSettings().unplacedLabelColor() );
526 tmpLyr.setFormat( format );
527 drawLabelPrivate( label, context, tmpLyr, Qgis::TextComponent::Text );
528 }
529
530 // add to the results
531 const QString labeltext = label->getFeaturePart()->feature()->labelText();
532 mEngine->results()->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, format.font(), false, lf->hasFixedPosition(), mProviderId, true );
533}
534
536{
537 // NOTE: this is repeatedly called for multi-part labels
538 Qgis::TextComponents components;
539 switch ( drawType )
540 {
543 break;
544
547 break;
548
551 components = drawType;
552 break;
553 }
554
555 // features are pre-rotated but not scaled/translated,
556 // so we only disable rotation here. Ideally, they'd be
557 // also pre-scaled/translated, as suggested here:
558 // https://github.com/qgis/QGIS/issues/20071
559 QgsMapToPixel xform = context.mapToPixel();
560 xform.setMapRotation( 0, 0, 0 );
561
562 QPointF outPt = xform.transform( label->getX(), label->getY() ).toQPointF();
563
564 QgsTextRenderer::Component component;
565 component.dpiRatio = dpiRatio;
566 component.origin = outPt;
567 component.rotation = label->getAlpha();
568
569 if ( drawType == Qgis::TextComponent::Background )
570 {
571 // get rotated label's center point
572 QPointF centerPt( outPt );
573 QgsPointXY outPt2 = xform.transform( label->getX() + label->getWidth() / 2, label->getY() + label->getHeight() / 2 );
574
575 double xc = outPt2.x() - outPt.x();
576 double yc = outPt2.y() - outPt.y();
577
578 double angle = -component.rotation;
579 double xd = xc * std::cos( angle ) - yc * std::sin( angle );
580 double yd = xc * std::sin( angle ) + yc * std::cos( angle );
581
582 centerPt.setX( centerPt.x() + xd );
583 centerPt.setY( centerPt.y() + yd );
584
585 component.center = centerPt;
586
587 {
588 // label size has already been calculated using any symbology reference scale factor -- we need
589 // to temporarily remove the reference scale here or we'll be applying the scaling twice
590 QgsScopedRenderContextReferenceScaleOverride referenceScaleOverride( context, -1.0 );
591
592 // convert label size to render units
593 double labelWidthPx = context.convertToPainterUnits( label->getWidth(), Qgis::RenderUnit::MapUnits, QgsMapUnitScale() );
594 double labelHeightPx = context.convertToPainterUnits( label->getHeight(), Qgis::RenderUnit::MapUnits, QgsMapUnitScale() );
595
596 component.size = QSizeF( labelWidthPx, labelHeightPx );
597 }
598
599 QgsTextRenderer::drawBackground( context, component, tmpLyr.format(), QgsTextDocumentMetrics(), Qgis::TextLayoutMode::Labeling );
600 }
601
602 else if ( drawType == Qgis::TextComponent::Buffer || drawType == Qgis::TextComponent::Text )
603 {
604 // TODO: optimize access :)
605 QgsTextLabelFeature *lf = static_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
606 QString txt = lf->text( label->getPartId() );
607
608 if ( auto *lMaskIdProvider = context.maskIdProvider() )
609 {
610 int maskId = lMaskIdProvider->maskId( label->getFeaturePart()->layer()->provider()->layerId(), label->getFeaturePart()->layer()->provider()->providerId() );
611 context.setCurrentMaskId( maskId );
612 }
613
614 const QgsTextDocument &precalculatedDocument = lf->document();
615 const QgsTextDocumentMetrics &precalculatedMetrics = lf->documentMetrics();
616 const QgsTextDocument *document = &precalculatedDocument;
617 const QgsTextDocumentMetrics *documentMetrics = &precalculatedMetrics;
618
619 // add the direction symbol if needed
620 // note that IF we do this, we can no longer use the original text document and metrics
621 // but have to re-calculate these with the newly added text!
622 std::optional< QgsTextDocument > newDocument;
623 std::optional< QgsTextDocumentMetrics > newDocumentMetrics;
624 if ( !txt.isEmpty() && tmpLyr.placement == Qgis::LabelPlacement::Line && tmpLyr.lineSettings().addDirectionSymbol() )
625 {
626 newDocument.emplace( *document );
627 bool prependSymb = false;
628 QString symb = tmpLyr.lineSettings().rightDirectionSymbol();
629
630 if ( label->isReversedFromLineDirection() )
631 {
632 prependSymb = true;
633 symb = tmpLyr.lineSettings().leftDirectionSymbol();
634 }
635
636 if ( tmpLyr.lineSettings().reverseDirectionSymbol() )
637 {
638 if ( symb == tmpLyr.lineSettings().rightDirectionSymbol() )
639 {
640 prependSymb = true;
641 symb = tmpLyr.lineSettings().leftDirectionSymbol();
642 }
643 else
644 {
645 prependSymb = false;
646 symb = tmpLyr.lineSettings().rightDirectionSymbol();
647 }
648 }
649
650 switch ( tmpLyr.lineSettings().directionSymbolPlacement() )
651 {
653 {
654 newDocument->insert( 0, QgsTextBlock( QgsTextFragment( symb ) ) );
655 break;
656 }
657
659 newDocument->append( QgsTextBlock( QgsTextFragment( symb ) ) );
660 break;
661
663 {
664 QgsTextBlock &block = newDocument.value()[0];
665 if ( prependSymb )
666 {
667 block.insert( 0, QgsTextFragment( symb ) );
668 }
669 else
670 {
671 block.append( QgsTextFragment( symb ) );
672 }
673 break;
674 }
675 }
676
677 QgsScopedRenderContextReferenceScaleOverride referenceScaleOverride( context, -1.0 );
678 newDocumentMetrics.emplace( QgsTextDocumentMetrics::calculateMetrics( newDocument.value(), tmpLyr.format(), context ) );
679 document = &newDocument.value();
680 documentMetrics = &newDocumentMetrics.value();
681 }
682
690
691 QgsTextRenderer::Component component;
692 component.origin = outPt;
693 component.rotation = label->getAlpha();
694
695 // If we are using non-curved, HTML formatted labels then we've already precalculated the text metrics.
696 // Otherwise we'll need to calculate them now.
697 switch ( tmpLyr.placement )
698 {
701 {
702 QgsTextDocument document;
703 const QgsTextCharacterFormat c = lf->characterFormat( label->getPartId() );
704 const QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap );
705 for ( const QString &line : multiLineList )
706 {
707 document.append( QgsTextBlock::fromPlainText( line, c ) );
708 }
709
710 QgsScopedRenderContextReferenceScaleOverride referenceScaleOverride( context, -1.0 );
711 const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, tmpLyr.format(), context );
712 QgsTextRenderer::drawTextInternal( components, context, tmpLyr.format(), component, document, metrics, hAlign, Qgis::TextVerticalAlignment::Top, Qgis::TextLayoutMode::Labeling );
713 break;
714 }
715
723 {
724 const double verticalAlignOffset = -documentMetrics->blockVerticalMargin( document->size() - 1 );
725
726 component.origin.ry() += verticalAlignOffset;
727
728 QgsTextRenderer::drawTextInternal( components, context, tmpLyr.format(), component, *document, *documentMetrics, hAlign, Qgis::TextVerticalAlignment::Top, Qgis::TextLayoutMode::Labeling );
729 break;
730 }
731 }
732 }
733 if ( label->nextPart() )
734 drawLabelPrivate( label->nextPart(), context, tmpLyr, drawType, dpiRatio );
735}
736
741
743{
744 mFields = fields;
745}
@ LabelLargestPartOnly
Place a label only on the largest part from the geometry.
Definition qgis.h:1366
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
Definition qgis.h:1309
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
Definition qgis.h:1311
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
Definition qgis.h:1308
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
Definition qgis.h:1310
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
Definition qgis.h:1313
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
Definition qgis.h:1314
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature or along a line feature....
Definition qgis.h:1312
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
Definition qgis.h:1315
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only.
Definition qgis.h:1316
@ Labeling
Labeling-specific layout mode.
Definition qgis.h:3129
@ AboveRight
Above right.
Definition qgis.h:1398
@ BelowLeft
Below left.
Definition qgis.h:1402
@ Above
Above center.
Definition qgis.h:1397
@ BelowRight
Below right.
Definition qgis.h:1404
@ Right
Right middle.
Definition qgis.h:1401
@ AboveLeft
Above left.
Definition qgis.h:1396
@ Below
Below center.
Definition qgis.h:1403
@ Over
Center middle.
Definition qgis.h:1400
@ NeverShow
Never show unplaced labels, regardless of the engine setting.
Definition qgis.h:1258
@ DrawUnplacedLabels
Whether to render unplaced labels as an indicator/warning for users.
Definition qgis.h:3069
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:399
@ Point
Points.
Definition qgis.h:400
@ Center
Center align.
Definition qgis.h:1480
@ FollowPlacement
Alignment follows placement of label, e.g., labels to the left of a feature will be drawn with right ...
Definition qgis.h:1482
@ MapUnits
Map units.
Definition qgis.h:5760
@ Pixels
Pixels.
Definition qgis.h:5761
@ Top
Align to top.
Definition qgis.h:3187
@ Marker
Marker symbol.
Definition qgis.h:672
QFlags< TextComponent > TextComponents
Text components.
Definition qgis.h:3156
TextHorizontalAlignment
Text horizontal alignment.
Definition qgis.h:3167
@ Justify
Justify align.
Definition qgis.h:3171
@ Center
Center align.
Definition qgis.h:3169
TextComponent
Text components.
Definition qgis.h:3143
@ Shadow
Drop shadow.
Definition qgis.h:3147
@ Buffer
Buffer component.
Definition qgis.h:3145
@ Text
Text component.
Definition qgis.h:3144
@ Background
Background shape.
Definition qgis.h:3146
@ Reverse
Reverse/inverse transform (from destination to source).
Definition qgis.h:2884
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.
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.
QString mLayerId
Associated layer's ID, if applicable.
double mPriority
Default priority of labels. 0 = highest priority, 1 = lowest priority.
const QgsLabelingEngine * mEngine
Associated labeling engine.
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
Flags mFlags
Flags altering drawing and registration of features.
virtual void startRender(QgsRenderContext &context)
To be called before rendering of labels begins.
Qgis::LabelPlacement mPlacement
Placement strategy.
@ 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.
Qgis::UpsideDownLabelHandling mUpsidedownLabels
How to handle labels that would be upside down.
QString providerId() const
Returns provider ID - useful in case there is more than one label provider within a layer (e....
QgsAbstractLabelProvider(QgsMapLayer *layer, const QString &providerId=QString())
Construct the provider with default values.
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.
bool allFeaturePartsLabeled
true if all parts of associated feature were labeled
Definition qgscallout.h:251
QList< QgsCalloutPosition > positions() const
Returns the list of rendered callout positions.
Definition qgscallout.h:285
QgsCoordinateReferenceSystem originalFeatureCrs
Contains the CRS of the original feature associated with this callout.
Definition qgscallout.h:258
@ OrderBelowIndividualLabels
Render callouts below their individual associated labels, some callouts may be drawn over other label...
Definition qgscallout.h:109
@ OrderBelowAllLabels
Render callouts below all labels.
Definition qgscallout.h:108
bool enabled() const
Returns true if the callout is enabled.
Definition qgscallout.h:321
Represents a coordinate reference system (CRS).
Handles coordinate transforms between two coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const
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
Transforms a rectangle from the source CRS to the destination CRS.
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.
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)
Fetch next feature and stores in f, returns true on success.
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:60
QgsGeometry geometry
Definition qgsfeature.h:66
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Container of fields for a vector layer.
Definition qgsfields.h:45
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Qgis::GeometryType type
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Definition qgsgeos.cpp:1722
Encapsulates details for an individual feature to label.
void setIsSelected(bool selected)
Sets whether the feature associated with the label is currently selected.
void setSymbol(const QgsSymbol *symbol)
Sets the (optional) symbol associated with the feature to label.
QgsGeometry obstacleGeometry() const
Returns the (optional) obstacle geometry for the label.
bool isSelected() const
Returns true if the feature associated with the label is currently selected.
const QgsSymbol * symbol() const
Returns the (optional) symbol associated with the feature to label.
void setObstacleGeometry(const QgsGeometry &geometry)
Sets the (optional) obstacle geometry for the label.
Qgis::MultiPartLabelingBehavior multiPartBehavior() const
Returns the multipart labeling behavior.
QgsCoordinateReferenceSystem originalFeatureCrs() const
Returns the original layer CRS of the feature associated with the label.
GEOSGeometry * geometry() const
Gets access to the associated geometry.
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
QString labelText() const
Text of the label.
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...
@ PolygonWhole
Avoid placing labels over ANY part of polygon. Where PolygonInterior will prefer to place labels with...
Base class for all map layer types.
Definition qgsmaplayer.h:83
Contains configuration for rendering maps.
Perform transforms between map coordinates and device coordinates.
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.
void transformInPlace(double &x, double &y) const
Transforms map coordinates to device 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.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
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.
QString wrapChar
Wrapping character string.
Qgis::LabelPlacement placement
Label placement mode.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label's property collection, used for data defined overrides.
Qgis::LabelMultiLineAlignment multilineAlign
Horizontal alignment of multi-line labels.
QgsCallout * callout() const
Returns the label callout renderer, responsible for drawing label callouts.
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
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...
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
QPointF toQPointF() const
Converts a point to a QPointF.
Definition qgspointxy.h:168
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
double x
Definition qgspoint.h:56
double y
Definition qgspoint.h:57
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
const QgsMaskIdProvider * maskIdProvider() const
Returns the mask id provider attached to the context.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
void setCurrentMaskId(int id)
Stores a mask id as the "current" one.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Scoped object for temporary override of the symbologyReferenceScale property of a QgsRenderContext.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:227
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.
void insert(int index, const QgsTextFragment &fragment)
Inserts a fragment into the block, at the specified index.
static QgsTextBlock fromPlainText(const QString &text, const QgsTextCharacterFormat &format=QgsTextCharacterFormat())
Constructor for QgsTextBlock consisting of a plain text, and optional character format.
void append(const QgsTextFragment &fragment)
Appends a fragment to the block.
bool enabled() const
Returns whether the buffer is enabled.
Stores information relating to individual character formatting.
Contains pre-calculated metrics of a QgsTextDocument.
static QgsTextDocumentMetrics calculateMetrics(const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor=1.0, const QgsTextDocumentRenderContext &documentContext=QgsTextDocumentRenderContext())
Returns precalculated text metrics for a text document, when rendered using the given base format and...
double blockVerticalMargin(int blockIndex) const
Returns the vertical margin for the specified block index.
Represents a document consisting of one or more QgsTextBlock objects.
int size() const
Returns the number of blocks in the document.
void append(const QgsTextBlock &block)
Appends a block to the document.
Container for all settings relating to text rendering.
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.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the size of rendered text.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
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 document along with formatting overrides to be used when rendering the fragment.
Adds extra information to QgsLabelFeature for text labels.
QFont definedFont() const
Font to be used for rendering.
const QgsTextDocumentMetrics & documentMetrics() const
Returns the document metrics for the label.
const QgsTextDocument & document() const
Returns the document for the label.
QgsTextCharacterFormat characterFormat(int partId) const
Returns the character format corresponding to the specified label part.
const QMap< QgsPalLayerSettings::Property, QVariant > & dataDefinedValues() const
Gets data-defined values.
QString text(int partId) const
Returns the text component corresponding to a specified label part.
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.
virtual QList< QgsLabelFeature * > registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsLabelFeatureDetails &details=QgsLabelFeatureDetails())
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels.
void stopRender(QgsRenderContext &context) override
To be called after rendering is complete.
QgsCoordinateReferenceSystem mCrs
Layer's CRS.
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.
void drawLabelPrivate(pal::LabelPosition *label, QgsRenderContext &context, QgsPalLayerSettings &tmpLyr, Qgis::TextComponent drawType, double dpiRatio=1.0) const
Internal label drawing method.
Qgis::GeometryType mLayerGeometryType
Geometry type of layer.
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.
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).
void init()
initialization method - called from constructors
void setFields(const QgsFields &fields)
Sets fields of this label provider.
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 dataset.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
Definition feature.cpp:168
int subPartId() const
Returns the unique sub part ID for the feature, for features which register multiple labels.
Definition feature.cpp:173
QgsLabelFeature * feature()
Returns the parent feature.
Definition feature.h:87
Layer * layer()
Returns the layer that feature belongs to.
Definition feature.cpp:163
LabelPosition is a candidate feature label position.
double getAlpha() const
Returns the angle to rotate text (in radians).
double getHeight() const
double getWidth() const
bool isReversedFromLineDirection() const
Returns true if the label direction is the reversed from the line or polygon ring direction.
Qgis::LabelQuadrantPosition quadrant() const
Returns the quadrant associated with this label position.
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.
LabelPosition * nextPart() const
Returns the next part of this label position (i.e.
QgsAbstractLabelProvider * provider() const
Returns pointer to the associated provider.
Definition layer.h:156
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:80
QList< QgsSymbol * > QgsSymbolList
Definition qgsrenderer.h:51
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:35