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 = qgis::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 = qgis::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 );
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 );
205 std::unique_ptr< Feats > ft = qgis::make_unique< Feats >();
206 ft->feature = featurePart;
208 ft->candidates = std::move( candidates );
209 ft->priority = featurePart->calculatePriority();
210 features.emplace_back( std::move( ft ) );
215 std::unique_ptr< LabelPosition > unplacedPosition = featurePart->createCandidatePointOnSurface( featurePart );
216 if ( !unplacedPosition )
222 unplacedPosition->insertIntoIndex( allCandidatesFirstRound );
223 candidates.emplace_back( std::move( unplacedPosition ) );
226 std::unique_ptr< Feats > ft = qgis::make_unique< Feats >();
227 ft->feature = featurePart;
229 ft->candidates = std::move( candidates );
230 ft->priority = featurePart->calculatePriority();
231 features.emplace_back( std::move( ft ) );
236 prob->positionsWithNoCandidates()->emplace_back( std::move( unplacedPosition ) );
250 obstacles.insert( obstaclePart, obstaclePart->boundingBox() );
251 allObstacleParts.emplace_back( obstaclePart );
260 if ( features.size() - previousFeatureCount > 0 || obstacleCount > previousObstacleCount )
262 layersWithFeaturesInBBox << layer->
name();
264 previousFeatureCount = features.size();
265 previousObstacleCount = obstacleCount;
272 prob->mLayerCount = layersWithFeaturesInBBox.size();
273 prob->labelledLayersName = layersWithFeaturesInBBox;
275 prob->mFeatureCount = features.size();
276 prob->mTotalCandidates = 0;
277 prob->mFeatNbLp.resize( prob->mFeatureCount );
278 prob->mFeatStartId.resize( prob->mFeatureCount );
279 prob->mInactiveCost.resize( prob->mFeatureCount );
281 if ( !features.empty() )
284 for (
FeaturePart *obstaclePart : allObstacleParts )
289 allCandidatesFirstRound.intersects( obstaclePart->boundingBox(), [obstaclePart,
this](
const LabelPosition * candidatePosition ) ->
bool
296 if ( ( !obstaclePart->getHoleOf() && candidatePosition->getFeaturePart()->hasSameLabelFeatureAs( obstaclePart ) )
297 || ( obstaclePart->getHoleOf() && !candidatePosition->getFeaturePart()->hasSameLabelFeatureAs( dynamic_cast< FeaturePart * >( obstaclePart->getHoleOf() ) ) ) )
314 for ( std::size_t i = 0; i < prob->mFeatureCount; i++ )
316 std::unique_ptr< Feats > feat = std::move( features.front() );
317 features.pop_front();
319 prob->mFeatStartId[i] = idlp;
320 prob->mInactiveCost[i] = std::pow( 2, 10 - 10 * feat->priority );
322 std::size_t maxCandidates = 0;
323 switch ( feat->feature->getGeosType() )
327 maxCandidates = feat->feature->maximumPointCandidates();
330 case GEOS_LINESTRING:
331 maxCandidates = feat->feature->maximumLineCandidates();
335 maxCandidates = std::max(
static_cast< std::size_t
>( 16 ), feat->feature->maximumPolygonCandidates() );
342 auto pruneHardConflicts = [&]
344 switch ( mPlacementVersion )
355 feat->candidates.erase( std::remove_if( feat->candidates.begin() + 1, feat->candidates.end(), [ & ]( std::unique_ptr< LabelPosition > &candidate )
357 if ( candidate->hasHardObstacleConflict() )
362 } ), feat->candidates.end() );
364 if ( feat->candidates.size() == 1 && feat->candidates[ 0 ]->hasHardObstacleConflict() && !feat->feature->layer()->displayAll() )
368 prob->positionsWithNoCandidates()->emplace_back( std::move( feat->candidates.front() ) );
369 feat->candidates.clear();
377 if ( !feat->feature->layer()->displayAll() )
379 pruneHardConflicts();
382 if ( feat->candidates.empty() )
395 if ( feat->feature->layer()->displayAll() )
397 pruneHardConflicts();
402 if ( maxCandidates > 0 && feat->candidates.size() > maxCandidates )
404 feat->candidates.resize( maxCandidates );
411 prob->mFeatNbLp[i] =
static_cast< int >( feat->candidates.size() );
412 prob->mTotalCandidates +=
static_cast< int >( feat->candidates.size() );
415 for ( std::unique_ptr< LabelPosition > &candidate : feat->candidates )
417 candidate->insertIntoIndex( prob->allCandidatesIndex() );
418 candidate->setProblemIds(
static_cast< int >( i ), idlp++ );
420 features.emplace_back( std::move( feat ) );
427 while ( !features.empty() )
432 std::unique_ptr< Feats > feat = std::move( features.front() );
433 features.pop_front();
435 for ( std::unique_ptr< LabelPosition > &candidate : feat->candidates )
437 std::unique_ptr< LabelPosition > lp = std::move( candidate );
439 lp->resetNumOverlaps();
447 lp->getBoundingBox( amin, amax );
448 prob->allCandidatesIndex().intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [&lp](
const LabelPosition * lp2 )->
bool
450 if ( lp->isInConflict( lp2 ) )
452 lp->incrementNumOverlaps();
459 nbOverlaps += lp->getNumOverlaps();
461 prob->addCandidatePosition( std::move( lp ) );
468 prob->mAllNblp = prob->mTotalCandidates;
469 prob->mNbOverlap = nbOverlaps;
475 void Pal::registerCancellationCallback( Pal::FnIsCanceled fnCanceled,
void *context )
477 fnIsCanceled = fnCanceled;
478 fnIsCanceledContext = context;
483 return extract( extent, mapBoundary );
489 return QList<LabelPosition *>();
499 return QList<LabelPosition *>();
505 void Pal::setMinIt(
int min_it )
511 void Pal::setMaxIt(
int max_it )
517 void Pal::setPopmusicR(
int r )
523 void Pal::setEjChainDeg(
int degree )
525 this->mEjChainDeg = degree;
528 void Pal::setTenure(
int tenure )
530 this->mTenure = tenure;
533 void Pal::setCandListSize(
double fact )
535 this->mCandListSize = fact;
540 this->mShowPartialLabels = show;
545 return mPlacementVersion;
565 return mShowPartialLabels;