Skip to content
Permalink
Browse files

[needs-docs] Add optional global settings allowing for hard limits

to be placed on the maximum number of point, line and polygon candidates
which are generated for label features

These settings are set via the core\rendering\label_candidates_limit_*
settings, and allow for global limits to be set on the maximum number
of candidates allowed for label features. Placing these limits can
improve map rendering time, at the expense of worse label placement or
potentially missing map labels. (By default no global limit is set, which
means the labeling engine auto calculates the limit or uses the project
level settings)

The intended use case is for server administrators who are seeking for
maximum rendering speed to globally set these limits, causing them to
apply to all projects without the need for project-specific tweaks.
  • Loading branch information
nyalldawson committed Dec 22, 2019
1 parent 7e3de3a commit c5e0ada6bde4db2a0e25d8386ad68d81b8e42293
@@ -98,6 +98,24 @@ NewsFeed\http00008000\long=
# When new projects are created, default to planimetric measurement.
measure\planimetric=false

# When set to a non-zero value, places a global limit on the maximum number of label candidates which
# are generated for point features. Setting this limit to a low (non-zero) value can improve map rendering
# time, at the expense of worse label placement or potentially missing map labels. A value of 0 indicates
# that no limit is present.
rendering\label_candidates_limit_points=0

# When set to a non-zero value, places a global limit on the maximum number of label candidates which
# are generated for line features. Setting this limit to a low (non-zero) value can improve map rendering
# time, at the expense of worse label placement or potentially missing map labels. A value of 0 indicates
# that no limit is present.
rendering\label_candidates_limit_lines=0

# When set to a non-zero value, places a global limit on the maximum number of label candidates which
# are generated for polygon features. Setting this limit to a low (non-zero) value can improve map rendering
# time, at the expense of worse label placement or potentially missing map labels. A value of 0 indicates
# that no limit is present.
rendering\label_candidates_limit_polygons=0

[colors]
# These colors are used in logs.
default=
@@ -157,6 +157,11 @@ QgsFeatureId FeaturePart::featureId() const
return mLF->id();
}

std::size_t FeaturePart::maximumPointCandidates() const
{
return mLF->layer()->maximumPointLabelCandidates();
}

std::size_t FeaturePart::maximumLineCandidates() const
{
if ( mCachedMaxLineCandidates > 0 )
@@ -168,7 +173,7 @@ std::size_t FeaturePart::maximumLineCandidates() const
double length = 0;
if ( GEOSLength_r( geosctxt, geos(), &length ) == 1 )
{
const std::size_t candidatesForLineLength = static_cast< std::size_t >( std::ceil( mLF->layer()->pal->maximumLineCandidatesPerMapUnit() * length ) );
const std::size_t candidatesForLineLength = static_cast< std::size_t >( std::ceil( mLF->layer()->mPal->maximumLineCandidatesPerMapUnit() * length ) );
const std::size_t maxForLayer = mLF->layer()->maximumLineLabelCandidates();
if ( maxForLayer == 0 )
mCachedMaxLineCandidates = candidatesForLineLength;
@@ -195,7 +200,7 @@ std::size_t FeaturePart::maximumPolygonCandidates() const
double area = 0;
if ( GEOSArea_r( geosctxt, geos(), &area ) == 1 )
{
const std::size_t candidatesForArea = static_cast< std::size_t >( std::ceil( mLF->layer()->pal->maximumPolygonCandidatesPerMapUnitSquared() * area ) );
const std::size_t candidatesForArea = static_cast< std::size_t >( std::ceil( mLF->layer()->mPal->maximumPolygonCandidatesPerMapUnitSquared() * area ) );
const std::size_t maxForLayer = mLF->layer()->maximumPolygonLabelCandidates();
if ( maxForLayer == 0 )
mCachedMaxPolygonCandidates = candidatesForArea;
@@ -126,6 +126,11 @@ namespace pal
*/
QgsFeatureId featureId() const;

/**
* Returns the maximum number of point candidates to generate for this feature.
*/
std::size_t maximumPointCandidates() const;

/**
* Returns the maximum number of line candidates to generate for this feature.
*/
@@ -44,7 +44,7 @@ using namespace pal;
Layer::Layer( QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal, bool displayAll )
: mProvider( provider )
, mName( name )
, pal( pal )
, mPal( pal )
, mActive( active )
, mLabelLayer( toLabel )
, mDisplayAll( displayAll )
@@ -88,7 +88,7 @@ namespace pal
* \param displayAll if TRUE, all features will be labelled even though overlaps occur
*
*/
Layer( QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal, bool displayAll = false );
Layer( QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *mPal, bool displayAll = false );

virtual ~Layer();

@@ -109,15 +109,15 @@ namespace pal
// to avoid the engine processing endlessly...
const int size = mHashtable.size();
if ( size > 1000 )
return 4;
return static_cast< std::size_t >( mPal->globalCandidatesLimitPoint() > 0 ? std::min( mPal->globalCandidatesLimitPoint(), 4 ) : 4 );
else if ( size > 500 )
return 6;
return static_cast< std::size_t >( mPal->globalCandidatesLimitPoint() > 0 ? std::min( mPal->globalCandidatesLimitPoint(), 6 ) : 6 );
else if ( size > 200 )
return 8;
return static_cast< std::size_t >( mPal->globalCandidatesLimitPoint() > 0 ? std::min( mPal->globalCandidatesLimitPoint(), 8 ) : 8 );
else if ( size > 100 )
return 12;
return static_cast< std::size_t >( mPal->globalCandidatesLimitPoint() > 0 ? std::min( mPal->globalCandidatesLimitPoint(), 12 ) : 12 );
else
return 0;
return static_cast< std::size_t >( std::max( mPal->globalCandidatesLimitPoint(), 0 ) );
}

/**
@@ -130,15 +130,15 @@ namespace pal
// to avoid the engine processing endlessly...
const int size = mHashtable.size();
if ( size > 1000 )
return static_cast< std::size_t >( 5 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitLine() > 0 ? std::min( mPal->globalCandidatesLimitLine(), 5 ) : 5 );
else if ( size > 500 )
return static_cast< std::size_t >( 10 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitLine() > 0 ? std::min( mPal->globalCandidatesLimitLine(), 10 ) : 10 );
else if ( size > 200 )
return static_cast< std::size_t >( 20 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitLine() > 0 ? std::min( mPal->globalCandidatesLimitLine(), 20 ) : 20 );
else if ( size > 100 )
return static_cast< std::size_t >( 40 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitLine() > 0 ? std::min( mPal->globalCandidatesLimitLine(), 40 ) : 40 );
else
return static_cast< std::size_t >( 0 );
return static_cast< std::size_t >( std::max( mPal->globalCandidatesLimitLine(), 0 ) );
}

/**
@@ -151,15 +151,15 @@ namespace pal
// to avoid the engine processing endlessly...
const int size = mHashtable.size();
if ( size > 1000 )
return static_cast< std::size_t >( 5 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitPolygon() > 0 ? std::min( mPal->globalCandidatesLimitPolygon(), 5 ) : 5 );
else if ( size > 500 )
return static_cast< std::size_t >( 15 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitPolygon() > 0 ? std::min( mPal->globalCandidatesLimitPolygon(), 15 ) : 15 );
else if ( size > 200 )
return static_cast< std::size_t >( 20 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitPolygon() > 0 ? std::min( mPal->globalCandidatesLimitPolygon(), 20 ) : 20 );
else if ( size > 100 )
return static_cast< std::size_t >( 25 );
return static_cast< std::size_t >( mPal->globalCandidatesLimitPolygon() > 0 ? std::min( mPal->globalCandidatesLimitPolygon(), 25 ) : 25 );
else
return static_cast< std::size_t >( 0 );
return static_cast< std::size_t >( std::max( mPal->globalCandidatesLimitPolygon(), 0 ) );
}

//! Returns pointer to the associated provider
@@ -329,7 +329,7 @@ namespace pal

std::vector< geos::unique_ptr > mGeosObstacleGeometries;

Pal *pal = nullptr;
Pal *mPal = nullptr;

double mDefaultPriority;

@@ -41,12 +41,19 @@
#include "internalexception.h"
#include "util.h"
#include "palrtree.h"
#include "qgssettings.h"
#include <cfloat>
#include <list>

using namespace pal;

Pal::Pal() = default;
Pal::Pal()
{
QgsSettings settings;
mGlobalCandidatesLimitPoint = settings.value( QStringLiteral( "rendering/label_candidates_limit_points" ), 0, QgsSettings::Core ).toInt();
mGlobalCandidatesLimitLine = settings.value( QStringLiteral( "rendering/label_candidates_limit_lines" ), 0, QgsSettings::Core ).toInt();
mGlobalCandidatesLimitPolygon = settings.value( QStringLiteral( "rendering/label_candidates_limit_polygons" ), 0, QgsSettings::Core ).toInt();
}

Pal::~Pal() = default;

@@ -291,7 +298,8 @@ std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeom
switch ( feat->feature->getGeosType() )
{
case GEOS_POINT:
// no max at this stage, use all the candidates generated
// this is usually 0, i.e. no maximum
max_p = feat->feature->maximumPointCandidates();
break;

case GEOS_LINESTRING:
@@ -215,6 +215,42 @@ namespace pal
*/
void setPlacementVersion( QgsLabelingEngineSettings::PlacementEngineVersion placementVersion );

/**
* Returns the global candidates limit for point features, or 0 if no global limit is in effect.
*
* This is an installation-wide setting which applies to all projects, and is set via QSettings. It can
* be used to place global limits on the number of candidates generated for point features in order
* to optimise map rendering speeds.
*
* \see globalCandidatesLimitLine()
* \see globalCandidatesLimitPolygon()
*/
int globalCandidatesLimitPoint() const { return mGlobalCandidatesLimitPoint; }

/**
* Returns the global candidates limit for line features, or 0 if no global limit is in effect.
*
* This is an installation-wide setting which applies to all projects, and is set via QSettings. It can
* be used to place global limits on the number of candidates generated for line features in order
* to optimise map rendering speeds.
*
* \see globalCandidatesLimitPolygon()
* \see globalCandidatesLimitPoint()
*/
int globalCandidatesLimitLine() const { return mGlobalCandidatesLimitLine; }

/**
* Returns the global candidates limit for polygon features, or 0 if no global limit is in effect.
*
* This is an installation-wide setting which applies to all projects, and is set via QSettings. It can
* be used to place global limits on the number of candidates generated for polygon features in order
* to optimise map rendering speeds.
*
* \see globalCandidatesLimitLine()
* \see globalCandidatesLimitPoint()
*/
int globalCandidatesLimitPolygon() const { return mGlobalCandidatesLimitPolygon; }

private:

std::unordered_map< QgsAbstractLabelProvider *, std::unique_ptr< Layer > > mLayers;
@@ -241,6 +277,10 @@ namespace pal
double mMaxLineCandidatesPerMapUnit = 0;
double mMaxPolygonCandidatesPerMapUnitSquared = 0;

int mGlobalCandidatesLimitPoint = 0;
int mGlobalCandidatesLimitLine = 0;
int mGlobalCandidatesLimitPolygon = 0;

QgsLabelingEngineSettings::PlacementEngineVersion mPlacementVersion = QgsLabelingEngineSettings::PlacementEngineVersion2;

//! Callback that may be called from PAL to check whether the job has not been canceled in meanwhile

0 comments on commit c5e0ada

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