Skip to content
Permalink
Browse files

Merge branch 'master' into wms-t_layer_metadata_support

  • Loading branch information
Samweli committed Dec 30, 2019
2 parents 24a3146 + 578f32a commit ad9313d08186e9f7264da217ee4a2c3eba524b16
Showing with 1,231 additions and 422 deletions.
  1. +2 −2 python/plugins/processing/algs/saga/description/GridBuffer.txt
  2. +1 −1 src/app/labeling/qgslabelengineconfigdialog.cpp
  3. +1 −1 src/core/labeling/qgslabelingenginesettings.cpp
  4. +1 −1 src/core/labeling/qgslabelingenginesettings.h
  5. +56 −11 src/core/pal/costcalculator.cpp
  6. +7 −0 src/core/pal/costcalculator.h
  7. +89 −77 src/core/pal/feature.cpp
  8. +10 −8 src/core/pal/layer.cpp
  9. +33 −3 src/core/pal/pointset.cpp
  10. +9 −0 src/core/pal/pointset.h
  11. +127 −103 src/providers/wcs/qgswcscapabilities.cpp
  12. +49 −7 src/providers/wcs/qgswcscapabilities.h
  13. +9 −1 src/providers/wcs/qgswcsprovider.cpp
  14. +28 −1 src/providers/wms/qgswmscapabilities.cpp
  15. +1 −0 src/providers/wms/qgswmscapabilities.h
  16. +20 −0 src/providers/wms/qgswmsprovider.cpp
  17. +150 −94 src/ui/layout/qgspdfexportoptions.ui
  18. +26 −26 src/ui/qgsoptionsbase.ui
  19. +8 −8 src/ui/qgsprojectpropertiesbase.ui
  20. +32 −32 src/ui/qgsrasterlayerpropertiesbase.ui
  21. +2 −2 src/ui/qgstextformatwidgetbase.ui
  22. +26 −44 src/ui/qgsvectorlayerpropertiesbase.ui
  23. +24 −0 tests/src/python/test_qgspallabeling_placement.py
  24. BIN ...a/control_images/expected_pal_placement/sp_polygon_placement_bumps/sp_polygon_placement_bumps.png
  25. BIN ...images/expected_pal_placement/sp_polygon_placement_small_bump/sp_polygon_placement_small_bump.png
  26. BIN .../expected_pal_placement/sp_polygon_placement_with_obstacle/sp_polygon_placement_with_obstacle.png
  27. +8 −0 tests/testdata/labeling/polygon_small_bump.geojson
  28. +252 −0 tests/testdata/labeling/polygon_small_bump.qml
  29. +8 −0 tests/testdata/labeling/polygon_with_bump.geojson
  30. +252 −0 tests/testdata/labeling/polygon_with_bump.qml
@@ -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
@@ -56,7 +56,7 @@ QgsLabelEngineConfigWidget::QgsLabelEngineConfigWidget( QWidget *parent )
} );

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

// candidate numbers
spinCandLine->setValue( engineSettings.maximumLineCandidatesPerCm() );
@@ -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;
@@ -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 );

@@ -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 );
}
}

@@ -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)
@@ -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] );

0 comments on commit ad9313d

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