52 delete[] chain->
label;
58 : mAllCandidatesIndex( extent )
59 , mActiveCandidatesIndex( extent )
76 bool *ok =
new bool[mTotalCandidates];
79 for ( i = 0; i < mTotalCandidates; i++ )
90 for ( i = 0; i < static_cast< int >( mFeatureCount ); i++ )
93 for ( j = 0; j < mFeatNbLp[i]; j++ )
95 if ( !ok[mFeatStartId[i] + j] )
97 if ( mLabelPositions.at( mFeatStartId[i] + j )->getNumOverlaps() == 0 )
100 ok[mFeatStartId[i] + j] =
true;
103 counter += mFeatNbLp[i] - j - 1;
105 for ( k = j + 1; k < mFeatNbLp[i]; k++ )
108 lpid = mFeatStartId[i] + k;
110 lp2 = mLabelPositions[lpid ].get();
115 mAllCandidatesIndex.intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [&lp2](
const LabelPosition * lp ) ->
bool
128 mFeatNbLp[i] = j + 1;
136 this->mTotalCandidates -= counter;
153 list.decreaseKey( lp2->getId() );
167 mSol.init( mFeatureCount );
176 for (
int i = 0; i < static_cast< int >( mFeatureCount ); i++ )
177 for (
int j = 0; j < mFeatNbLp[i]; j++ )
179 label = mFeatStartId[i] + j;
182 list.
insert( label, mLabelPositions.at( label )->getNumOverlaps() );
192 if (
pal->isCanceled() )
199 lp = mLabelPositions[ label ].get();
201 if ( lp->
getId() != label )
207 mSol.activeLabelIds[probFeatId] = label;
209 for (
int i = mFeatStartId[probFeatId]; i < mFeatStartId[probFeatId] + mFeatNbLp[probFeatId]; i++ )
211 ignoreLabel( mLabelPositions[ i ].get(), list, mAllCandidatesIndex );
217 std::vector< const LabelPosition * > conflictingPositions;
218 mAllCandidatesIndex.intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [lp, &conflictingPositions](
const LabelPosition * lp2 ) ->
bool
222 conflictingPositions.emplace_back( lp2 );
229 ignoreLabel( conflict, list, mAllCandidatesIndex );
232 mActiveCandidatesIndex.insert( lp,
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ) );
242 for ( std::size_t i = 0; i < mFeatureCount; i++ )
244 if ( mSol.activeLabelIds[i] == -1 )
246 nbOverlap = std::numeric_limits<int>::max();
247 start_p = mFeatStartId[i];
248 for ( p = 0; p < mFeatNbLp[i]; p++ )
250 lp = mLabelPositions[ start_p + p ].get();
256 mActiveCandidatesIndex.intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [&lp](
const LabelPosition * lp2 )->
bool
260 lp->incrementNumOverlaps();
271 mSol.activeLabelIds[i] = retainedLabel->
getId();
280 inline Chain *Problem::chain(
int seed )
286 double delta_best = std::numeric_limits<double>::max();
291 Chain *retainedChain =
nullptr;
293 int max_degree =
pal->mEjChainDeg;
297 QLinkedList<ElemTrans *> currentChain;
298 QLinkedList<int> conflicts;
300 std::vector< int > tmpsol( mSol.activeLabelIds );
310 seedNbLp = mFeatNbLp[seed];
311 delta_min = std::numeric_limits<double>::max();
317 if ( tmpsol[seed] == -1 )
318 delta -= mInactiveCost[seed];
320 delta -= mLabelPositions.at( tmpsol[seed] )->cost();
322 for (
int i = -1; i < seedNbLp; i++ )
327 if ( !( tmpsol[seed] == -1 && i == -1 ) && i + mFeatStartId[seed] != tmpsol[seed] )
331 lid = mFeatStartId[seed] + i;
334 lp = mLabelPositions[ lid ].get();
339 mActiveCandidatesIndex.intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [lp, &delta_tmp, &conflicts, ¤tChain,
this](
const LabelPosition * lp2 ) ->
bool
343 const int feat = lp2->getProblemFeatureId();
346 QLinkedList< ElemTrans * >::iterator cur;
347 for ( cur = currentChain.begin(); cur != currentChain.end(); ++cur )
349 if ( ( *cur )->feat == feat )
355 if ( !conflicts.contains( feat ) )
357 conflicts.append( feat );
358 delta_tmp += lp2->cost() + mInactiveCost[feat];
365 if ( conflicts.isEmpty() )
367 if ( !retainedChain || delta + lp->
cost() < delta_best )
371 delete[] retainedChain->
label;
372 delete[] retainedChain->
feat;
376 retainedChain =
new Chain();
379 delta_best = delta + lp->
cost();
381 retainedChain->
degree = currentChain.size() + 1;
382 retainedChain->
feat =
new int[retainedChain->
degree];
383 retainedChain->
label =
new int[retainedChain->
degree];
384 QLinkedList<ElemTrans *>::iterator current = currentChain.begin();
387 while ( current != currentChain.end() )
390 retainedChain->
feat[j] = move->
feat;
395 retainedChain->
feat[j] = seed;
396 retainedChain->
label[j] = lid;
397 retainedChain->
delta = delta + lp->
cost();
402 else if ( conflicts.size() == 1 )
404 if ( delta_tmp < delta_min )
406 delta_min = delta_tmp;
408 next_seed = conflicts.takeFirst();
412 conflicts.takeFirst();
420 newChain->
degree = currentChain.size() + 1 + conflicts.size();
423 QLinkedList<ElemTrans *>::iterator current = currentChain.begin();
427 while ( current != currentChain.end() )
437 newChain->
feat[j] = seed;
438 newChain->
label[j] = lid;
439 newChain->
delta = delta + mLabelPositions.at( newChain->
label[j] )->cost();
443 while ( !conflicts.isEmpty() )
445 int ftid = conflicts.takeFirst();
446 newChain->
feat[j] = ftid;
447 newChain->
label[j] = -1;
448 newChain->
delta += mInactiveCost[ftid];
452 if ( newChain->
delta < delta_best )
457 delta_best = newChain->
delta;
458 retainedChain = newChain;
469 if ( !retainedChain || delta + mInactiveCost[seed] < delta_best )
473 delete[] retainedChain->
label;
474 delete[] retainedChain->
feat;
477 retainedChain =
new Chain();
479 delta_best = delta + mInactiveCost[seed];
481 retainedChain->
degree = currentChain.size() + 1;
482 retainedChain->
feat =
new int[retainedChain->
degree];
483 retainedChain->
label =
new int[retainedChain->
degree];
484 QLinkedList<ElemTrans *>::iterator current = currentChain.begin();
487 while ( current != currentChain.end() )
490 retainedChain->
feat[j] = move->
feat;
495 retainedChain->
feat[j] = seed;
496 retainedChain->
label[j] = -1;
497 retainedChain->
delta = delta + mInactiveCost[seed];
508 if ( next_seed == -1 )
512 else if ( currentChain.size() > max_degree )
523 currentChain.append( et );
527 mLabelPositions.at( et->
old_label )->removeFromIndex( mActiveCandidatesIndex );
532 mLabelPositions.at( et->
new_label )->insertIntoIndex( mActiveCandidatesIndex );
536 tmpsol[seed] = retainedLabel;
538 delta += mLabelPositions.at( retainedLabel )->cost();
543 while ( !currentChain.isEmpty() )
545 std::unique_ptr< ElemTrans > et( currentChain.takeFirst() );
549 mLabelPositions.at( et->
new_label )->removeFromIndex( mActiveCandidatesIndex );
554 mLabelPositions.at( et->
old_label )->insertIntoIndex( mActiveCandidatesIndex );
558 return retainedChain;
562 void Problem::chain_search()
564 if ( mFeatureCount == 0 )
569 bool *ok =
new bool[mFeatureCount];
574 Chain *retainedChain =
nullptr;
576 std::fill( ok, ok + mFeatureCount,
false );
594 for ( seed = ( iter + 1 ) % mFeatureCount;
595 ok[seed] && seed != iter;
596 seed = ( seed + 1 ) % mFeatureCount )
605 iter = ( iter + 1 ) % mFeatureCount;
606 retainedChain = chain( seed );
608 if ( retainedChain && retainedChain->
delta < -
EPSILON )
611 for ( i = 0; i < retainedChain->
degree; i++ )
613 fid = retainedChain->
feat[i];
614 lid = retainedChain->
label[i];
616 if ( mSol.activeLabelIds[fid] >= 0 )
618 LabelPosition *old = mLabelPositions[ mSol.activeLabelIds[fid] ].get();
621 mAllCandidatesIndex.intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [&ok, old](
const LabelPosition * lp ) ->
bool
625 ok[lp->getProblemFeatureId()] = false;
632 mSol.activeLabelIds[fid] = lid;
634 if ( mSol.activeLabelIds[fid] >= 0 )
636 mLabelPositions.at( lid )->insertIntoIndex( mActiveCandidatesIndex );
641 mSol.totalCost += retainedChain->
delta;
659 QList<LabelPosition *> finalLabelPlacements;
662 for ( std::size_t i = 0; i < mFeatureCount; i++ )
664 const int labelId = mSol.activeLabelIds[i];
665 const bool foundNonOverlappingPlacement = labelId != -1;
666 const int startIndexForLabelPlacements = mFeatStartId[i];
667 const bool foundCandidatesForFeature = startIndexForLabelPlacements < static_cast< int >( mLabelPositions.size() );
669 if ( foundNonOverlappingPlacement )
671 finalLabelPlacements.push_back( mLabelPositions[ labelId ].get() );
673 else if ( foundCandidatesForFeature &&
675 || mLabelPositions.at( startIndexForLabelPlacements )->getFeaturePart()->layer()->displayAll()
676 || mLabelPositions.at( startIndexForLabelPlacements )->getFeaturePart()->alwaysShow() ) )
678 finalLabelPlacements.push_back( mLabelPositions[ startIndexForLabelPlacements ].get() );
680 else if ( unlabeled )
683 if ( foundCandidatesForFeature && ( i == mFeatureCount - 1 || startIndexForLabelPlacements != mFeatStartId[i + 1] ) )
684 unlabeled->push_back( mLabelPositions[ startIndexForLabelPlacements ].get() );
691 for (
const std::unique_ptr< LabelPosition > &position : mPositionsWithNoCandidates )
692 unlabeled->append( position.get() );
695 return finalLabelPlacements;
698 void Problem::solution_cost()
700 mSol.totalCost = 0.0;
707 for ( std::size_t i = 0; i < mFeatureCount; i++ )
709 if ( mSol.activeLabelIds[i] == -1 )
711 mSol.totalCost += mInactiveCost[i];
715 lp = mLabelPositions[ mSol.activeLabelIds[i] ].get();
718 mActiveCandidatesIndex.intersects(
QgsRectangle( amin[0], amin[1], amax[0], amax[1] ), [&lp,
this](
const LabelPosition * lp2 )->
bool
722 mSol.totalCost += mInactiveCost[lp2->getProblemFeatureId()] + lp2->cost();
728 mSol.totalCost += lp->
cost();