mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-12 00:02:25 -04:00
More pal modernization of memory management, finally ownership is starting to become clear...
This commit is contained in:
parent
b0f4cb45cc
commit
077c507207
@ -25,12 +25,12 @@
|
||||
|
||||
using namespace pal;
|
||||
|
||||
bool CostCalculator::candidateSortGrow( const LabelPosition *c1, const LabelPosition *c2 )
|
||||
bool CostCalculator::candidateSortGrow( const std::unique_ptr< LabelPosition > &c1, const std::unique_ptr< LabelPosition > &c2 )
|
||||
{
|
||||
return c1->cost() < c2->cost();
|
||||
}
|
||||
|
||||
bool CostCalculator::candidateSortShrink( const LabelPosition *c1, const LabelPosition *c2 )
|
||||
bool CostCalculator::candidateSortShrink( const std::unique_ptr< LabelPosition > &c1, const std::unique_ptr< LabelPosition > &c2 )
|
||||
{
|
||||
return c1->cost() > c2->cost();
|
||||
}
|
||||
@ -93,31 +93,21 @@ void CostCalculator::addObstacleCostPenalty( LabelPosition *lp, FeaturePart *obs
|
||||
lp->setCost( lp->cost() + obstacleCost );
|
||||
}
|
||||
|
||||
void CostCalculator::setPolygonCandidatesCost( int nblp, QList< LabelPosition * > &lPos, RTree<FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] )
|
||||
void CostCalculator::setPolygonCandidatesCost( std::size_t nblp, std::vector< std::unique_ptr< LabelPosition > > &lPos, RTree<FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] )
|
||||
{
|
||||
double normalizer;
|
||||
// compute raw cost
|
||||
for ( int i = 0; i < nblp; ++i )
|
||||
setCandidateCostFromPolygon( lPos.at( i ), obstacles, bbx, bby );
|
||||
for ( std::size_t i = 0; i < nblp; ++i )
|
||||
setCandidateCostFromPolygon( lPos[ i ].get(), obstacles, bbx, bby );
|
||||
|
||||
// lPos with big values came first (value = min distance from label to Polygon's Perimeter)
|
||||
// IMPORTANT - only want to sort first nblp positions. The rest have not had the cost
|
||||
// calculated so will have nonsense values
|
||||
QList< LabelPosition * > toSort;
|
||||
toSort.reserve( nblp );
|
||||
for ( int i = 0; i < nblp; ++i )
|
||||
{
|
||||
toSort << lPos.at( i );
|
||||
}
|
||||
std::sort( toSort.begin(), toSort.end(), candidateSortShrink );
|
||||
for ( int i = 0; i < nblp; ++i )
|
||||
{
|
||||
lPos[i] = toSort.at( i );
|
||||
}
|
||||
std::sort( lPos.begin(), lPos.begin() + nblp, candidateSortShrink );
|
||||
|
||||
// define the value's range
|
||||
double cost_max = lPos.at( 0 )->cost();
|
||||
double cost_min = lPos.at( nblp - 1 )->cost();
|
||||
double cost_max = lPos.front()->cost();
|
||||
double cost_min = lPos.back()->cost();
|
||||
|
||||
cost_max -= cost_min;
|
||||
|
||||
@ -132,17 +122,18 @@ void CostCalculator::setPolygonCandidatesCost( int nblp, QList< LabelPosition *
|
||||
|
||||
// adjust cost => the best is 0.0001, the worst is 0.0021
|
||||
// others are set proportionally between best and worst
|
||||
for ( int i = 0; i < nblp; ++i )
|
||||
for ( std::size_t i = 0; i < nblp; ++i )
|
||||
{
|
||||
LabelPosition *pos = lPos[ i ].get();
|
||||
//if (cost_max - cost_min < EPSILON)
|
||||
if ( cost_max > EPSILON )
|
||||
{
|
||||
lPos.at( i )->setCost( 0.0021 - ( lPos.at( i )->cost() - cost_min ) * normalizer );
|
||||
pos->setCost( 0.0021 - ( pos->cost() - cost_min ) * normalizer );
|
||||
}
|
||||
else
|
||||
{
|
||||
//lPos[i]->cost = 0.0001 + (lPos[i]->cost - cost_min) * normalizer;
|
||||
lPos.at( i )->setCost( 0.0001 );
|
||||
//pos->cost = 0.0001 + (pos->cost - cost_min) * normalizer;
|
||||
pos->setCost( 0.0001 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,31 +165,30 @@ void CostCalculator::setCandidateCostFromPolygon( LabelPosition *lp, RTree <Feat
|
||||
delete pCost;
|
||||
}
|
||||
|
||||
int CostCalculator::finalizeCandidatesCosts( Feats *feat, int max_p, RTree <FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] )
|
||||
std::size_t CostCalculator::finalizeCandidatesCosts( Feats *feat, std::size_t max_p, RTree <FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] )
|
||||
{
|
||||
// If candidates list is smaller than expected
|
||||
if ( max_p > feat->candidates.count() )
|
||||
max_p = feat->candidates.count();
|
||||
if ( max_p > feat->candidates.size() )
|
||||
max_p = feat->candidates.size();
|
||||
//
|
||||
// sort candidates list, best label to worst
|
||||
std::sort( feat->candidates.begin(), feat->candidates.end(), candidateSortGrow );
|
||||
|
||||
// try to exclude all conflitual labels (good ones have cost < 1 by pruning)
|
||||
double discrim = 0.0;
|
||||
int stop;
|
||||
std::size_t stop = 0;
|
||||
do
|
||||
{
|
||||
discrim += 1.0;
|
||||
for ( stop = 0; stop < feat->candidates.count() && feat->candidates.at( stop )->cost() < discrim; stop++ )
|
||||
for ( stop = 0; stop < feat->candidates.size() && feat->candidates[ stop ]->cost() < discrim; stop++ )
|
||||
;
|
||||
}
|
||||
while ( stop == 0 && discrim < feat->candidates.last()->cost() + 2.0 );
|
||||
while ( stop == 0 && discrim < feat->candidates.back()->cost() + 2.0 );
|
||||
|
||||
if ( discrim > 1.5 )
|
||||
{
|
||||
int k;
|
||||
for ( k = 0; k < stop; k++ )
|
||||
feat->candidates.at( k )->setCost( 0.0021 );
|
||||
for ( std::size_t k = 0; k < stop; k++ )
|
||||
feat->candidates[ k ]->setCost( 0.0021 );
|
||||
}
|
||||
|
||||
if ( max_p > stop )
|
||||
|
@ -28,6 +28,7 @@
|
||||
namespace pal
|
||||
{
|
||||
class Feats;
|
||||
class LabelPosition;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
@ -38,23 +39,23 @@ namespace pal
|
||||
//! Increase candidate's cost according to its collision with passed feature
|
||||
static void addObstacleCostPenalty( LabelPosition *lp, pal::FeaturePart *obstacle );
|
||||
|
||||
static void setPolygonCandidatesCost( int nblp, QList< LabelPosition * > &lPos, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );
|
||||
static void setPolygonCandidatesCost( std::size_t nblp, std::vector<std::unique_ptr<pal::LabelPosition> > &lPos, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );
|
||||
|
||||
//! Sets cost to the smallest distance between lPos's centroid and a polygon stored in geoetry field
|
||||
static void setCandidateCostFromPolygon( LabelPosition *lp, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );
|
||||
|
||||
//! Sort candidates by costs, skip the worse ones, evaluate polygon candidates
|
||||
static int finalizeCandidatesCosts( Feats *feat, int max_p, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );
|
||||
static std::size_t finalizeCandidatesCosts( Feats *feat, std::size_t max_p, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );
|
||||
|
||||
/**
|
||||
* Sorts label candidates in ascending order of cost
|
||||
*/
|
||||
static bool candidateSortGrow( const LabelPosition *c1, const LabelPosition *c2 );
|
||||
static bool candidateSortGrow( const std::unique_ptr<pal::LabelPosition> &c1, const std::unique_ptr<pal::LabelPosition> &c2 );
|
||||
|
||||
/**
|
||||
* Sorts label candidates in descending order of cost
|
||||
*/
|
||||
static bool candidateSortShrink( const LabelPosition *c1, const LabelPosition *c2 );
|
||||
static bool candidateSortShrink( const std::unique_ptr<pal::LabelPosition> &c1, const std::unique_ptr<pal::LabelPosition> &c2 );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -235,9 +235,9 @@ void FeaturePart::setTotalRepeats( int totalRepeats )
|
||||
mTotalRepeats = totalRepeats;
|
||||
}
|
||||
|
||||
int FeaturePart::createCandidatesOverPoint( double x, double y, QList< LabelPosition *> &lPos, double angle )
|
||||
std::size_t FeaturePart::createCandidatesOverPoint( double x, double y, std::vector< std::unique_ptr< LabelPosition > > &lPos, double angle )
|
||||
{
|
||||
int nbp = 1;
|
||||
std::size_t nbp = 1;
|
||||
|
||||
// get from feature
|
||||
double labelW = getLabelWidth( angle );
|
||||
@ -310,7 +310,7 @@ int FeaturePart::createCandidatesOverPoint( double x, double y, QList< LabelPosi
|
||||
}
|
||||
}
|
||||
|
||||
lPos << new LabelPosition( id, lx, ly, labelW, labelH, angle, cost, this, false, quadrantFromOffset() );
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( id, lx, ly, labelW, labelH, angle, cost, this, false, quadrantFromOffset() ) );
|
||||
return nbp;
|
||||
}
|
||||
|
||||
@ -341,7 +341,7 @@ std::unique_ptr<LabelPosition> FeaturePart::createCandidatePointOnSurface( Point
|
||||
return qgis::make_unique< LabelPosition >( 0, px, py, getLabelWidth(), getLabelHeight(), 0.0, 0.0, this );
|
||||
}
|
||||
|
||||
int FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y, QList<LabelPosition *> &lPos, double angle )
|
||||
std::size_t FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y, std::vector< std::unique_ptr< LabelPosition > > &lPos, double angle )
|
||||
{
|
||||
QVector< QgsPalLayerSettings::PredefinedPointPosition > positions = mLF->predefinedPositionOrder();
|
||||
double labelWidth = getLabelWidth( angle );
|
||||
@ -356,7 +356,7 @@ int FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y
|
||||
int i = 0;
|
||||
const auto constPositions = positions;
|
||||
|
||||
const int maxNumberCandidates = mLF->layer()->maximumPointLabelCandidates();
|
||||
const std::size_t maxNumberCandidates = mLF->layer()->maximumPointLabelCandidates();
|
||||
for ( QgsPalLayerSettings::PredefinedPointPosition position : constPositions )
|
||||
{
|
||||
double alpha = 0.0;
|
||||
@ -459,7 +459,7 @@ int FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y
|
||||
|
||||
if ( ! mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), labelX, labelY, labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
lPos << new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this, false, quadrant );
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this, false, quadrant ) );
|
||||
//TODO - tweak
|
||||
cost += 0.001;
|
||||
if ( lPos.size() >= maxNumberCandidates )
|
||||
@ -468,16 +468,16 @@ int FeaturePart::createCandidatesAtOrderedPositionsOverPoint( double x, double y
|
||||
++i;
|
||||
}
|
||||
|
||||
return lPos.count();
|
||||
return lPos.size();
|
||||
}
|
||||
|
||||
int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPosition * > &lPos, double angle )
|
||||
std::size_t FeaturePart::createCandidatesAroundPoint( double x, double y, std::vector< std::unique_ptr< LabelPosition > > &lPos, double angle )
|
||||
{
|
||||
double labelWidth = getLabelWidth( angle );
|
||||
double labelHeight = getLabelHeight( angle );
|
||||
double distanceToLabel = getLabelDistance();
|
||||
|
||||
const int maxNumberCandidates = mLF->layer()->maximumPointLabelCandidates();
|
||||
const std::size_t maxNumberCandidates = mLF->layer()->maximumPointLabelCandidates();
|
||||
|
||||
int icost = 0;
|
||||
int inc = 2;
|
||||
@ -508,9 +508,9 @@ int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPo
|
||||
if ( gamma2 > a90 / 3.0 )
|
||||
gamma2 = a90 / 3.0;
|
||||
|
||||
QList< LabelPosition * > candidates;
|
||||
std::size_t numberCandidatesGenerated = 0;
|
||||
|
||||
int i;
|
||||
std::size_t i;
|
||||
double angleToCandidate;
|
||||
for ( i = 0, angleToCandidate = M_PI_4; i < maxNumberCandidates; i++, angleToCandidate += candidateAngleIncrement )
|
||||
{
|
||||
@ -596,35 +596,28 @@ int FeaturePart::createCandidatesAroundPoint( double x, double y, QList< LabelPo
|
||||
}
|
||||
}
|
||||
|
||||
candidates << new LabelPosition( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this, false, quadrant );
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, labelX, labelY, labelWidth, labelHeight, angle, cost, this, false, quadrant ) );
|
||||
numberCandidatesGenerated++;
|
||||
|
||||
icost += inc;
|
||||
|
||||
if ( icost == maxNumberCandidates )
|
||||
if ( icost == static_cast< int >( maxNumberCandidates ) )
|
||||
{
|
||||
icost = maxNumberCandidates - 1;
|
||||
icost = static_cast< int >( maxNumberCandidates ) - 1;
|
||||
inc = -2;
|
||||
}
|
||||
else if ( icost > maxNumberCandidates )
|
||||
else if ( icost > static_cast< int >( maxNumberCandidates ) )
|
||||
{
|
||||
icost = maxNumberCandidates - 2;
|
||||
icost = static_cast< int >( maxNumberCandidates ) - 2;
|
||||
inc = -2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !candidates.isEmpty() )
|
||||
{
|
||||
for ( int i = 0; i < candidates.count(); ++i )
|
||||
{
|
||||
lPos << candidates.at( i );
|
||||
}
|
||||
}
|
||||
|
||||
return candidates.count();
|
||||
return numberCandidatesGenerated;
|
||||
}
|
||||
|
||||
int FeaturePart::createCandidatesAlongLine( QList< LabelPosition * > &lPos, PointSet *mapShape, bool allowOverrun )
|
||||
std::size_t FeaturePart::createCandidatesAlongLine( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape, bool allowOverrun )
|
||||
{
|
||||
if ( allowOverrun )
|
||||
{
|
||||
@ -639,9 +632,9 @@ int FeaturePart::createCandidatesAlongLine( QList< LabelPosition * > &lPos, Poin
|
||||
}
|
||||
|
||||
//prefer to label along straightish segments:
|
||||
int candidates = createCandidatesAlongLineNearStraightSegments( lPos, mapShape );
|
||||
std::size_t candidates = createCandidatesAlongLineNearStraightSegments( lPos, mapShape );
|
||||
|
||||
if ( candidates < mLF->layer()->maximumLineLabelCandidates() )
|
||||
if ( static_cast< int >( candidates ) < mLF->layer()->maximumLineLabelCandidates() )
|
||||
{
|
||||
// but not enough candidates yet, so fallback to labeling near whole line's midpoint
|
||||
candidates = createCandidatesAlongLineNearMidpoint( lPos, mapShape, candidates > 0 ? 0.01 : 0.0 );
|
||||
@ -649,7 +642,7 @@ int FeaturePart::createCandidatesAlongLine( QList< LabelPosition * > &lPos, Poin
|
||||
return candidates;
|
||||
}
|
||||
|
||||
int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosition *> &lPos, PointSet *mapShape )
|
||||
std::size_t FeaturePart::createCandidatesAlongLineNearStraightSegments( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape )
|
||||
{
|
||||
double labelWidth = getLabelWidth();
|
||||
double labelHeight = getLabelHeight();
|
||||
@ -835,7 +828,7 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
const double candidateCost = cost + ( reversed ? 0 : 0.001 );
|
||||
lPos.append( new LabelPosition( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( aboveLine )
|
||||
@ -843,7 +836,7 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
const double candidateCost = cost + ( !reversed ? 0 : 0.001 ); // no extra cost for above line placements
|
||||
lPos.append( new LabelPosition( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( flags & FLAG_ON_LINE )
|
||||
@ -851,13 +844,13 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
const double candidateCost = cost + 0.002;
|
||||
lPos.append( new LabelPosition( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
|
||||
{
|
||||
lPos.append( new LabelPosition( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost, this ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost, this ) ); // Line
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -873,7 +866,7 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
|
||||
return lPos.size();
|
||||
}
|
||||
|
||||
int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &lPos, PointSet *mapShape, double initialCost )
|
||||
std::size_t FeaturePart::createCandidatesAlongLineNearMidpoint( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape, double initialCost )
|
||||
{
|
||||
double distanceLineToLabel = getLabelDistance();
|
||||
|
||||
@ -887,8 +880,6 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &
|
||||
if ( flags == 0 )
|
||||
flags = FLAG_ON_LINE; // default flag
|
||||
|
||||
QList<LabelPosition *> positions;
|
||||
|
||||
PointSet *line = mapShape;
|
||||
int nbPoints = line->nbPoints;
|
||||
std::vector< double > &x = line->x;
|
||||
@ -989,7 +980,7 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
const double candidateCost = cost + ( !reversed ? 0 : 0.001 ); // no extra cost for above line placements
|
||||
positions.append( new LabelPosition( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( belowLine )
|
||||
@ -997,7 +988,7 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
const double candidateCost = cost + ( !reversed ? 0.001 : 0 );
|
||||
positions.append( new LabelPosition( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( flags & FLAG_ON_LINE )
|
||||
@ -1005,13 +996,13 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
const double candidateCost = cost + 0.002;
|
||||
positions.append( new LabelPosition( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
|
||||
{
|
||||
positions.append( new LabelPosition( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost, this ) ); // Line
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( i, candidateStartX - labelWidth / 2, candidateStartY - labelHeight / 2, labelWidth, labelHeight, 0, cost, this ) ); // Line
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1031,7 +1022,6 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &
|
||||
delete[] segmentLengths;
|
||||
delete[] distanceToSegment;
|
||||
|
||||
lPos.append( positions );
|
||||
return lPos.size();
|
||||
}
|
||||
|
||||
@ -1212,7 +1202,7 @@ static LabelPosition *_createCurvedCandidate( LabelPosition *lp, double angle, d
|
||||
return newLp;
|
||||
}
|
||||
|
||||
int FeaturePart::createCurvedCandidatesAlongLine( QList< LabelPosition * > &lPos, PointSet *mapShape, bool allowOverrun )
|
||||
std::size_t FeaturePart::createCurvedCandidatesAlongLine( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape, bool allowOverrun )
|
||||
{
|
||||
LabelInfo *li = mLF->curvedLabelInfo();
|
||||
|
||||
@ -1391,10 +1381,10 @@ int FeaturePart::createCurvedCandidatesAlongLine( QList< LabelPosition * > &lPos
|
||||
delete slp;
|
||||
}
|
||||
|
||||
int nbp = positions.size();
|
||||
for ( int i = 0; i < nbp; i++ )
|
||||
std::size_t nbp = positions.size();
|
||||
for ( std::size_t i = 0; i < nbp; i++ )
|
||||
{
|
||||
lPos << positions.takeFirst();
|
||||
lPos.emplace_back( std::unique_ptr< LabelPosition >( positions.takeFirst() ) );
|
||||
}
|
||||
|
||||
return nbp;
|
||||
@ -1412,9 +1402,8 @@ int FeaturePart::createCurvedCandidatesAlongLine( QList< LabelPosition * > &lPos
|
||||
*
|
||||
*/
|
||||
|
||||
int FeaturePart::createCandidatesForPolygon( QList< LabelPosition *> &lPos, PointSet *mapShape )
|
||||
std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape )
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
double labelWidth = getLabelWidth();
|
||||
@ -1429,12 +1418,10 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition *> &lPos, Poin
|
||||
|
||||
splitPolygons( shapes_toProcess, shapes_final, labelWidth, labelHeight );
|
||||
|
||||
int nbp;
|
||||
std::size_t nbp = 0;
|
||||
|
||||
if ( !shapes_final.isEmpty() )
|
||||
{
|
||||
QLinkedList<LabelPosition *> positions;
|
||||
|
||||
int id = 0; // ids for candidates
|
||||
double dlx, dly; // delta from label center and bottom-left corner
|
||||
double alpha = 0.0; // rotation for the label
|
||||
@ -1470,6 +1457,8 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition *> &lPos, Poin
|
||||
//then use a smaller limit for number of iterations
|
||||
int maxTry = mLF->permissibleZonePrepared() ? 7 : 10;
|
||||
|
||||
std::size_t numberCandidatesGenerated = 0;
|
||||
|
||||
do
|
||||
{
|
||||
for ( bbid = 0; bbid < j; bbid++ )
|
||||
@ -1580,13 +1569,14 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition *> &lPos, Poin
|
||||
if ( candidateAcceptable )
|
||||
{
|
||||
// cost is set to minimal value, evaluated later
|
||||
positions.append( new LabelPosition( id++, rx - dlx, ry - dly, labelWidth, labelHeight, alpha, 0.0001, this ) ); // Polygon
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition >( id++, rx - dlx, ry - dly, labelWidth, labelHeight, alpha, 0.0001, this ) ); // Polygon
|
||||
numberCandidatesGenerated++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // forall box
|
||||
|
||||
nbp = positions.size();
|
||||
nbp = numberCandidatesGenerated;
|
||||
if ( nbp == 0 )
|
||||
{
|
||||
dx /= 2;
|
||||
@ -1596,12 +1586,7 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition *> &lPos, Poin
|
||||
}
|
||||
while ( nbp == 0 && numTry < maxTry );
|
||||
|
||||
nbp = positions.size();
|
||||
|
||||
for ( i = 0; i < nbp; i++ )
|
||||
{
|
||||
lPos << positions.takeFirst();
|
||||
}
|
||||
nbp = numberCandidatesGenerated;
|
||||
|
||||
for ( bbid = 0; bbid < j; bbid++ )
|
||||
{
|
||||
@ -1618,14 +1603,14 @@ int FeaturePart::createCandidatesForPolygon( QList< LabelPosition *> &lPos, Poin
|
||||
return nbp;
|
||||
}
|
||||
|
||||
QList<LabelPosition *> FeaturePart::createCandidates()
|
||||
std::vector< std::unique_ptr< LabelPosition > > FeaturePart::createCandidates()
|
||||
{
|
||||
QList<LabelPosition *> lPos;
|
||||
std::vector< std::unique_ptr< LabelPosition > > lPos;
|
||||
double angle = mLF->hasFixedAngle() ? mLF->fixedAngle() : 0.0;
|
||||
|
||||
if ( mLF->hasFixedPosition() )
|
||||
{
|
||||
lPos << new LabelPosition( 0, mLF->fixedPosition().x(), mLF->fixedPosition().y(), getLabelWidth( angle ), getLabelHeight( angle ), angle, 0.0, this );
|
||||
lPos.emplace_back( qgis::make_unique< LabelPosition> ( 0, mLF->fixedPosition().x(), mLF->fixedPosition().y(), getLabelWidth( angle ), getLabelHeight( angle ), angle, 0.0, this ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1674,7 +1659,7 @@ QList<LabelPosition *> FeaturePart::createCandidates()
|
||||
return lPos;
|
||||
}
|
||||
|
||||
void FeaturePart::addSizePenalty( int nbp, QList< LabelPosition * > &lPos, double bbx[4], double bby[4] )
|
||||
void FeaturePart::addSizePenalty( std::size_t nbp, std::vector< std::unique_ptr< LabelPosition > > &lPos, double bbx[4], double bby[4] )
|
||||
{
|
||||
if ( !mGeos )
|
||||
createGeosGeom();
|
||||
@ -1725,9 +1710,10 @@ void FeaturePart::addSizePenalty( int nbp, QList< LabelPosition * > &lPos, doubl
|
||||
return; // no size penalty for points
|
||||
|
||||
// apply the penalty
|
||||
for ( int i = 0; i < nbp; i++ )
|
||||
for ( std::size_t i = 0; i < nbp; i++ )
|
||||
{
|
||||
lPos.at( i )->setCost( lPos.at( i )->cost() + sizeCost / 100 );
|
||||
LabelPosition *pos = lPos[ i ].get();
|
||||
pos->setCost( pos->cost() + sizeCost / 100 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ namespace pal
|
||||
/**
|
||||
* Generates a list of candidate positions for labels for this feature.
|
||||
*/
|
||||
QList<LabelPosition *> createCandidates();
|
||||
std::vector<std::unique_ptr<LabelPosition> > createCandidates();
|
||||
|
||||
/**
|
||||
* Generate candidates for point feature, located around a specified point.
|
||||
@ -140,7 +140,7 @@ namespace pal
|
||||
* \param angle orientation of the label
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCandidatesAroundPoint( double x, double y, QList<LabelPosition *> &lPos, double angle );
|
||||
std::size_t createCandidatesAroundPoint( double x, double y, std::vector<std::unique_ptr<LabelPosition> > &lPos, double angle );
|
||||
|
||||
/**
|
||||
* Generate one candidate over or offset the specified point.
|
||||
@ -150,7 +150,7 @@ namespace pal
|
||||
* \param angle orientation of the label
|
||||
* \returns the number of generated candidates (always 1)
|
||||
*/
|
||||
int createCandidatesOverPoint( double x, double y, QList<LabelPosition *> &lPos, double angle );
|
||||
std::size_t createCandidatesOverPoint( double x, double y, std::vector<std::unique_ptr<LabelPosition> > &lPos, double angle );
|
||||
|
||||
/**
|
||||
* Creates a single candidate using the "point on sruface" algorithm.
|
||||
@ -168,7 +168,7 @@ namespace pal
|
||||
* \param angle orientation of the label
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCandidatesAtOrderedPositionsOverPoint( double x, double y, QList<LabelPosition *> &lPos, double angle );
|
||||
std::size_t createCandidatesAtOrderedPositionsOverPoint( double x, double y, std::vector<std::unique_ptr<LabelPosition> > &lPos, double angle );
|
||||
|
||||
/**
|
||||
* Generate candidates for line feature.
|
||||
@ -177,7 +177,7 @@ namespace pal
|
||||
* \param allowOverrun set to TRUE to allow labels to overrun features
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCandidatesAlongLine( QList<LabelPosition *> &lPos, PointSet *mapShape, bool allowOverrun = false );
|
||||
std::size_t createCandidatesAlongLine( std::vector<std::unique_ptr<LabelPosition> > &lPos, PointSet *mapShape, bool allowOverrun = false );
|
||||
|
||||
/**
|
||||
* Generate candidates for line feature, by trying to place candidates towards the middle of the longest
|
||||
@ -186,7 +186,7 @@ namespace pal
|
||||
* \param mapShape a pointer to the line
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCandidatesAlongLineNearStraightSegments( QList<LabelPosition *> &lPos, PointSet *mapShape );
|
||||
std::size_t createCandidatesAlongLineNearStraightSegments( std::vector<std::unique_ptr<LabelPosition> > &lPos, PointSet *mapShape );
|
||||
|
||||
/**
|
||||
* Generate candidates for line feature, by trying to place candidates as close as possible to the line's midpoint.
|
||||
@ -197,7 +197,7 @@ namespace pal
|
||||
* by a preset amount.
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &lPos, PointSet *mapShape, double initialCost = 0.0 );
|
||||
std::size_t createCandidatesAlongLineNearMidpoint( std::vector<std::unique_ptr<LabelPosition> > &lPos, PointSet *mapShape, double initialCost = 0.0 );
|
||||
|
||||
/**
|
||||
* Returns the label position for a curved label at a specific offset along a path.
|
||||
@ -219,7 +219,7 @@ namespace pal
|
||||
* \param allowOverrun set to TRUE to allow labels to overrun features
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCurvedCandidatesAlongLine( QList<LabelPosition *> &lPos, PointSet *mapShape, bool allowOverrun = false );
|
||||
std::size_t createCurvedCandidatesAlongLine( std::vector<std::unique_ptr<LabelPosition> > &lPos, PointSet *mapShape, bool allowOverrun = false );
|
||||
|
||||
/**
|
||||
* Generate candidates for polygon features.
|
||||
@ -227,7 +227,7 @@ namespace pal
|
||||
* \param mapShape a pointer to the polygon
|
||||
* \returns the number of generated candidates
|
||||
*/
|
||||
int createCandidatesForPolygon( QList<LabelPosition *> &lPos, PointSet *mapShape );
|
||||
std::size_t createCandidatesForPolygon( std::vector<std::unique_ptr<LabelPosition> > &lPos, PointSet *mapShape );
|
||||
|
||||
/**
|
||||
* Tests whether this feature part belongs to the same QgsLabelFeature as another
|
||||
@ -304,7 +304,7 @@ namespace pal
|
||||
* Returns TRUE on success, FALSE if the feature wasn't modified */
|
||||
bool mergeWithFeaturePart( FeaturePart *other );
|
||||
|
||||
void addSizePenalty( int nbp, QList<LabelPosition *> &lPos, double bbx[4], double bby[4] );
|
||||
void addSizePenalty( std::size_t nbp, std::vector<std::unique_ptr<LabelPosition> > &lPos, double bbx[4], double bby[4] );
|
||||
|
||||
/**
|
||||
* Calculates the priority for the feature. This will be the feature's priority if set,
|
||||
|
@ -92,7 +92,7 @@ Layer *Pal::addLayer( QgsAbstractLabelProvider *provider, const QString &layerNa
|
||||
return layer;
|
||||
}
|
||||
|
||||
typedef struct _featCbackCtx
|
||||
struct FeatCallBackCtx
|
||||
{
|
||||
Layer *layer = nullptr;
|
||||
|
||||
@ -103,7 +103,7 @@ typedef struct _featCbackCtx
|
||||
QList<LabelPosition *> *positionsWithNoCandidates;
|
||||
const GEOSPreparedGeometry *mapBoundary = nullptr;
|
||||
Pal *pal = nullptr;
|
||||
} FeatCallBackCtx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -130,40 +130,31 @@ bool extractFeatCallback( FeaturePart *featurePart, void *ctx )
|
||||
}
|
||||
|
||||
// generate candidates for the feature part
|
||||
QList< LabelPosition * > candidates = featurePart->createCandidates();
|
||||
std::vector< std::unique_ptr< LabelPosition > > candidates = featurePart->createCandidates();
|
||||
|
||||
// purge candidates that are outside the bbox
|
||||
|
||||
QMutableListIterator< LabelPosition *> i( candidates );
|
||||
while ( i.hasNext() )
|
||||
candidates.erase( std::remove_if( candidates.begin(), candidates.end(), [&context]( std::unique_ptr< LabelPosition > &candidate )
|
||||
{
|
||||
LabelPosition *pos = i.next();
|
||||
bool outside = false;
|
||||
|
||||
if ( context->pal->getShowPartial() )
|
||||
outside = !pos->intersects( context->mapBoundary );
|
||||
return !candidate->intersects( context->mapBoundary );
|
||||
else
|
||||
outside = !pos->within( context->mapBoundary );
|
||||
if ( outside )
|
||||
{
|
||||
i.remove();
|
||||
delete pos;
|
||||
}
|
||||
else // this one is OK
|
||||
{
|
||||
pos->insertIntoIndex( context->candidates );
|
||||
}
|
||||
}
|
||||
return !candidate->within( context->mapBoundary );
|
||||
} ), candidates.end() );
|
||||
|
||||
if ( !candidates.empty() )
|
||||
{
|
||||
for ( std::unique_ptr< LabelPosition > &candidate : candidates )
|
||||
{
|
||||
candidate->insertIntoIndex( context->candidates );
|
||||
}
|
||||
|
||||
std::sort( candidates.begin(), candidates.end(), CostCalculator::candidateSortGrow );
|
||||
|
||||
// valid features are added to fFeats
|
||||
std::unique_ptr< Feats > ft = qgis::make_unique< Feats >();
|
||||
ft->feature = featurePart;
|
||||
ft->shape = nullptr;
|
||||
ft->candidates = candidates;
|
||||
ft->candidates = std::move( candidates );
|
||||
ft->priority = featurePart->calculatePriority();
|
||||
context->fFeats->emplace_back( std::move( ft ) );
|
||||
}
|
||||
@ -233,17 +224,13 @@ std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeom
|
||||
RTree<FeaturePart *, double, 2, double> obstacles;
|
||||
std::unique_ptr< Problem > prob = qgis::make_unique< Problem >();
|
||||
|
||||
int j;
|
||||
|
||||
double bbx[4];
|
||||
double bby[4];
|
||||
|
||||
double amin[2];
|
||||
double amax[2];
|
||||
|
||||
int max_p = 0;
|
||||
|
||||
LabelPosition *lp = nullptr;
|
||||
std::size_t max_p = 0;
|
||||
|
||||
bbx[0] = bbx[3] = amin[0] = prob->bbox[0] = extent.xMinimum();
|
||||
bby[0] = bby[1] = amin[1] = prob->bbox[1] = extent.yMinimum();
|
||||
@ -338,12 +325,6 @@ std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeom
|
||||
|
||||
if ( isCanceled() )
|
||||
{
|
||||
for ( const std::unique_ptr< Feats > &feat : qgis::as_const( fFeats ) )
|
||||
{
|
||||
qDeleteAll( feat->candidates );
|
||||
feat->candidates.clear();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -373,23 +354,22 @@ std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeom
|
||||
max_p = CostCalculator::finalizeCandidatesCosts( feat.get(), max_p, &obstacles, bbx, bby );
|
||||
|
||||
// only keep the 'max_p' best candidates
|
||||
while ( feat->candidates.count() > max_p )
|
||||
while ( feat->candidates.size() > max_p )
|
||||
{
|
||||
// TODO remove from index
|
||||
feat->candidates.constLast()->removeFromIndex( prob->candidates );
|
||||
delete feat->candidates.takeLast();
|
||||
feat->candidates.back()->removeFromIndex( prob->candidates );
|
||||
feat->candidates.pop_back();
|
||||
}
|
||||
|
||||
// update problem's # candidate
|
||||
prob->featNbLp[i] = feat->candidates.count();
|
||||
prob->mTotalCandidates += feat->candidates.count();
|
||||
prob->featNbLp[i] = static_cast< int >( feat->candidates.size() );
|
||||
prob->mTotalCandidates += static_cast< int >( feat->candidates.size() );
|
||||
|
||||
// add all candidates into a rtree (to speed up conflicts searching)
|
||||
for ( j = 0; j < feat->candidates.count(); j++, idlp++ )
|
||||
for ( std::size_t j = 0; j < feat->candidates.size(); j++, idlp++ )
|
||||
{
|
||||
lp = feat->candidates.at( j );
|
||||
//lp->insertIntoIndex(prob->candidates);
|
||||
lp->setProblemIds( i, idlp ); // bugfix #1 (maxence 10/23/2008)
|
||||
feat->candidates[ j ]->setProblemIds( static_cast< int >( i ), idlp ); // bugfix #1 (maxence 10/23/2008)
|
||||
}
|
||||
fFeats.emplace_back( std::move( feat ) );
|
||||
}
|
||||
@ -400,35 +380,31 @@ std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeom
|
||||
{
|
||||
if ( isCanceled() )
|
||||
{
|
||||
for ( const std::unique_ptr< Feats > &feat : qgis::as_const( fFeats ) )
|
||||
{
|
||||
qDeleteAll( feat->candidates );
|
||||
feat->candidates.clear();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr< Feats > feat = std::move( fFeats.front() );
|
||||
fFeats.pop_front();
|
||||
|
||||
while ( !feat->candidates.isEmpty() ) // foreach label candidate
|
||||
for ( std::unique_ptr< LabelPosition > &candidate : feat->candidates )
|
||||
{
|
||||
lp = feat->candidates.takeFirst();
|
||||
std::unique_ptr< LabelPosition > lp = std::move( candidate );
|
||||
|
||||
lp->resetNumOverlaps();
|
||||
|
||||
// make sure that candidate's cost is less than 1
|
||||
lp->validateCost();
|
||||
|
||||
prob->addCandidatePosition( lp );
|
||||
//prob->feat[idlp] = j;
|
||||
|
||||
lp->getBoundingBox( amin, amax );
|
||||
|
||||
// lookup for overlapping candidate
|
||||
prob->candidates->Search( amin, amax, LabelPosition::countOverlapCallback, static_cast< void * >( lp ) );
|
||||
prob->candidates->Search( amin, amax, LabelPosition::countOverlapCallback, static_cast< void * >( lp.get() ) );
|
||||
|
||||
nbOverlaps += lp->getNumOverlaps();
|
||||
|
||||
prob->addCandidatePosition( lp.release() );
|
||||
}
|
||||
}
|
||||
nbOverlaps /= 2;
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
|
||||
#include <QList>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace pal
|
||||
{
|
||||
@ -41,6 +43,7 @@ namespace pal
|
||||
class LabelPosition;
|
||||
class Layer;
|
||||
class FeaturePart;
|
||||
class PointSet;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
@ -56,7 +59,7 @@ namespace pal
|
||||
FeaturePart *feature = nullptr;
|
||||
PointSet *shape = nullptr;
|
||||
double priority = 0;
|
||||
QList< LabelPosition *> candidates;
|
||||
std::vector< std::unique_ptr< LabelPosition > > candidates;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user