QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
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#include "qgsunittypes.h"
18#include "qgssymbollayerutils.h"
20#include "qgsthreadingutils.h"
21#include "qgsspatialindex.h"
22#include "qgsgeos.h"
23#include "labelposition.h"
24#include "feature.h"
25#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 10
26#include "qgsmessagelog.h"
27#endif
28
29//
30// QgsAbstractLabelingEngineRuleDistanceFromFeature
31//
32
35
37{
38 if ( !mTargetLayer )
39 return false;
40
42 mTargetLayerSource = std::make_unique< QgsVectorLayerFeatureSource >( mTargetLayer.get() );
43
44 mDistanceMapUnits = context.convertToMapUnits( mDistance, mDistanceUnit, mDistanceUnitScale );
45 return true;
46}
47
48void QgsAbstractLabelingEngineRuleDistanceFromFeature::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
49{
50 element.setAttribute( QStringLiteral( "distance" ), mDistance );
51 element.setAttribute( QStringLiteral( "distanceUnit" ), QgsUnitTypes::encodeUnit( mDistanceUnit ) );
52 element.setAttribute( QStringLiteral( "distanceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceUnitScale ) );
53 element.setAttribute( QStringLiteral( "cost" ), mCost );
54
55 if ( mLabeledLayer )
56 {
57 element.setAttribute( QStringLiteral( "labeledLayer" ), mLabeledLayer.layerId );
58 element.setAttribute( QStringLiteral( "labeledLayerName" ), mLabeledLayer.name );
59 element.setAttribute( QStringLiteral( "labeledLayerSource" ), mLabeledLayer.source );
60 element.setAttribute( QStringLiteral( "labeledLayerProvider" ), mLabeledLayer.provider );
61 }
62 if ( mTargetLayer )
63 {
64 element.setAttribute( QStringLiteral( "targetLayer" ), mTargetLayer.layerId );
65 element.setAttribute( QStringLiteral( "targetLayerName" ), mTargetLayer.name );
66 element.setAttribute( QStringLiteral( "targetLayerSource" ), mTargetLayer.source );
67 element.setAttribute( QStringLiteral( "targetLayerProvider" ), mTargetLayer.provider );
68 }
69}
70
72{
73 mDistance = element.attribute( QStringLiteral( "distance" ), QStringLiteral( "5" ) ).toDouble();
74 mDistanceUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "distanceUnit" ) ) );
75 mDistanceUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( element.attribute( QStringLiteral( "distanceUnitScale" ) ) );
76 mCost = element.attribute( QStringLiteral( "cost" ), QStringLiteral( "10" ) ).toDouble();
77
78 {
79 const QString layerId = element.attribute( QStringLiteral( "labeledLayer" ) );
80 const QString layerName = element.attribute( QStringLiteral( "labeledLayerName" ) );
81 const QString layerSource = element.attribute( QStringLiteral( "labeledLayerSource" ) );
82 const QString layerProvider = element.attribute( QStringLiteral( "labeledLayerProvider" ) );
83 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
84 }
85 {
86 const QString layerId = element.attribute( QStringLiteral( "targetLayer" ) );
87 const QString layerName = element.attribute( QStringLiteral( "targetLayerName" ) );
88 const QString layerSource = element.attribute( QStringLiteral( "targetLayerSource" ) );
89 const QString layerProvider = element.attribute( QStringLiteral( "targetLayerProvider" ) );
90 mTargetLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
91 }
92}
93
95{
96 mLabeledLayer.resolve( project );
97 mTargetLayer.resolve( project );
98}
99
101{
102 // hard blocks on candidates only apply when cost == 10
103 if ( mCost < 10 )
104 return false;
105
106 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
107 {
108 return false;
109 }
110
111 if ( !mTargetLayerSource )
112 return false;
113
114 return candidateExceedsTolerance( candidate, context );
115}
116
118{
119 // cost of 10 = hard block, handled in candidateIsIllegal
120 if ( mCost >= 10 )
121 return;
122
123 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
124 {
125 return;
126 }
127
128 if ( !mTargetLayerSource )
129 return;
130
131 if ( candidateExceedsTolerance( candidate, context ) )
132 {
133 // magic number alert! / 1000 here is completely arbitrary, an attempt to balance against the cost scaling of other factors
134 // assigned by the inscrutible logic of the pal engine internals
135 candidate->setCost( candidate->cost() + mCost / 1000 );
136 }
137}
138
140{
141#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
142 return true;
143#else
144 return false;
145#endif
146}
147
152
154{
155 mLabeledLayer = layer;
156}
157
162
167
169{
172 {
173 otherRule->mLabeledLayer = mLabeledLayer;
174 otherRule->mTargetLayer = mTargetLayer;
175 otherRule->mDistance = mDistance;
176 otherRule->mDistanceUnit = mDistanceUnit;
177 otherRule->mDistanceUnitScale = mDistanceUnitScale;
178 otherRule->mCost = mCost;
179 }
180}
181
182void QgsAbstractLabelingEngineRuleDistanceFromFeature::initialize( QgsLabelingEngineContext &context )
183{
186 req.setFilterRect( context.extent() );
187 req.setNoAttributes();
188
189 QgsFeatureIterator it = mTargetLayerSource->getFeatures( req );
190
191 mIndex = std::make_unique< QgsSpatialIndex >( it, context.renderContext().feedback(), QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
192
193 mInitialized = true;
194}
195
196bool QgsAbstractLabelingEngineRuleDistanceFromFeature::candidateExceedsTolerance( const pal::LabelPosition *candidate, QgsLabelingEngineContext &context ) const
197{
198 if ( !mInitialized )
199 const_cast< QgsAbstractLabelingEngineRuleDistanceFromFeature * >( this )->initialize( context );
200
201 const QgsRectangle candidateBounds = candidate->outerBoundingBox();
202 const QgsRectangle expandedBounds = candidateBounds.buffered( mDistanceMapUnits );
203
204 const QList<QgsFeatureId> overlapCandidates = mIndex->intersects( expandedBounds );
205 if ( overlapCandidates.empty() )
206 return !mMustBeDistant;
207
208 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
209
210 const GEOSPreparedGeometry *candidateGeos = candidate->preparedMultiPartGeom();
211 for ( const QgsFeatureId overlapCandidateId : overlapCandidates )
212 {
213 if ( context.renderContext().feedback() && context.renderContext().feedback()->isCanceled() )
214 break;
215
216 try
217 {
218 geos::unique_ptr featureCandidate = QgsGeos::asGeos( mIndex->geometry( overlapCandidateId ).constGet() );
219#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
220 if ( GEOSPreparedDistanceWithin_r( geosctxt, candidateGeos, featureCandidate.get(), mDistanceMapUnits ) )
221 {
222 return mMustBeDistant;
223 }
224#else
225 QgsMessageLog::logMessage( QStringLiteral( "The %1 labeling rule requires GEOS 3.10+" ).arg( name().isEmpty() ? displayType() : name() ) );
226 return false;
227#endif
228 }
229 catch ( GEOSException &e )
230 {
231 QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) );
232 }
233 }
234
235 return !mMustBeDistant;
236}
237
238//
239// QgsLabelingEngineRuleMinimumDistanceLabelToFeature
240//
241
244
246{
247 std::unique_ptr< QgsLabelingEngineRuleMinimumDistanceLabelToFeature> res = std::make_unique< QgsLabelingEngineRuleMinimumDistanceLabelToFeature >();
248 copyCommonProperties( res.get() );
249 return res.release();
250}
251
253{
254 return QStringLiteral( "minimumDistanceLabelToFeature" );
255}
256
258{
259 return QObject::tr( "Push Labels Away from Features" );
260}
261
263{
264 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
265 if ( labeledLayer() && targetLayer() )
266 {
267 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must be at least %2 %3 from features in <i>%4</i>" ).arg(
268 labeledLayer()->name(),
269 QString::number( distance() ),
271 targetLayer()->name()
272 ) + QStringLiteral( "</p>" );
273 }
274 return res;
275}
276
277
278//
279// QgsLabelingEngineRuleMaximumDistanceLabelToFeature
280//
281
286
288
290{
291 std::unique_ptr< QgsLabelingEngineRuleMaximumDistanceLabelToFeature > res = std::make_unique< QgsLabelingEngineRuleMaximumDistanceLabelToFeature >();
292 copyCommonProperties( res.get() );
293 return res.release();
294}
295
297{
298 return QStringLiteral( "maximumDistanceLabelToFeature" );
299}
300
302{
303 return QObject::tr( "Pull Labels Toward Features" );
304}
305
307{
308 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
309 if ( labeledLayer() && targetLayer() )
310 {
311 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must be at most %2 %3 from features in <i>%4</i>" ).arg(
312 labeledLayer()->name(),
313 QString::number( distance() ),
315 targetLayer()->name()
316 ) + QStringLiteral( "</p>" );
317 }
318 return res;
319}
320
321
322//
323// QgsLabelingEngineRuleMinimumDistanceLabelToLabel
324//
325
328
330{
331 std::unique_ptr< QgsLabelingEngineRuleMinimumDistanceLabelToLabel> res = std::make_unique< QgsLabelingEngineRuleMinimumDistanceLabelToLabel >();
332 copyCommonProperties( res.get() );
333 res->mLabeledLayer = mLabeledLayer;
334 res->mTargetLayer = mTargetLayer;
335 res->mDistance = mDistance;
336 res->mDistanceUnit = mDistanceUnit;
337 res->mDistanceUnitScale = mDistanceUnitScale;
338 return res.release();
339}
340
342{
343 return QStringLiteral( "minimumDistanceLabelToLabel" );
344}
345
347{
348 return QObject::tr( "Push Labels Away from Other Labels" );
349}
350
352{
353 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
354 if ( labeledLayer() && targetLayer() )
355 {
356 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must be at least %2 %3 from labels from <i>%4</i>" ).arg(
357 labeledLayer()->name(),
358 QString::number( distance() ),
360 targetLayer()->name()
361 ) + QStringLiteral( "</p>" );
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( QStringLiteral( "distance" ), mDistance );
378 element.setAttribute( QStringLiteral( "distanceUnit" ), QgsUnitTypes::encodeUnit( mDistanceUnit ) );
379 element.setAttribute( QStringLiteral( "distanceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceUnitScale ) );
380
381 if ( mLabeledLayer )
382 {
383 element.setAttribute( QStringLiteral( "labeledLayer" ), mLabeledLayer.layerId );
384 element.setAttribute( QStringLiteral( "labeledLayerName" ), mLabeledLayer.name );
385 element.setAttribute( QStringLiteral( "labeledLayerSource" ), mLabeledLayer.source );
386 element.setAttribute( QStringLiteral( "labeledLayerProvider" ), mLabeledLayer.provider );
387 }
388 if ( mTargetLayer )
389 {
390 element.setAttribute( QStringLiteral( "targetLayer" ), mTargetLayer.layerId );
391 element.setAttribute( QStringLiteral( "targetLayerName" ), mTargetLayer.name );
392 element.setAttribute( QStringLiteral( "targetLayerSource" ), mTargetLayer.source );
393 element.setAttribute( QStringLiteral( "targetLayerProvider" ), mTargetLayer.provider );
394 }
395}
396
398{
399 mDistance = element.attribute( QStringLiteral( "distance" ), QStringLiteral( "5" ) ).toDouble();
400 mDistanceUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "distanceUnit" ) ) );
401 mDistanceUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( element.attribute( QStringLiteral( "distanceUnitScale" ) ) );
402
403 {
404 const QString layerId = element.attribute( QStringLiteral( "labeledLayer" ) );
405 const QString layerName = element.attribute( QStringLiteral( "labeledLayerName" ) );
406 const QString layerSource = element.attribute( QStringLiteral( "labeledLayerSource" ) );
407 const QString layerProvider = element.attribute( QStringLiteral( "labeledLayerProvider" ) );
408 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
409 }
410 {
411 const QString layerId = element.attribute( QStringLiteral( "targetLayer" ) );
412 const QString layerName = element.attribute( QStringLiteral( "targetLayerName" ) );
413 const QString layerSource = element.attribute( QStringLiteral( "targetLayerSource" ) );
414 const QString layerProvider = element.attribute( QStringLiteral( "targetLayerProvider" ) );
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 (
440 ( lp1->getFeaturePart()->feature()->provider()->layerId() == mLabeledLayer.layerId
441 && lp2->getFeaturePart()->feature()->provider()->layerId() == mTargetLayer.layerId )
442 ||
443 ( lp2->getFeaturePart()->feature()->provider()->layerId() == mLabeledLayer.layerId
444 && lp1->getFeaturePart()->feature()->provider()->layerId() == mTargetLayer.layerId )
445 )
446 {
447 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
448 try
449 {
450#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
451 if ( GEOSPreparedDistanceWithin_r( geosctxt, lp1->preparedMultiPartGeom(), lp2->multiPartGeom(), mDistanceMapUnits ) )
452 {
453 return true;
454 }
455#else
456 QgsMessageLog::logMessage( QStringLiteral( "The %1 labeling rule requires GEOS 3.10+" ).arg( name().isEmpty() ? displayType() : name() ) );
457 return false;
458#endif
459 }
460 catch ( GEOSException &e )
461 {
462 QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) );
463 }
464 }
465
466 return false;
467}
468
473
475{
476 mLabeledLayer = layer;
477}
478
483
485{
486 mTargetLayer = layer;
487}
488
489
490//
491// QgsLabelingEngineRuleAvoidLabelOverlapWithFeature
492//
493
496
498{
499 std::unique_ptr< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature> res = std::make_unique< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature >();
500 copyCommonProperties( res.get() );
501 res->mLabeledLayer = mLabeledLayer;
502 res->mTargetLayer = mTargetLayer;
503 return res.release();
504}
505
507{
508 return QStringLiteral( "avoidLabelOverlapWithFeature" );
509}
510
512{
513 return QObject::tr( "Prevent Labels Overlapping Features" );
514}
515
517{
518 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
519 if ( labeledLayer() && targetLayer() )
520 {
521 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must not overlap features from <i>%2</i>" ).arg(
522 labeledLayer()->name(),
523 targetLayer()->name()
524 ) + QStringLiteral( "</p>" );
525 }
526 return res;
527}
528
530{
531 if ( !mTargetLayer )
532 return false;
533
535 mTargetLayerSource = std::make_unique< QgsVectorLayerFeatureSource >( mTargetLayer.get() );
536 return true;
537}
538
539void QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
540{
541 if ( mLabeledLayer )
542 {
543 element.setAttribute( QStringLiteral( "labeledLayer" ), mLabeledLayer.layerId );
544 element.setAttribute( QStringLiteral( "labeledLayerName" ), mLabeledLayer.name );
545 element.setAttribute( QStringLiteral( "labeledLayerSource" ), mLabeledLayer.source );
546 element.setAttribute( QStringLiteral( "labeledLayerProvider" ), mLabeledLayer.provider );
547 }
548 if ( mTargetLayer )
549 {
550 element.setAttribute( QStringLiteral( "targetLayer" ), mTargetLayer.layerId );
551 element.setAttribute( QStringLiteral( "targetLayerName" ), mTargetLayer.name );
552 element.setAttribute( QStringLiteral( "targetLayerSource" ), mTargetLayer.source );
553 element.setAttribute( QStringLiteral( "targetLayerProvider" ), mTargetLayer.provider );
554 }
555}
556
558{
559 {
560 const QString layerId = element.attribute( QStringLiteral( "labeledLayer" ) );
561 const QString layerName = element.attribute( QStringLiteral( "labeledLayerName" ) );
562 const QString layerSource = element.attribute( QStringLiteral( "labeledLayerSource" ) );
563 const QString layerProvider = element.attribute( QStringLiteral( "labeledLayerProvider" ) );
564 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
565 }
566 {
567 const QString layerId = element.attribute( QStringLiteral( "targetLayer" ) );
568 const QString layerName = element.attribute( QStringLiteral( "targetLayerName" ) );
569 const QString layerSource = element.attribute( QStringLiteral( "targetLayerSource" ) );
570 const QString layerProvider = element.attribute( QStringLiteral( "targetLayerProvider" ) );
571 mTargetLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
572 }
573}
574
576{
577 mLabeledLayer.resolve( project );
578 mTargetLayer.resolve( project );
579}
580
582{
583 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
584 {
585 return false;
586 }
587
588 if ( !mTargetLayerSource )
589 return false;
590
591 if ( !mInitialized )
592 const_cast< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature * >( this )->initialize( context );
593
594 const QList<QgsFeatureId> overlapCandidates = mIndex->intersects( candidate->outerBoundingBox() );
595 if ( overlapCandidates.empty() )
596 return false;
597
598 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
599
600 const GEOSPreparedGeometry *candidateGeos = candidate->preparedMultiPartGeom();
601 for ( const QgsFeatureId overlapCandidateId : overlapCandidates )
602 {
603 if ( context.renderContext().feedback() && context.renderContext().feedback()->isCanceled() )
604 break;
605
606 try
607 {
608 geos::unique_ptr featureCandidate = QgsGeos::asGeos( mIndex->geometry( overlapCandidateId ).constGet() );
609 if ( GEOSPreparedIntersects_r( geosctxt, candidateGeos, featureCandidate.get() ) == 1 )
610 return true;
611 }
612 catch ( GEOSException &e )
613 {
614 QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) );
615 }
616 }
617
618 return false;
619}
620
625
627{
628 mLabeledLayer = layer;
629}
630
635
640
641void QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::initialize( QgsLabelingEngineContext &context )
642{
645 req.setFilterRect( context.extent() );
646 req.setNoAttributes();
647
648 QgsFeatureIterator it = mTargetLayerSource->getFeatures( req );
649
650 mIndex = std::make_unique< QgsSpatialIndex >( it, context.renderContext().feedback(), QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
651
652 mInitialized = true;
653}
QString layerId() const
Returns ID of associated layer, or empty string if no layer is associated with the provider.
Base class for labeling engine rules which prevents labels being placed too close or to far from feat...
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.
This class 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:53
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:257
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.
A labeling engine rule which prevents labels being placed overlapping features from a different layer...
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.
A labeling engine rule which prevents labels being placed too far from features from a different laye...
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.
A labeling engine rule which prevents labels being placed too close to features from a different laye...
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.
A labeling engine rule which prevents labels being placed too close to labels from a different layer.
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:76
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
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:107
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
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 data sets.
QgsLabelFeature * feature()
Returns the parent feature.
Definition feature.h:94
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.
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugError(str)
Definition qgslogger.h:38
_LayerRef< QgsMapLayer > QgsMapLayerRef
#define QGIS_CHECK_OTHER_QOBJECT_THREAD_ACCESS(other)
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
QString source
Weak reference to layer public source.
QString name
Weak reference to layer name.
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer.
QString provider
Weak reference to layer provider.
TYPE * resolve(const QgsProject *project)
Resolves the map layer by attempting to find a layer with matching ID within a project.
QString layerId
Original layer ID.