53   mGlobalCandidatesLimitPoint = settings.
value( QStringLiteral( 
"rendering/label_candidates_limit_points" ), 0, 
QgsSettings::Core ).toInt();
 
   54   mGlobalCandidatesLimitLine = settings.
value( QStringLiteral( 
"rendering/label_candidates_limit_lines" ), 0, 
QgsSettings::Core ).toInt();
 
   55   mGlobalCandidatesLimitPolygon = settings.
value( QStringLiteral( 
"rendering/label_candidates_limit_polygons" ), 0, 
QgsSettings::Core ).toInt();
 
   67   for ( 
auto it = mLayers.begin(); it != mLayers.end(); ++it )
 
   69     if ( it->second.get() == layer )
 
   82   Q_ASSERT( mLayers.find( provider ) == mLayers.end() );
 
   84   std::unique_ptr< Layer > layer = std::make_unique< Layer >( provider, layerName, arrangement, defaultPriority, active, toLabel, 
this, displayAll );
 
   85   Layer *res = layer.get();
 
  102   std::vector< FeaturePart * > allObstacleParts;
 
  103   std::unique_ptr< Problem > prob = std::make_unique< Problem >( maxCoordinateExtentForSpatialIndices );
 
  108   bbx[0] = bbx[3] = prob->mMapExtentBounds[0] = extent.
xMinimum();
 
  109   bby[0] = bby[1] = prob->mMapExtentBounds[1] = extent.
yMinimum();
 
  110   bbx[1] = bbx[2] = prob->mMapExtentBounds[2] = extent.
xMaximum();
 
  111   bby[2] = bby[3] = prob->mMapExtentBounds[3] = extent.
yMaximum();
 
  115   std::list< std::unique_ptr< Feats > > features;
 
  121   int obstacleCount = 0;
 
  125   std::size_t previousFeatureCount = 0;
 
  126   int previousObstacleCount = 0;
 
  128   QStringList layersWithFeaturesInBBox;
 
  130   QMutexLocker palLocker( &mMutex );
 
  131   for ( 
const auto &it : mLayers )
 
  133     Layer *layer = it.second.get();
 
  156     QMutexLocker locker( &layer->
mMutex );
 
  159     for ( 
const std::unique_ptr< FeaturePart > &featurePart : std::as_const( layer->
mFeatureParts ) )
 
  165       for ( 
int i = 0; i < featurePart->getNumSelfObstacles(); i++ )
 
  168         obstacles.insert( selfObstacle, selfObstacle->
boundingBox() );
 
  169         allObstacleParts.emplace_back( selfObstacle );
 
  171         if ( !featurePart->getSelfObstacle( i )->getHoleOf() )
 
  178       std::vector< std::unique_ptr< LabelPosition > > candidates = featurePart->
createCandidates( 
this );
 
  184       candidates.erase( std::remove_if( candidates.begin(), candidates.end(), [&mapBoundaryPrepared, 
this]( std::unique_ptr< LabelPosition > &candidate )
 
  186         if ( showPartialLabels() )
 
  187           return !candidate->intersects( mapBoundaryPrepared.get() );
 
  189           return !candidate->within( mapBoundaryPrepared.get() );
 
  190       } ), candidates.end() );
 
  195       if ( !candidates.empty() )
 
  197         for ( std::unique_ptr< LabelPosition > &candidate : candidates )
 
  199           candidate->insertIntoIndex( allCandidatesFirstRound );
 
  200           candidate->setGlobalId( mNextCandidateId++ );
 
  206         std::unique_ptr< Feats > ft = std::make_unique< Feats >();
 
  207         ft->feature = featurePart.get();
 
  209         ft->candidates = std::move( candidates );
 
  210         ft->priority = featurePart->calculatePriority();
 
  211         features.emplace_back( std::move( ft ) );
 
  216         std::unique_ptr< LabelPosition > unplacedPosition = featurePart->createCandidatePointOnSurface( featurePart.get() );
 
  217         if ( !unplacedPosition )
 
  223           unplacedPosition->insertIntoIndex( allCandidatesFirstRound );
 
  224           unplacedPosition->setGlobalId( mNextCandidateId++ );
 
  225           candidates.emplace_back( std::move( unplacedPosition ) );
 
  228           std::unique_ptr< Feats > ft = std::make_unique< Feats >();
 
  229           ft->feature = featurePart.get();
 
  231           ft->candidates = std::move( candidates );
 
  232           ft->priority = featurePart->calculatePriority();
 
  233           features.emplace_back( std::move( ft ) );
 
  238           prob->positionsWithNoCandidates()->emplace_back( std::move( unplacedPosition ) );
 
  252       obstacles.insert( obstaclePart, obstaclePart->boundingBox() );
 
  253       allObstacleParts.emplace_back( obstaclePart );
 
  262     if ( features.size() - previousFeatureCount > 0 || obstacleCount > previousObstacleCount )
 
  264       layersWithFeaturesInBBox << layer->
name();
 
  266     previousFeatureCount = features.size();
 
  267     previousObstacleCount = obstacleCount;
 
  274   prob->mLayerCount = layersWithFeaturesInBBox.size();
 
  275   prob->labelledLayersName = layersWithFeaturesInBBox;
 
  277   prob->mFeatureCount = features.size();
 
  278   prob->mTotalCandidates = 0;
 
  279   prob->mFeatNbLp.resize( prob->mFeatureCount );
 
  280   prob->mFeatStartId.resize( prob->mFeatureCount );
 
  281   prob->mInactiveCost.resize( prob->mFeatureCount );
 
  283   if ( !features.empty() )
 
  286     for ( 
FeaturePart *obstaclePart : allObstacleParts )
 
  291       allCandidatesFirstRound.intersects( obstaclePart->boundingBox(), [obstaclePart, 
this]( 
const LabelPosition * candidatePosition ) -> 
bool 
  298         if ( ( !obstaclePart->getHoleOf() && candidatePosition->getFeaturePart()->hasSameLabelFeatureAs( obstaclePart ) )
 
  299              || ( obstaclePart->getHoleOf() && !candidatePosition->getFeaturePart()->hasSameLabelFeatureAs( dynamic_cast< FeaturePart * >( obstaclePart->getHoleOf() ) ) ) )
 
  316     for ( std::size_t i = 0; i < prob->mFeatureCount; i++ ) 
 
  318       std::unique_ptr< Feats > feat = std::move( features.front() );
 
  319       features.pop_front();
 
  321       prob->mFeatStartId[i] = idlp;
 
  322       prob->mInactiveCost[i] = std::pow( 2, 10 - 10 * feat->priority );
 
  324       std::size_t maxCandidates = 0;
 
  325       switch ( feat->feature->getGeosType() )
 
  329           maxCandidates = feat->feature->maximumPointCandidates();
 
  332         case GEOS_LINESTRING:
 
  333           maxCandidates = feat->feature->maximumLineCandidates();
 
  337           maxCandidates = std::max( 
static_cast< std::size_t 
>( 16 ), feat->feature->maximumPolygonCandidates() );
 
  344       auto pruneHardConflicts = [&]
 
  346         switch ( mPlacementVersion )
 
  357             feat->candidates.erase( std::remove_if( feat->candidates.begin() + 1, feat->candidates.end(), [ & ]( std::unique_ptr< LabelPosition > &candidate )
 
  359               if ( candidate->hasHardObstacleConflict() )
 
  364             } ), feat->candidates.end() );
 
  366             if ( feat->candidates.size() == 1 && feat->candidates[ 0 ]->hasHardObstacleConflict() && !feat->feature->layer()->displayAll() )
 
  370               prob->positionsWithNoCandidates()->emplace_back( std::move( feat->candidates.front() ) );
 
  371               feat->candidates.clear();
 
  379       if ( !feat->feature->layer()->displayAll() )
 
  381         pruneHardConflicts();
 
  384       if ( feat->candidates.empty() )
 
  397       if ( feat->feature->layer()->displayAll() )
 
  399         pruneHardConflicts();
 
  404       if ( maxCandidates > 0 && feat->candidates.size() > maxCandidates )
 
  406         feat->candidates.resize( maxCandidates );
 
  413       prob->mFeatNbLp[i] = 
static_cast< int >( feat->candidates.size() );
 
  414       prob->mTotalCandidates += 
static_cast< int >( feat->candidates.size() );
 
  417       for ( std::unique_ptr< LabelPosition > &candidate : feat->candidates )
 
  419         candidate->insertIntoIndex( prob->allCandidatesIndex() );
 
  420         candidate->setProblemIds( 
static_cast< int >( i ), idlp++ );
 
  422       features.emplace_back( std::move( feat ) );
 
  429     while ( !features.empty() ) 
 
  434       std::unique_ptr< Feats > feat = std::move( features.front() );
 
  435       features.pop_front();
 
  437       for ( std::unique_ptr< LabelPosition > &candidate : feat->candidates )
 
  439         std::unique_ptr< LabelPosition > lp = std::move( candidate );
 
  441         lp->resetNumOverlaps();
 
  449         lp->getBoundingBox( amin, amax );
 
  450         prob->allCandidatesIndex().intersects( 
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [&lp, 
this]( 
const LabelPosition * lp2 )->
bool 
  452           if ( candidatesAreConflicting( lp.get(), lp2 ) )
 
  454             lp->incrementNumOverlaps();
 
  461         nbOverlaps += lp->getNumOverlaps();
 
  463         prob->addCandidatePosition( std::move( lp ) );
 
  470     prob->mAllNblp = prob->mTotalCandidates;
 
  471     prob->mNbOverlap = nbOverlaps;
 
  477 void Pal::registerCancellationCallback( Pal::FnIsCanceled fnCanceled, 
void *context )
 
  479   fnIsCanceled = fnCanceled;
 
  480   fnIsCanceledContext = context;
 
  485   return extract( extent, mapBoundary );
 
  491     return QList<LabelPosition *>();
 
  501     return QList<LabelPosition *>();
 
  507 void Pal::setMinIt( 
int min_it )
 
  513 void Pal::setMaxIt( 
int max_it )
 
  519 void Pal::setPopmusicR( 
int r )
 
  525 void Pal::setEjChainDeg( 
int degree )
 
  527   this->mEjChainDeg = degree;
 
  530 void Pal::setTenure( 
int tenure )
 
  532   this->mTenure = tenure;
 
  535 void Pal::setCandListSize( 
double fact )
 
  537   this->mCandListSize = fact;
 
  542   this->mShowPartialLabels = show;
 
  547   return mPlacementVersion;
 
  562   auto it = mCandidateConflicts.constFind( key );
 
  563   if ( it != mCandidateConflicts.constEnd() )
 
  567   mCandidateConflicts.insert( key, res );
 
  583   return mShowPartialLabels;
 
A rtree spatial index for use in the pal labeling engine.
The QgsAbstractLabelProvider class is an interface class.
A geometry is the spatial representation of a feature.
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0)
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
static GEOSContextHandle_t getGEOSHandler()
PlacementEngineVersion
Placement engine version.
@ PlacementEngineVersion1
Version 1, matches placement from QGIS <= 3.10.1.
@ PlacementEngineVersion2
Version 2 (default for new projects since QGIS 3.12)
Placement
Placement modes which determine how label candidates are generated for a feature.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsRectangle buffered(double width) const
Gets rectangle enlarged by buffer.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static void addObstacleCostPenalty(pal::LabelPosition *lp, pal::FeaturePart *obstacle, Pal *pal)
Increase candidate's cost according to its collision with passed feature.
static void finalizeCandidatesCosts(Feats *feat, double bbx[4], double bby[4])
Sort candidates by costs, skip the worse ones, evaluate polygon candidates.
static bool candidateSortGrow(const std::unique_ptr< pal::LabelPosition > &c1, const std::unique_ptr< pal::LabelPosition > &c2)
Sorts label candidates in ascending order of cost.
Main class to handle feature.
std::vector< std::unique_ptr< LabelPosition > > createCandidates(Pal *pal)
Generates a list of candidate positions for labels for this feature.
FeaturePart * getSelfObstacle(int i)
Gets hole (inner ring) - considered as obstacle.
Thrown when trying to access an empty data set.
LabelPosition is a candidate feature label position.
bool isInConflict(const LabelPosition *ls) const
Check whether or not this overlap with another labelPosition.
unsigned int globalId() const
Returns the global ID for the candidate, which is unique for a single run of the pal labelling engine...
A set of features which influence the labeling process.
std::deque< std::unique_ptr< FeaturePart > > mFeatureParts
List of feature parts.
QList< FeaturePart * > mObstacleParts
List of obstacle parts.
QString name() const
Returns the layer's name.
bool active() const
Returns whether the layer is currently active.
bool mergeConnectedLines() const
Returns whether connected lines will be merged before labeling.
void joinConnectedFeatures()
Join connected features with the same label text.
void chopFeaturesAtRepeatDistance()
Chop layer features at the repeat distance.
void setPlacementVersion(QgsLabelingEngineSettings::PlacementEngineVersion placementVersion)
Sets the placement engine version, which dictates how the label placement problem is solved.
QgsLabelingEngineSettings::PlacementEngineVersion placementVersion() const
Returns the placement engine version, which dictates how the label placement problem is solved.
void setShowPartialLabels(bool show)
Sets whether partial labels show be allowed.
Layer * addLayer(QgsAbstractLabelProvider *provider, const QString &layerName, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, bool displayAll=false)
add a new layer
std::unique_ptr< Problem > extractProblem(const QgsRectangle &extent, const QgsGeometry &mapBoundary)
Extracts the labeling problem for the specified map extent - only features within this extent will be...
void removeLayer(Layer *layer)
remove a layer
bool candidatesAreConflicting(const LabelPosition *lp1, const LabelPosition *lp2) const
Returns true if a labelling candidate lp1 conflicts with lp2.
QList< LabelPosition * > solveProblem(Problem *prob, bool displayAll, QList< pal::LabelPosition * > *unlabeled=nullptr)
Solves the labeling problem, selecting the best candidate locations for all labels and returns a list...
bool showPartialLabels() const
Returns whether partial labels should be allowed.
Pal()
Create an new pal instance.
bool isCanceled()
Check whether the job has been canceled.
QgsRectangle boundingBox() const
Returns the point set bounding box.
Representation of a labeling problem.
QList< LabelPosition * > getSolution(bool returnInactive, QList< LabelPosition * > *unlabeled=nullptr)
Solves the labeling problem, selecting the best candidate locations for all labels and returns a list...
void chain_search()
Test with very-large scale neighborhood.
std::unique_ptr< const GEOSPreparedGeometry, GeosDeleter > prepared_unique_ptr
Scoped GEOS prepared geometry pointer.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.