QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
qgslabelingenginerule_impl.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslabelingenginerule_impl.cpp
3 ---------------------
4 Date : August 2024
5 Copyright : (C) 2024 by Nyall Dawson
6 Email : nyall dot dawson 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 "feature.h"
19#include "labelposition.h"
20#include "qgsgeos.h"
21#include "qgsspatialindex.h"
22#include "qgssymbollayerutils.h"
23#include "qgsthreadingutils.h"
24#include "qgsunittypes.h"
26
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
31#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 10
32#include "qgsmessagelog.h"
33#endif
34
35//
36// QgsAbstractLabelingEngineRuleDistanceFromFeature
37//
38
41
43{
44 if ( !mTargetLayer )
45 return false;
46
48 mTargetLayerSource = std::make_unique< QgsVectorLayerFeatureSource >( mTargetLayer.get() );
49
50 mDistanceMapUnits = context.convertToMapUnits( mDistance, mDistanceUnit, mDistanceUnitScale );
51 return true;
52}
53
54void QgsAbstractLabelingEngineRuleDistanceFromFeature::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
55{
56 element.setAttribute( u"distance"_s, mDistance );
57 element.setAttribute( u"distanceUnit"_s, QgsUnitTypes::encodeUnit( mDistanceUnit ) );
58 element.setAttribute( u"distanceUnitScale"_s, QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceUnitScale ) );
59 element.setAttribute( u"cost"_s, mCost );
60
61 if ( mLabeledLayer )
62 {
63 element.setAttribute( u"labeledLayer"_s, mLabeledLayer.layerId );
64 element.setAttribute( u"labeledLayerName"_s, mLabeledLayer.name );
65 element.setAttribute( u"labeledLayerSource"_s, mLabeledLayer.source );
66 element.setAttribute( u"labeledLayerProvider"_s, mLabeledLayer.provider );
67 }
68 if ( mTargetLayer )
69 {
70 element.setAttribute( u"targetLayer"_s, mTargetLayer.layerId );
71 element.setAttribute( u"targetLayerName"_s, mTargetLayer.name );
72 element.setAttribute( u"targetLayerSource"_s, mTargetLayer.source );
73 element.setAttribute( u"targetLayerProvider"_s, mTargetLayer.provider );
74 }
75}
76
78{
79 mDistance = element.attribute( u"distance"_s, u"5"_s ).toDouble();
80 mDistanceUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( u"distanceUnit"_s ) );
81 mDistanceUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( element.attribute( u"distanceUnitScale"_s ) );
82 mCost = element.attribute( u"cost"_s, u"10"_s ).toDouble();
83
84 {
85 const QString layerId = element.attribute( u"labeledLayer"_s );
86 const QString layerName = element.attribute( u"labeledLayerName"_s );
87 const QString layerSource = element.attribute( u"labeledLayerSource"_s );
88 const QString layerProvider = element.attribute( u"labeledLayerProvider"_s );
89 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
90 }
91 {
92 const QString layerId = element.attribute( u"targetLayer"_s );
93 const QString layerName = element.attribute( u"targetLayerName"_s );
94 const QString layerSource = element.attribute( u"targetLayerSource"_s );
95 const QString layerProvider = element.attribute( u"targetLayerProvider"_s );
96 mTargetLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
97 }
98}
99
101{
102 mLabeledLayer.resolve( project );
103 mTargetLayer.resolve( project );
104}
105
107{
108 // hard blocks on candidates only apply when cost == 10
109 if ( mCost < 10 )
110 return false;
111
112 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
113 {
114 return false;
115 }
116
117 if ( !mTargetLayerSource )
118 return false;
119
120 return candidateExceedsTolerance( candidate, context );
121}
122
124{
125 // cost of 10 = hard block, handled in candidateIsIllegal
126 if ( mCost >= 10 )
127 return;
128
129 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
130 {
131 return;
132 }
133
134 if ( !mTargetLayerSource )
135 return;
136
137 if ( candidateExceedsTolerance( candidate, context ) )
138 {
139 // magic number alert! / 1000 here is completely arbitrary, an attempt to balance against the cost scaling of other factors
140 // assigned by the inscrutible logic of the pal engine internals
141 candidate->setCost( candidate->cost() + mCost / 1000 );
142 }
143}
144
146{
147#if GEOS_VERSION_MAJOR > 3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 10 )
148 return true;
149#else
150 return false;
151#endif
152}
153
155{
156 return mLabeledLayer.get();
157}
158
160{
161 mLabeledLayer = layer;
162}
163
168
173
175{
178 {
179 otherRule->mLabeledLayer = mLabeledLayer;
180 otherRule->mTargetLayer = mTargetLayer;
181 otherRule->mDistance = mDistance;
182 otherRule->mDistanceUnit = mDistanceUnit;
183 otherRule->mDistanceUnitScale = mDistanceUnitScale;
184 otherRule->mCost = mCost;
185 }
186}
187
188void QgsAbstractLabelingEngineRuleDistanceFromFeature::initialize( QgsLabelingEngineContext &context )
189{
192 req.setFilterRect( context.extent() );
193 req.setNoAttributes();
194
195 QgsFeatureIterator it = mTargetLayerSource->getFeatures( req );
196
197 mIndex = std::make_unique< QgsSpatialIndex >( it, context.renderContext().feedback(), QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
198
199 mInitialized = true;
200}
201
202bool QgsAbstractLabelingEngineRuleDistanceFromFeature::candidateExceedsTolerance( const pal::LabelPosition *candidate, QgsLabelingEngineContext &context ) const
203{
204 if ( !mInitialized )
205 const_cast< QgsAbstractLabelingEngineRuleDistanceFromFeature * >( this )->initialize( context );
206
207 const QgsRectangle candidateBounds = candidate->outerBoundingBox();
208 const QgsRectangle expandedBounds = candidateBounds.buffered( mDistanceMapUnits );
209
210 const QList<QgsFeatureId> overlapCandidates = mIndex->intersects( expandedBounds );
211 if ( overlapCandidates.empty() )
212 return !mMustBeDistant;
213
214 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
215
216 const GEOSPreparedGeometry *candidateGeos = candidate->preparedMultiPartGeom();
217 for ( const QgsFeatureId overlapCandidateId : overlapCandidates )
218 {
219 if ( context.renderContext().feedback() && context.renderContext().feedback()->isCanceled() )
220 break;
221
222 try
223 {
224 geos::unique_ptr featureCandidate = QgsGeos::asGeos( mIndex->geometry( overlapCandidateId ).constGet() );
225#if GEOS_VERSION_MAJOR > 3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 10 )
226 if ( GEOSPreparedDistanceWithin_r( geosctxt, candidateGeos, featureCandidate.get(), mDistanceMapUnits ) )
227 {
228 return mMustBeDistant;
229 }
230#else
231 QgsMessageLog::logMessage( u"The %1 labeling rule requires GEOS 3.10+"_s.arg( name().isEmpty() ? displayType() : name() ) );
232 return false;
233#endif
234 }
235 catch ( QgsGeosException &e )
236 {
237 QgsDebugError( u"GEOS exception: %1"_s.arg( e.what() ) );
238 }
239 }
240
241 return !mMustBeDistant;
242}
243
244//
245// QgsLabelingEngineRuleMinimumDistanceLabelToFeature
246//
247
250
252{
253 auto res = std::make_unique< QgsLabelingEngineRuleMinimumDistanceLabelToFeature >();
254 copyCommonProperties( res.get() );
255 return res.release();
256}
257
259{
260 return u"minimumDistanceLabelToFeature"_s;
261}
262
264{
265 return QObject::tr( "Push Labels Away from Features" );
266}
267
269{
270 QString res = u"<b>%1</b>"_s.arg( name().isEmpty() ? displayType() : name() );
271 if ( labeledLayer() && targetLayer() )
272 {
273 res += u"<p>"_s
274 + QObject::tr( "Labels from <i>%1</i> must be at least %2 %3 from features in <i>%4</i>" )
275 .arg( labeledLayer()->name(), QString::number( distance() ), QgsUnitTypes::toAbbreviatedString( distanceUnit() ), targetLayer()->name() )
276 + u"</p>"_s;
277 }
278 return res;
279}
280
281
282//
283// QgsLabelingEngineRuleMaximumDistanceLabelToFeature
284//
285
290
292
294{
295 auto res = std::make_unique< QgsLabelingEngineRuleMaximumDistanceLabelToFeature >();
296 copyCommonProperties( res.get() );
297 return res.release();
298}
299
301{
302 return u"maximumDistanceLabelToFeature"_s;
303}
304
306{
307 return QObject::tr( "Pull Labels Toward Features" );
308}
309
311{
312 QString res = u"<b>%1</b>"_s.arg( name().isEmpty() ? displayType() : name() );
313 if ( labeledLayer() && targetLayer() )
314 {
315 res += u"<p>"_s
316 + QObject::tr( "Labels from <i>%1</i> must be at most %2 %3 from features in <i>%4</i>" )
317 .arg( labeledLayer()->name(), QString::number( distance() ), QgsUnitTypes::toAbbreviatedString( distanceUnit() ), targetLayer()->name() )
318 + u"</p>"_s;
319 }
320 return res;
321}
322
323
324//
325// QgsLabelingEngineRuleMinimumDistanceLabelToLabel
326//
327
330
332{
333 auto res = std::make_unique< QgsLabelingEngineRuleMinimumDistanceLabelToLabel >();
334 copyCommonProperties( res.get() );
335 res->mLabeledLayer = mLabeledLayer;
336 res->mTargetLayer = mTargetLayer;
337 res->mDistance = mDistance;
338 res->mDistanceUnit = mDistanceUnit;
339 res->mDistanceUnitScale = mDistanceUnitScale;
340 return res.release();
341}
342
344{
345 return u"minimumDistanceLabelToLabel"_s;
346}
347
349{
350 return QObject::tr( "Push Labels Away from Other Labels" );
351}
352
354{
355 QString res = u"<b>%1</b>"_s.arg( name().isEmpty() ? displayType() : name() );
356 if ( labeledLayer() && targetLayer() )
357 {
358 res += u"<p>"_s
359 + QObject::tr( "Labels from <i>%1</i> must be at least %2 %3 from labels from <i>%4</i>" )
360 .arg( labeledLayer()->name(), QString::number( distance() ), QgsUnitTypes::toAbbreviatedString( distanceUnit() ), targetLayer()->name() )
361 + u"</p>"_s;
362 }
363 return res;
364}
365
367{
368#if GEOS_VERSION_MAJOR > 3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 10 )
369 return true;
370#else
371 return false;
372#endif
373}
374
375void QgsLabelingEngineRuleMinimumDistanceLabelToLabel::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
376{
377 element.setAttribute( u"distance"_s, mDistance );
378 element.setAttribute( u"distanceUnit"_s, QgsUnitTypes::encodeUnit( mDistanceUnit ) );
379 element.setAttribute( u"distanceUnitScale"_s, QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceUnitScale ) );
380
381 if ( mLabeledLayer )
382 {
383 element.setAttribute( u"labeledLayer"_s, mLabeledLayer.layerId );
384 element.setAttribute( u"labeledLayerName"_s, mLabeledLayer.name );
385 element.setAttribute( u"labeledLayerSource"_s, mLabeledLayer.source );
386 element.setAttribute( u"labeledLayerProvider"_s, mLabeledLayer.provider );
387 }
388 if ( mTargetLayer )
389 {
390 element.setAttribute( u"targetLayer"_s, mTargetLayer.layerId );
391 element.setAttribute( u"targetLayerName"_s, mTargetLayer.name );
392 element.setAttribute( u"targetLayerSource"_s, mTargetLayer.source );
393 element.setAttribute( u"targetLayerProvider"_s, mTargetLayer.provider );
394 }
395}
396
398{
399 mDistance = element.attribute( u"distance"_s, u"5"_s ).toDouble();
400 mDistanceUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( u"distanceUnit"_s ) );
401 mDistanceUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( element.attribute( u"distanceUnitScale"_s ) );
402
403 {
404 const QString layerId = element.attribute( u"labeledLayer"_s );
405 const QString layerName = element.attribute( u"labeledLayerName"_s );
406 const QString layerSource = element.attribute( u"labeledLayerSource"_s );
407 const QString layerProvider = element.attribute( u"labeledLayerProvider"_s );
408 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
409 }
410 {
411 const QString layerId = element.attribute( u"targetLayer"_s );
412 const QString layerName = element.attribute( u"targetLayerName"_s );
413 const QString layerSource = element.attribute( u"targetLayerSource"_s );
414 const QString layerProvider = element.attribute( u"targetLayerProvider"_s );
415 mTargetLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
416 }
417}
418
420{
421 mLabeledLayer.resolve( project );
422 mTargetLayer.resolve( project );
423}
424
426{
427 mDistanceMapUnits = context.convertToMapUnits( mDistance, mDistanceUnit, mDistanceUnitScale );
428 return true;
429}
430
432{
433 return candidateBounds.buffered( mDistanceMapUnits );
434}
435
437{
438 // conflicts are commutative -- we need to check both layers
439 if ( ( lp1->getFeaturePart()->feature()->provider()->layerId() == mLabeledLayer.layerId && lp2->getFeaturePart()->feature()->provider()->layerId() == mTargetLayer.layerId )
440 || ( lp2->getFeaturePart()->feature()->provider()->layerId() == mLabeledLayer.layerId && lp1->getFeaturePart()->feature()->provider()->layerId() == mTargetLayer.layerId ) )
441 {
442 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
443 try
444 {
445#if GEOS_VERSION_MAJOR > 3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 10 )
446 if ( GEOSPreparedDistanceWithin_r( geosctxt, lp1->preparedMultiPartGeom(), lp2->multiPartGeom(), mDistanceMapUnits ) )
447 {
448 return true;
449 }
450#else
451 QgsMessageLog::logMessage( u"The %1 labeling rule requires GEOS 3.10+"_s.arg( name().isEmpty() ? displayType() : name() ) );
452 return false;
453#endif
454 }
455 catch ( QgsGeosException &e )
456 {
457 QgsDebugError( u"GEOS exception: %1"_s.arg( e.what() ) );
458 }
459 }
460
461 return false;
462}
463
465{
466 return mLabeledLayer.get();
467}
468
470{
471 mLabeledLayer = layer;
472}
473
475{
476 return mTargetLayer.get();
477}
478
480{
481 mTargetLayer = layer;
482}
483
484
485//
486// QgsLabelingEngineRuleAvoidLabelOverlapWithFeature
487//
488
491
493{
494 auto res = std::make_unique< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature >();
495 copyCommonProperties( res.get() );
496 res->mLabeledLayer = mLabeledLayer;
497 res->mTargetLayer = mTargetLayer;
498 return res.release();
499}
500
502{
503 return u"avoidLabelOverlapWithFeature"_s;
504}
505
507{
508 return QObject::tr( "Prevent Labels Overlapping Features" );
509}
510
512{
513 QString res = u"<b>%1</b>"_s.arg( name().isEmpty() ? displayType() : name() );
514 if ( labeledLayer() && targetLayer() )
515 {
516 res += u"<p>"_s + QObject::tr( "Labels from <i>%1</i> must not overlap features from <i>%2</i>" ).arg( labeledLayer()->name(), targetLayer()->name() ) + u"</p>"_s;
517 }
518 return res;
519}
520
522{
523 if ( !mTargetLayer )
524 return false;
525
527 mTargetLayerSource = std::make_unique< QgsVectorLayerFeatureSource >( mTargetLayer.get() );
528 return true;
529}
530
531void QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
532{
533 if ( mLabeledLayer )
534 {
535 element.setAttribute( u"labeledLayer"_s, mLabeledLayer.layerId );
536 element.setAttribute( u"labeledLayerName"_s, mLabeledLayer.name );
537 element.setAttribute( u"labeledLayerSource"_s, mLabeledLayer.source );
538 element.setAttribute( u"labeledLayerProvider"_s, mLabeledLayer.provider );
539 }
540 if ( mTargetLayer )
541 {
542 element.setAttribute( u"targetLayer"_s, mTargetLayer.layerId );
543 element.setAttribute( u"targetLayerName"_s, mTargetLayer.name );
544 element.setAttribute( u"targetLayerSource"_s, mTargetLayer.source );
545 element.setAttribute( u"targetLayerProvider"_s, mTargetLayer.provider );
546 }
547}
548
550{
551 {
552 const QString layerId = element.attribute( u"labeledLayer"_s );
553 const QString layerName = element.attribute( u"labeledLayerName"_s );
554 const QString layerSource = element.attribute( u"labeledLayerSource"_s );
555 const QString layerProvider = element.attribute( u"labeledLayerProvider"_s );
556 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
557 }
558 {
559 const QString layerId = element.attribute( u"targetLayer"_s );
560 const QString layerName = element.attribute( u"targetLayerName"_s );
561 const QString layerSource = element.attribute( u"targetLayerSource"_s );
562 const QString layerProvider = element.attribute( u"targetLayerProvider"_s );
563 mTargetLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
564 }
565}
566
568{
569 mLabeledLayer.resolve( project );
570 mTargetLayer.resolve( project );
571}
572
574{
575 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
576 {
577 return false;
578 }
579
580 if ( !mTargetLayerSource )
581 return false;
582
583 if ( !mInitialized )
584 const_cast< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature * >( this )->initialize( context );
585
586 const QList<QgsFeatureId> overlapCandidates = mIndex->intersects( candidate->outerBoundingBox() );
587 if ( overlapCandidates.empty() )
588 return false;
589
590 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
591
592 const GEOSPreparedGeometry *candidateGeos = candidate->preparedMultiPartGeom();
593 for ( const QgsFeatureId overlapCandidateId : overlapCandidates )
594 {
595 if ( context.renderContext().feedback() && context.renderContext().feedback()->isCanceled() )
596 break;
597
598 try
599 {
600 geos::unique_ptr featureCandidate = QgsGeos::asGeos( mIndex->geometry( overlapCandidateId ).constGet() );
601 if ( GEOSPreparedIntersects_r( geosctxt, candidateGeos, featureCandidate.get() ) == 1 )
602 return true;
603 }
604 catch ( QgsGeosException &e )
605 {
606 QgsDebugError( u"GEOS exception: %1"_s.arg( e.what() ) );
607 }
608 }
609
610 return false;
611}
612
614{
615 return mLabeledLayer.get();
616}
617
619{
620 mLabeledLayer = layer;
621}
622
627
632
633void QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::initialize( QgsLabelingEngineContext &context )
634{
637 req.setFilterRect( context.extent() );
638 req.setNoAttributes();
639
640 QgsFeatureIterator it = mTargetLayerSource->getFeatures( req );
641
642 mIndex = std::make_unique< QgsSpatialIndex >( it, context.renderContext().feedback(), QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
643
644 mInitialized = true;
645}
QString layerId() const
Returns ID of associated layer, or empty string if no layer is associated with the provider.
bool candidateIsIllegal(const pal::LabelPosition *candidate, QgsLabelingEngineContext &context) const override
Returns true if a labeling candidate violates the rule and should be eliminated.
bool prepare(QgsRenderContext &context) override
Prepares the rule.
void setTargetLayer(QgsVectorLayer *layer)
Sets the layer providing the features which labels must be distant from (or close to).
Qgis::RenderUnit distanceUnit() const
Returns the units for the distance between labels and the features from the targetLayer().
double distance() const
Returns the acceptable distance threshold between labels and the features from the targetLayer().
void alterCandidateCost(pal::LabelPosition *candidate, QgsLabelingEngineContext &context) const override
Provides an opportunity for the rule to alter the cost for a candidate.
bool isAvailable() const override
Returns true if the rule is available for use within the current QGIS environment.
void writeXml(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context) const override
Writes the rule properties to an XML element.
void resolveReferences(const QgsProject *project) override
Resolves reference to layers from stored layer ID.
QgsVectorLayer * targetLayer() const
Returns the layer providing the features which labels must be distant from (or close to).
void setLabeledLayer(QgsMapLayer *layer)
Sets the layer providing the labels.
void copyCommonProperties(QgsAbstractLabelingEngineRule *other) const override
Copies common properties from this object to an other.
void readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the rule properties from an XML element.
QgsMapLayer * labeledLayer() const
Returns the layer providing the labels.
bool mMustBeDistant
true if labels must be distant from features, false if they must be close
Abstract base class for labeling engine rules.
QString name() const
Returns the name for this instance of the rule.
virtual QString displayType() const =0
Returns a user-friendly, translated string representing the rule type.
virtual void copyCommonProperties(QgsAbstractLabelingEngineRule *other) const
Copies common properties from this object to an other.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system, which the transform will transform coordinates t...
Wrapper for iterator of features from vector data provider or vector layer.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
static GEOSContextHandle_t get()
Returns a thread local instance of a GEOS context, safe for use in the current thread.
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlags())
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
Definition qgsgeos.cpp:254
QgsAbstractLabelProvider * provider() const
Returns provider of this instance.
Encapsulates the context for a labeling engine run.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
QgsRectangle extent() const
Returns the map extent defining the limits for labeling.
void readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the rule properties from an XML element.
void writeXml(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context) const override
Writes the rule properties to an XML element.
QString displayType() const override
Returns a user-friendly, translated string representing the rule type.
bool prepare(QgsRenderContext &context) override
Prepares the rule.
QString id() const override
Returns a string uniquely identifying the rule subclass.
void setTargetLayer(QgsVectorLayer *layer)
Sets the layer providing the features which labels must not overlap.
QgsLabelingEngineRuleAvoidLabelOverlapWithFeature * clone() const override
Creates a clone of this rule.
QString description() const override
Returns a user-friendly description of the rule.
void setLabeledLayer(QgsMapLayer *layer)
Sets the layer providing the labels.
QgsMapLayer * labeledLayer() const
Returns the layer providing the labels.
void resolveReferences(const QgsProject *project) override
Resolves reference to layers from stored layer ID.
bool candidateIsIllegal(const pal::LabelPosition *candidate, QgsLabelingEngineContext &context) const override
Returns true if a labeling candidate violates the rule and should be eliminated.
QgsVectorLayer * targetLayer() const
Returns the layer providing the features which labels must not overlap.
QString id() const override
Returns a string uniquely identifying the rule subclass.
QString description() const override
Returns a user-friendly description of the rule.
QString displayType() const override
Returns a user-friendly, translated string representing the rule type.
QgsLabelingEngineRuleMaximumDistanceLabelToFeature * clone() const override
Creates a clone of this rule.
QString description() const override
Returns a user-friendly description of the rule.
QgsLabelingEngineRuleMinimumDistanceLabelToFeature * clone() const override
Creates a clone of this rule.
QString id() const override
Returns a string uniquely identifying the rule subclass.
QString displayType() const override
Returns a user-friendly, translated string representing the rule type.
double distance() const
Returns the minimum permitted distance between labels from the labeledLayer() and the labels from the...
QgsMapLayer * labeledLayer() const
Returns the layer providing the labels.
QgsRectangle modifyCandidateConflictSearchBoundingBox(const QgsRectangle &candidateBounds) const override
Returns a (possibly expanded) bounding box to use when searching for conflicts for a candidate.
QString id() const override
Returns a string uniquely identifying the rule subclass.
void setLabeledLayer(QgsMapLayer *layer)
Sets the layer providing the labels.
void writeXml(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context) const override
Writes the rule properties to an XML element.
void resolveReferences(const QgsProject *project) override
Resolves reference to layers from stored layer ID.
QgsMapLayer * targetLayer() const
Returns the layer providing the labels which labels must be distant from.
void readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the rule properties from an XML element.
QgsLabelingEngineRuleMinimumDistanceLabelToLabel * clone() const override
Creates a clone of this rule.
QString displayType() const override
Returns a user-friendly, translated string representing the rule type.
QString description() const override
Returns a user-friendly description of the rule.
void setTargetLayer(QgsMapLayer *layer)
Sets the layer providing the labels which labels must be distant from.
Qgis::RenderUnit distanceUnit() const
Returns the units for the distance between labels from the labeledLayer() and the labels from the tar...
bool prepare(QgsRenderContext &context) override
Prepares the rule.
bool isAvailable() const override
Returns true if the rule is available for use within the current QGIS environment.
bool candidatesAreConflicting(const pal::LabelPosition *lp1, const pal::LabelPosition *lp2) const override
Returns true if a labeling candidate lp1 conflicts with lp2 after applying the rule.
Base class for all map layer types.
Definition qgsmaplayer.h:83
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:113
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
QgsRectangle buffered(double width) const
Gets rectangle enlarged by buffer.
Contains information about the context of a rendering operation.
double convertToMapUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
QgsCoordinateTransformContext transformContext() const
Returns the context's coordinate transform context, which stores various information regarding which ...
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static Q_INVOKABLE QString toAbbreviatedString(Qgis::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
Represents a vector layer which manages a vector based dataset.
QgsLabelFeature * feature()
Returns the parent feature.
Definition feature.h:87
LabelPosition is a candidate feature label position.
QgsRectangle outerBoundingBox() const
Returns bounding box.
void setCost(double newCost)
Sets the candidate label position's geographical cost.
const GEOSGeometry * multiPartGeom() const
Returns a GEOS representation of all label parts as a multipolygon.
double cost() const
Returns the candidate label position's geographical cost.
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
const GEOSPreparedGeometry * preparedMultiPartGeom() const
Returns a prepared GEOS representation of all label parts as a multipolygon.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
Definition qgsgeos.h:112
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugError(str)
Definition qgslogger.h:59
_LayerRef< QgsMapLayer > QgsMapLayerRef
#define QGIS_CHECK_OTHER_QOBJECT_THREAD_ACCESS(other)
_LayerRef< QgsVectorLayer > QgsVectorLayerRef