Skip to content

Commit

Permalink
Merge branch 'master' into wms-t_layer_metadata_support
Browse files Browse the repository at this point in the history
  • Loading branch information
Samweli committed Dec 30, 2019
2 parents 24a3146 + 578f32a commit ad9313d
Show file tree
Hide file tree
Showing 30 changed files with 1,231 additions and 422 deletions.
@@ -1,6 +1,6 @@
Grid Buffer
grid_tools
QgsProcessingParameterRasterLayer|FEATURES|Features Grid|None|False
QgsProcessingParameterNumber|DIST|Distance|QgsProcessingParameterNumber.Integer|1000|False|None|None
QgsProcessingParameterEnum|BUFFERTYPE|Buffer Distance|[0] Fixed;[1] Cell value
QgsProcessingParameterNumber|DISTANCE|Distance|QgsProcessingParameterNumber.Double|1000.0|False|0.0|None
QgsProcessingParameterEnum|TYPE|Buffer Distance|[0] fixed;[1] cell's value
QgsProcessingParameterRasterDestination|BUFFER|Buffer Grid
2 changes: 1 addition & 1 deletion src/app/labeling/qgslabelengineconfigdialog.cpp
Expand Up @@ -56,7 +56,7 @@ QgsLabelEngineConfigWidget::QgsLabelEngineConfigWidget( QWidget *parent )
} );

spinCandLine->setClearValue( 5 );
spinCandPolygon->setClearValue( 10 );
spinCandPolygon->setClearValue( 2.5 );

// candidate numbers
spinCandLine->setValue( engineSettings.maximumLineCandidatesPerCm() );
Expand Down
2 changes: 1 addition & 1 deletion src/core/labeling/qgslabelingenginesettings.cpp
Expand Up @@ -33,7 +33,7 @@ void QgsLabelingEngineSettings::readSettingsFromProject( QgsProject *prj )
bool saved = false;
mSearchMethod = static_cast< Search >( prj->readNumEntry( QStringLiteral( "PAL" ), QStringLiteral( "/SearchMethod" ), static_cast< int >( Chain ), &saved ) );
mMaxLineCandidatesPerCm = prj->readDoubleEntry( QStringLiteral( "PAL" ), QStringLiteral( "/CandidatesLinePerCM" ), 5, &saved );
mMaxPolygonCandidatesPerCmSquared = prj->readDoubleEntry( QStringLiteral( "PAL" ), QStringLiteral( "/CandidatesPolygonPerCM" ), 10, &saved );
mMaxPolygonCandidatesPerCmSquared = prj->readDoubleEntry( QStringLiteral( "PAL" ), QStringLiteral( "/CandidatesPolygonPerCM" ), 2.5, &saved );

mFlags = nullptr;
if ( prj->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/ShowingCandidates" ), false, &saved ) ) mFlags |= DrawCandidates;
Expand Down
2 changes: 1 addition & 1 deletion src/core/labeling/qgslabelingenginesettings.h
Expand Up @@ -220,7 +220,7 @@ class CORE_EXPORT QgsLabelingEngineSettings

// maximum density of line/polygon candidates per mm
double mMaxLineCandidatesPerCm = 5;
double mMaxPolygonCandidatesPerCmSquared = 10;
double mMaxPolygonCandidatesPerCmSquared = 2.5;

QColor mUnplacedLabelColor = QColor( 255, 0, 0 );

Expand Down
67 changes: 56 additions & 11 deletions src/core/pal/costcalculator.cpp
Expand Up @@ -111,32 +111,72 @@ void CostCalculator::calculateCandidatePolygonRingDistanceCosts( std::vector< st
{
// 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
QHash< LabelPosition *, double > polygonRingDistanceCosts;
double minCandidateRingDistanceCost = std::numeric_limits< double >::max();
double maxCandidateRingDistanceCost = std::numeric_limits< double >::lowest();
QHash< LabelPosition *, double > polygonRingDistances;
double minCandidateRingDistance = std::numeric_limits< double >::max();
double maxCandidateRingDistance = std::numeric_limits< double >::lowest();
for ( std::unique_ptr< LabelPosition > &pos : lPos )
{
const double candidatePolygonRingDistanceCost = calculatePolygonRingDistance( pos.get(), bbx, bby );
const double candidatePolygonRingDistance = calculatePolygonRingDistance( pos.get(), bbx, bby );

minCandidateRingDistanceCost = std::min( minCandidateRingDistanceCost, candidatePolygonRingDistanceCost );
maxCandidateRingDistanceCost = std::max( maxCandidateRingDistanceCost, candidatePolygonRingDistanceCost );
minCandidateRingDistance = std::min( minCandidateRingDistance, candidatePolygonRingDistance );
maxCandidateRingDistance = std::max( maxCandidateRingDistance, candidatePolygonRingDistance );

polygonRingDistanceCosts.insert( pos.get(), candidatePolygonRingDistanceCost );
polygonRingDistances.insert( pos.get(), candidatePolygonRingDistance );
}

// define the cost's range, if range is too small, just ignore the ring distance cost
const double costRange = maxCandidateRingDistanceCost - minCandidateRingDistanceCost;
const double costRange = maxCandidateRingDistance - minCandidateRingDistance;
if ( costRange <= EPSILON )
return;

const double normalizer = 0.0020 / costRange;

// adjust cost => the best is 0.0001, the worst is 0.0021
// adjust cost => the best is 0, the worst is 0.002
// others are set proportionally between best and worst
for ( std::unique_ptr< LabelPosition > &pos : lPos )
{
const double originalPolygonRingDistanceCost = polygonRingDistanceCosts.value( pos.get() );
pos->setCost( pos->cost() + 0.0021 - ( originalPolygonRingDistanceCost - minCandidateRingDistanceCost ) * normalizer );
const double polygonRingDistanceCost = polygonRingDistances.value( pos.get() );
pos->setCost( pos->cost() + 0.002 - ( polygonRingDistanceCost - minCandidateRingDistance ) * normalizer );
}
}

void CostCalculator::calculateCandidatePolygonCentroidDistanceCosts( pal::FeaturePart *feature, std::vector<std::unique_ptr<LabelPosition> > &lPos )
{
double cx, cy;
feature->getCentroid( cx, cy );

// first we calculate the centroid distance cost for all candidates for this feature. We then use the range
// of distance costs to calculate a standardised scaling for the costs
QHash< LabelPosition *, double > polygonCentroidDistances;
double minCandidateCentroidDistance = std::numeric_limits< double >::max();
double maxCandidateCentroidDistance = std::numeric_limits< double >::lowest();
for ( std::unique_ptr< LabelPosition > &pos : lPos )
{
const double lPosX = ( pos->x[0] + pos->x[2] ) / 2.0;
const double lPosY = ( pos->y[0] + pos->y[2] ) / 2.0;

const double candidatePolygonCentroidDistance = std::sqrt( ( cx - lPosX ) * ( cx - lPosX ) + ( cy - lPosY ) * ( cy - lPosY ) );

minCandidateCentroidDistance = std::min( minCandidateCentroidDistance, candidatePolygonCentroidDistance );
maxCandidateCentroidDistance = std::max( maxCandidateCentroidDistance, candidatePolygonCentroidDistance );

polygonCentroidDistances.insert( pos.get(), candidatePolygonCentroidDistance );
}

// define the cost's range, if range is too small, just ignore the ring distance cost
const double costRange = maxCandidateCentroidDistance - minCandidateCentroidDistance;
if ( costRange <= EPSILON )
return;

const double normalizer = 0.001 / costRange;

// adjust cost => the closest is 0, the furthest is 0.001
// others are set proportionally between best and worst
// NOTE: centroid cost range may need adjusting with respect to ring distance range!
for ( std::unique_ptr< LabelPosition > &pos : lPos )
{
const double polygonCentroidDistance = polygonCentroidDistances.value( pos.get() );
pos->setCost( pos->cost() + ( polygonCentroidDistance - minCandidateCentroidDistance ) * normalizer );
}
}

Expand Down Expand Up @@ -207,7 +247,12 @@ void CostCalculator::finalizeCandidatesCosts( Feats *feat, double bbx[4], double
{
int arrangement = feat->feature->layer()->arrangement();
if ( arrangement == QgsPalLayerSettings::Free || arrangement == QgsPalLayerSettings::Horizontal )
{
// prefer positions closer to the pole of inaccessibilities
calculateCandidatePolygonRingDistanceCosts( feat->candidates, bbx, bby );
// ...of these, prefer positions closer to the overall polygon centroid
calculateCandidatePolygonCentroidDistanceCosts( feat->feature, feat->candidates );
}
}

// add size penalty (small lines/polygons get higher cost)
Expand Down
7 changes: 7 additions & 0 deletions src/core/pal/costcalculator.h
Expand Up @@ -46,6 +46,13 @@ namespace pal
*/
static void calculateCandidatePolygonRingDistanceCosts( std::vector<std::unique_ptr<pal::LabelPosition> > &lPos, double bbx[4], double bby[4] );

/**
* Updates the costs for polygon label candidates by considering the distance between the
* candidates and the polygon centroid (i.e. given labels at similar distances from polygon rings,
* prefer labels closer to the centroid).
*/
static void calculateCandidatePolygonCentroidDistanceCosts( pal::FeaturePart *feature, std::vector<std::unique_ptr<pal::LabelPosition> > &lPos );

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

Expand Down

0 comments on commit ad9313d

Please sign in to comment.