Skip to content
Permalink
Browse files

Don't use a spatial index to iterate over polygon rings

it's an insane approach
  • Loading branch information
nyalldawson committed Dec 27, 2019
1 parent 9af3a72 commit 12d8377f8afe01402a1bebe523e8399cef281a76
Showing with 12 additions and 24 deletions.
  1. +8 −20 src/core/pal/costcalculator.cpp
  2. +3 −3 src/core/pal/costcalculator.h
  3. +1 −1 src/core/pal/pal.cpp
@@ -107,7 +107,7 @@ void CostCalculator::addObstacleCostPenalty( LabelPosition *lp, FeaturePart *obs
lp->setCost( lp->cost() + obstacleCost );
}

void CostCalculator::calculateCandidatePolygonRingDistanceCosts( std::vector< std::unique_ptr< LabelPosition > > &lPos, PalRtree<FeaturePart> *obstacles, double bbx[4], double bby[4] )
void CostCalculator::calculateCandidatePolygonRingDistanceCosts( std::vector< std::unique_ptr< LabelPosition > > &lPos, double bbx[4], double bby[4] )
{
// first we calculate the ring distance cost for all candidates for this feature. We then use the range
// of distance costs to calculate a standardised scaling for the costs
@@ -116,7 +116,7 @@ void CostCalculator::calculateCandidatePolygonRingDistanceCosts( std::vector< st
double maxCandidateRingDistanceCost = std::numeric_limits< double >::lowest();
for ( std::unique_ptr< LabelPosition > &pos : lPos )
{
const double candidatePolygonRingDistanceCost = calculatePolygonRingDistance( pos.get(), obstacles, bbx, bby );
const double candidatePolygonRingDistanceCost = calculatePolygonRingDistance( pos.get(), bbx, bby );

minCandidateRingDistanceCost = std::min( minCandidateRingDistanceCost, candidatePolygonRingDistanceCost );
maxCandidateRingDistanceCost = std::max( maxCandidateRingDistanceCost, candidatePolygonRingDistanceCost );
@@ -140,7 +140,7 @@ void CostCalculator::calculateCandidatePolygonRingDistanceCosts( std::vector< st
}
}

double CostCalculator::calculatePolygonRingDistance( LabelPosition *candidate, PalRtree<FeaturePart> *obstacles, double bbx[4], double bby[4] )
double CostCalculator::calculatePolygonRingDistance( LabelPosition *candidate, double bbx[4], double bby[4] )
{
// TODO 1: Consider whether distance calculation should use min distance to the candidate rectangle
// instead of just the center
@@ -159,27 +159,15 @@ double CostCalculator::calculatePolygonRingDistance( LabelPosition *candidate, P
ringDistanceCalculator.addRing( &extent );

// prefer candidates which further from interior rings (holes) of the polygon
obstacles->intersects( candidate->feature->boundingBox(), [&ringDistanceCalculator, candidate]( const FeaturePart * obstacle )->bool
for ( int i = 0; i < candidate->feature->getNumSelfObstacles(); ++i )
{
// we only care about obstacles which are polygon holes, AND only holes which belong to this same feature
// because:
// 1. holes for other features are a good place to put labels for this feature
// 2. we handle obstacle avoidance for all candidate types elsewhere -- here we are solely concerned with
// ranking the relative candidates for a single feature while considering that feature's shape alone.
if ( ( obstacle == candidate->feature ) || ( !obstacle->getHoleOf() ) || ( obstacle->getHoleOf() && obstacle->getHoleOf() != candidate->feature ) )
{
return true;
}

ringDistanceCalculator.addRing( obstacle );

return true;
} );
ringDistanceCalculator.addRing( candidate->feature->getSelfObstacle( i ) );
}

return ringDistanceCalculator.minimumDistance();
}

void CostCalculator::finalizeCandidatesCosts( Feats *feat, PalRtree<FeaturePart> *obstacles, double bbx[4], double bby[4] )
void CostCalculator::finalizeCandidatesCosts( Feats *feat, double bbx[4], double bby[4] )
{
// sort candidates list, best label to worst
std::sort( feat->candidates.begin(), feat->candidates.end(), candidateSortGrow );
@@ -219,7 +207,7 @@ void CostCalculator::finalizeCandidatesCosts( Feats *feat, PalRtree<FeaturePart>
{
int arrangement = feat->feature->layer()->arrangement();
if ( arrangement == QgsPalLayerSettings::Free || arrangement == QgsPalLayerSettings::Horizontal )
calculateCandidatePolygonRingDistanceCosts( feat->candidates, obstacles, bbx, bby );
calculateCandidatePolygonRingDistanceCosts( feat->candidates, bbx, bby );
}

// add size penalty (small lines/polygons get higher cost)
@@ -44,13 +44,13 @@ namespace pal
* Updates the costs for polygon label candidates by considering the distance between the
* candidates and the nearest polygon ring (i.e. prefer labels closer to the pole of inaccessibility).
*/
static void calculateCandidatePolygonRingDistanceCosts( std::vector<std::unique_ptr<pal::LabelPosition> > &lPos, PalRtree< FeaturePart > *obstacles, double bbx[4], double bby[4] );
static void calculateCandidatePolygonRingDistanceCosts( std::vector<std::unique_ptr<pal::LabelPosition> > &lPos, double bbx[4], double bby[4] );

//! Calculates the distance between a label candidate and the closest ring for a polygon feature
static double calculatePolygonRingDistance( LabelPosition *candidate, PalRtree< FeaturePart > *obstacles, double bbx[4], double bby[4] );
static double calculatePolygonRingDistance( LabelPosition *candidate, double bbx[4], double bby[4] );

//! Sort candidates by costs, skip the worse ones, evaluate polygon candidates
static void finalizeCandidatesCosts( Feats *feat, PalRtree< FeaturePart > *obstacles, double bbx[4], double bby[4] );
static void finalizeCandidatesCosts( Feats *feat, double bbx[4], double bby[4] );

/**
* Sorts label candidates in ascending order of cost
@@ -353,7 +353,7 @@ std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeom
continue;

// calculate final costs
CostCalculator::finalizeCandidatesCosts( feat.get(), &obstacles, bbx, bby );
CostCalculator::finalizeCandidatesCosts( feat.get(), bbx, bby );

// sort candidates list, best label to worst
std::sort( feat->candidates.begin(), feat->candidates.end(), CostCalculator::candidateSortGrow );

0 comments on commit 12d8377

Please sign in to comment.
You can’t perform that action at this time.