QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 10
28#include "qgsmessagelog.h"
29#endif
30
31//
32// QgsAbstractLabelingEngineRuleDistanceFromFeature
33//
34
37
39{
40 if ( !mTargetLayer )
41 return false;
42
44 mTargetLayerSource = std::make_unique< QgsVectorLayerFeatureSource >( mTargetLayer.get() );
45
46 mDistanceMapUnits = context.convertToMapUnits( mDistance, mDistanceUnit, mDistanceUnitScale );
47 return true;
48}
49
50void QgsAbstractLabelingEngineRuleDistanceFromFeature::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
51{
52 element.setAttribute( QStringLiteral( "distance" ), mDistance );
53 element.setAttribute( QStringLiteral( "distanceUnit" ), QgsUnitTypes::encodeUnit( mDistanceUnit ) );
54 element.setAttribute( QStringLiteral( "distanceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceUnitScale ) );
55 element.setAttribute( QStringLiteral( "cost" ), mCost );
56
57 if ( mLabeledLayer )
58 {
59 element.setAttribute( QStringLiteral( "labeledLayer" ), mLabeledLayer.layerId );
60 element.setAttribute( QStringLiteral( "labeledLayerName" ), mLabeledLayer.name );
61 element.setAttribute( QStringLiteral( "labeledLayerSource" ), mLabeledLayer.source );
62 element.setAttribute( QStringLiteral( "labeledLayerProvider" ), mLabeledLayer.provider );
63 }
64 if ( mTargetLayer )
65 {
66 element.setAttribute( QStringLiteral( "targetLayer" ), mTargetLayer.layerId );
67 element.setAttribute( QStringLiteral( "targetLayerName" ), mTargetLayer.name );
68 element.setAttribute( QStringLiteral( "targetLayerSource" ), mTargetLayer.source );
69 element.setAttribute( QStringLiteral( "targetLayerProvider" ), mTargetLayer.provider );
70 }
71}
72
74{
75 mDistance = element.attribute( QStringLiteral( "distance" ), QStringLiteral( "5" ) ).toDouble();
76 mDistanceUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "distanceUnit" ) ) );
77 mDistanceUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( element.attribute( QStringLiteral( "distanceUnitScale" ) ) );
78 mCost = element.attribute( QStringLiteral( "cost" ), QStringLiteral( "10" ) ).toDouble();
79
80 {
81 const QString layerId = element.attribute( QStringLiteral( "labeledLayer" ) );
82 const QString layerName = element.attribute( QStringLiteral( "labeledLayerName" ) );
83 const QString layerSource = element.attribute( QStringLiteral( "labeledLayerSource" ) );
84 const QString layerProvider = element.attribute( QStringLiteral( "labeledLayerProvider" ) );
85 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
86 }
87 {
88 const QString layerId = element.attribute( QStringLiteral( "targetLayer" ) );
89 const QString layerName = element.attribute( QStringLiteral( "targetLayerName" ) );
90 const QString layerSource = element.attribute( QStringLiteral( "targetLayerSource" ) );
91 const QString layerProvider = element.attribute( QStringLiteral( "targetLayerProvider" ) );
92 mTargetLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
93 }
94}
95
97{
98 mLabeledLayer.resolve( project );
99 mTargetLayer.resolve( project );
100}
101
103{
104 // hard blocks on candidates only apply when cost == 10
105 if ( mCost < 10 )
106 return false;
107
108 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
109 {
110 return false;
111 }
112
113 if ( !mTargetLayerSource )
114 return false;
115
116 return candidateExceedsTolerance( candidate, context );
117}
118
120{
121 // cost of 10 = hard block, handled in candidateIsIllegal
122 if ( mCost >= 10 )
123 return;
124
125 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
126 {
127 return;
128 }
129
130 if ( !mTargetLayerSource )
131 return;
132
133 if ( candidateExceedsTolerance( candidate, context ) )
134 {
135 // magic number alert! / 1000 here is completely arbitrary, an attempt to balance against the cost scaling of other factors
136 // assigned by the inscrutible logic of the pal engine internals
137 candidate->setCost( candidate->cost() + mCost / 1000 );
138 }
139}
140
142{
143#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
144 return true;
145#else
146 return false;
147#endif
148}
149
151{
152 return mLabeledLayer.get();
153}
154
156{
157 mLabeledLayer = layer;
158}
159
164
169
171{
174 {
175 otherRule->mLabeledLayer = mLabeledLayer;
176 otherRule->mTargetLayer = mTargetLayer;
177 otherRule->mDistance = mDistance;
178 otherRule->mDistanceUnit = mDistanceUnit;
179 otherRule->mDistanceUnitScale = mDistanceUnitScale;
180 otherRule->mCost = mCost;
181 }
182}
183
184void QgsAbstractLabelingEngineRuleDistanceFromFeature::initialize( QgsLabelingEngineContext &context )
185{
188 req.setFilterRect( context.extent() );
189 req.setNoAttributes();
190
191 QgsFeatureIterator it = mTargetLayerSource->getFeatures( req );
192
193 mIndex = std::make_unique< QgsSpatialIndex >( it, context.renderContext().feedback(), QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
194
195 mInitialized = true;
196}
197
198bool QgsAbstractLabelingEngineRuleDistanceFromFeature::candidateExceedsTolerance( const pal::LabelPosition *candidate, QgsLabelingEngineContext &context ) const
199{
200 if ( !mInitialized )
201 const_cast< QgsAbstractLabelingEngineRuleDistanceFromFeature * >( this )->initialize( context );
202
203 const QgsRectangle candidateBounds = candidate->outerBoundingBox();
204 const QgsRectangle expandedBounds = candidateBounds.buffered( mDistanceMapUnits );
205
206 const QList<QgsFeatureId> overlapCandidates = mIndex->intersects( expandedBounds );
207 if ( overlapCandidates.empty() )
208 return !mMustBeDistant;
209
210 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
211
212 const GEOSPreparedGeometry *candidateGeos = candidate->preparedMultiPartGeom();
213 for ( const QgsFeatureId overlapCandidateId : overlapCandidates )
214 {
215 if ( context.renderContext().feedback() && context.renderContext().feedback()->isCanceled() )
216 break;
217
218 try
219 {
220 geos::unique_ptr featureCandidate = QgsGeos::asGeos( mIndex->geometry( overlapCandidateId ).constGet() );
221#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
222 if ( GEOSPreparedDistanceWithin_r( geosctxt, candidateGeos, featureCandidate.get(), mDistanceMapUnits ) )
223 {
224 return mMustBeDistant;
225 }
226#else
227 QgsMessageLog::logMessage( QStringLiteral( "The %1 labeling rule requires GEOS 3.10+" ).arg( name().isEmpty() ? displayType() : name() ) );
228 return false;
229#endif
230 }
231 catch ( QgsGeosException &e )
232 {
233 QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) );
234 }
235 }
236
237 return !mMustBeDistant;
238}
239
240//
241// QgsLabelingEngineRuleMinimumDistanceLabelToFeature
242//
243
246
248{
249 auto res = std::make_unique< QgsLabelingEngineRuleMinimumDistanceLabelToFeature >();
250 copyCommonProperties( res.get() );
251 return res.release();
252}
253
255{
256 return QStringLiteral( "minimumDistanceLabelToFeature" );
257}
258
260{
261 return QObject::tr( "Push Labels Away from Features" );
262}
263
265{
266 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
267 if ( labeledLayer() && targetLayer() )
268 {
269 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must be at least %2 %3 from features in <i>%4</i>" ).arg(
270 labeledLayer()->name(),
271 QString::number( distance() ),
273 targetLayer()->name()
274 ) + QStringLiteral( "</p>" );
275 }
276 return res;
277}
278
279
280//
281// QgsLabelingEngineRuleMaximumDistanceLabelToFeature
282//
283
288
290
292{
293 auto res = std::make_unique< QgsLabelingEngineRuleMaximumDistanceLabelToFeature >();
294 copyCommonProperties( res.get() );
295 return res.release();
296}
297
299{
300 return QStringLiteral( "maximumDistanceLabelToFeature" );
301}
302
304{
305 return QObject::tr( "Pull Labels Toward Features" );
306}
307
309{
310 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
311 if ( labeledLayer() && targetLayer() )
312 {
313 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must be at most %2 %3 from features in <i>%4</i>" ).arg(
314 labeledLayer()->name(),
315 QString::number( distance() ),
317 targetLayer()->name()
318 ) + QStringLiteral( "</p>" );
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 QStringLiteral( "minimumDistanceLabelToLabel" );
346}
347
349{
350 return QObject::tr( "Push Labels Away from Other Labels" );
351}
352
354{
355 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
356 if ( labeledLayer() && targetLayer() )
357 {
358 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must be at least %2 %3 from labels from <i>%4</i>" ).arg(
359 labeledLayer()->name(),
360 QString::number( distance() ),
362 targetLayer()->name()
363 ) + QStringLiteral( "</p>" );
364 }
365 return res;
366}
367
369{
370#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
371 return true;
372#else
373 return false;
374#endif
375}
376
377void QgsLabelingEngineRuleMinimumDistanceLabelToLabel::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
378{
379 element.setAttribute( QStringLiteral( "distance" ), mDistance );
380 element.setAttribute( QStringLiteral( "distanceUnit" ), QgsUnitTypes::encodeUnit( mDistanceUnit ) );
381 element.setAttribute( QStringLiteral( "distanceUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceUnitScale ) );
382
383 if ( mLabeledLayer )
384 {
385 element.setAttribute( QStringLiteral( "labeledLayer" ), mLabeledLayer.layerId );
386 element.setAttribute( QStringLiteral( "labeledLayerName" ), mLabeledLayer.name );
387 element.setAttribute( QStringLiteral( "labeledLayerSource" ), mLabeledLayer.source );
388 element.setAttribute( QStringLiteral( "labeledLayerProvider" ), mLabeledLayer.provider );
389 }
390 if ( mTargetLayer )
391 {
392 element.setAttribute( QStringLiteral( "targetLayer" ), mTargetLayer.layerId );
393 element.setAttribute( QStringLiteral( "targetLayerName" ), mTargetLayer.name );
394 element.setAttribute( QStringLiteral( "targetLayerSource" ), mTargetLayer.source );
395 element.setAttribute( QStringLiteral( "targetLayerProvider" ), mTargetLayer.provider );
396 }
397}
398
400{
401 mDistance = element.attribute( QStringLiteral( "distance" ), QStringLiteral( "5" ) ).toDouble();
402 mDistanceUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "distanceUnit" ) ) );
403 mDistanceUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( element.attribute( QStringLiteral( "distanceUnitScale" ) ) );
404
405 {
406 const QString layerId = element.attribute( QStringLiteral( "labeledLayer" ) );
407 const QString layerName = element.attribute( QStringLiteral( "labeledLayerName" ) );
408 const QString layerSource = element.attribute( QStringLiteral( "labeledLayerSource" ) );
409 const QString layerProvider = element.attribute( QStringLiteral( "labeledLayerProvider" ) );
410 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
411 }
412 {
413 const QString layerId = element.attribute( QStringLiteral( "targetLayer" ) );
414 const QString layerName = element.attribute( QStringLiteral( "targetLayerName" ) );
415 const QString layerSource = element.attribute( QStringLiteral( "targetLayerSource" ) );
416 const QString layerProvider = element.attribute( QStringLiteral( "targetLayerProvider" ) );
417 mTargetLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
418 }
419}
420
422{
423 mLabeledLayer.resolve( project );
424 mTargetLayer.resolve( project );
425}
426
428{
429 mDistanceMapUnits = context.convertToMapUnits( mDistance, mDistanceUnit, mDistanceUnitScale );
430 return true;
431}
432
434{
435 return candidateBounds.buffered( mDistanceMapUnits );
436}
437
439{
440 // conflicts are commutative -- we need to check both layers
441 if (
442 ( lp1->getFeaturePart()->feature()->provider()->layerId() == mLabeledLayer.layerId
443 && lp2->getFeaturePart()->feature()->provider()->layerId() == mTargetLayer.layerId )
444 ||
445 ( lp2->getFeaturePart()->feature()->provider()->layerId() == mLabeledLayer.layerId
446 && lp1->getFeaturePart()->feature()->provider()->layerId() == mTargetLayer.layerId )
447 )
448 {
449 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
450 try
451 {
452#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
453 if ( GEOSPreparedDistanceWithin_r( geosctxt, lp1->preparedMultiPartGeom(), lp2->multiPartGeom(), mDistanceMapUnits ) )
454 {
455 return true;
456 }
457#else
458 QgsMessageLog::logMessage( QStringLiteral( "The %1 labeling rule requires GEOS 3.10+" ).arg( name().isEmpty() ? displayType() : name() ) );
459 return false;
460#endif
461 }
462 catch ( QgsGeosException &e )
463 {
464 QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) );
465 }
466 }
467
468 return false;
469}
470
472{
473 return mLabeledLayer.get();
474}
475
477{
478 mLabeledLayer = layer;
479}
480
482{
483 return mTargetLayer.get();
484}
485
487{
488 mTargetLayer = layer;
489}
490
491
492//
493// QgsLabelingEngineRuleAvoidLabelOverlapWithFeature
494//
495
498
500{
501 auto res = std::make_unique< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature >();
502 copyCommonProperties( res.get() );
503 res->mLabeledLayer = mLabeledLayer;
504 res->mTargetLayer = mTargetLayer;
505 return res.release();
506}
507
509{
510 return QStringLiteral( "avoidLabelOverlapWithFeature" );
511}
512
514{
515 return QObject::tr( "Prevent Labels Overlapping Features" );
516}
517
519{
520 QString res = QStringLiteral( "<b>%1</b>" ).arg( name().isEmpty() ? displayType() : name() );
521 if ( labeledLayer() && targetLayer() )
522 {
523 res += QStringLiteral( "<p>" ) + QObject::tr( "Labels from <i>%1</i> must not overlap features from <i>%2</i>" ).arg(
524 labeledLayer()->name(),
525 targetLayer()->name()
526 ) + QStringLiteral( "</p>" );
527 }
528 return res;
529}
530
532{
533 if ( !mTargetLayer )
534 return false;
535
537 mTargetLayerSource = std::make_unique< QgsVectorLayerFeatureSource >( mTargetLayer.get() );
538 return true;
539}
540
541void QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::writeXml( QDomDocument &, QDomElement &element, const QgsReadWriteContext & ) const
542{
543 if ( mLabeledLayer )
544 {
545 element.setAttribute( QStringLiteral( "labeledLayer" ), mLabeledLayer.layerId );
546 element.setAttribute( QStringLiteral( "labeledLayerName" ), mLabeledLayer.name );
547 element.setAttribute( QStringLiteral( "labeledLayerSource" ), mLabeledLayer.source );
548 element.setAttribute( QStringLiteral( "labeledLayerProvider" ), mLabeledLayer.provider );
549 }
550 if ( mTargetLayer )
551 {
552 element.setAttribute( QStringLiteral( "targetLayer" ), mTargetLayer.layerId );
553 element.setAttribute( QStringLiteral( "targetLayerName" ), mTargetLayer.name );
554 element.setAttribute( QStringLiteral( "targetLayerSource" ), mTargetLayer.source );
555 element.setAttribute( QStringLiteral( "targetLayerProvider" ), mTargetLayer.provider );
556 }
557}
558
560{
561 {
562 const QString layerId = element.attribute( QStringLiteral( "labeledLayer" ) );
563 const QString layerName = element.attribute( QStringLiteral( "labeledLayerName" ) );
564 const QString layerSource = element.attribute( QStringLiteral( "labeledLayerSource" ) );
565 const QString layerProvider = element.attribute( QStringLiteral( "labeledLayerProvider" ) );
566 mLabeledLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
567 }
568 {
569 const QString layerId = element.attribute( QStringLiteral( "targetLayer" ) );
570 const QString layerName = element.attribute( QStringLiteral( "targetLayerName" ) );
571 const QString layerSource = element.attribute( QStringLiteral( "targetLayerSource" ) );
572 const QString layerProvider = element.attribute( QStringLiteral( "targetLayerProvider" ) );
573 mTargetLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
574 }
575}
576
578{
579 mLabeledLayer.resolve( project );
580 mTargetLayer.resolve( project );
581}
582
584{
585 if ( candidate->getFeaturePart()->feature()->provider()->layerId() != mLabeledLayer.layerId )
586 {
587 return false;
588 }
589
590 if ( !mTargetLayerSource )
591 return false;
592
593 if ( !mInitialized )
594 const_cast< QgsLabelingEngineRuleAvoidLabelOverlapWithFeature * >( this )->initialize( context );
595
596 const QList<QgsFeatureId> overlapCandidates = mIndex->intersects( candidate->outerBoundingBox() );
597 if ( overlapCandidates.empty() )
598 return false;
599
600 GEOSContextHandle_t geosctxt = QgsGeosContext::get();
601
602 const GEOSPreparedGeometry *candidateGeos = candidate->preparedMultiPartGeom();
603 for ( const QgsFeatureId overlapCandidateId : overlapCandidates )
604 {
605 if ( context.renderContext().feedback() && context.renderContext().feedback()->isCanceled() )
606 break;
607
608 try
609 {
610 geos::unique_ptr featureCandidate = QgsGeos::asGeos( mIndex->geometry( overlapCandidateId ).constGet() );
611 if ( GEOSPreparedIntersects_r( geosctxt, candidateGeos, featureCandidate.get() ) == 1 )
612 return true;
613 }
614 catch ( QgsGeosException &e )
615 {
616 QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) );
617 }
618 }
619
620 return false;
621}
622
624{
625 return mLabeledLayer.get();
626}
627
629{
630 mLabeledLayer = layer;
631}
632
637
642
643void QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::initialize( QgsLabelingEngineContext &context )
644{
647 req.setFilterRect( context.extent() );
648 req.setNoAttributes();
649
650 QgsFeatureIterator it = mTargetLayerSource->getFeatures( req );
651
652 mIndex = std::make_unique< QgsSpatialIndex >( it, context.renderContext().feedback(), QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
653
654 mInitialized = true;
655}
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: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:260
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:80
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())
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:109
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:89
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:114
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugError(str)
Definition qgslogger.h:57
_LayerRef< QgsMapLayer > QgsMapLayerRef
#define QGIS_CHECK_OTHER_QOBJECT_THREAD_ACCESS(other)
_LayerRef< QgsVectorLayer > QgsVectorLayerRef