Skip to content

Commit ce2c402

Browse files
committed
[FEATURE][labeling] Allow data defined control of label priority
Previously only the priority for the entire layer could be specified (fix #4606)
1 parent 736f1c4 commit ce2c402

10 files changed

+484
-78
lines changed

python/core/qgspallabeling.sip

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ class QgsPalLayerSettings
278278
Rotation, //data defined rotation
279279
RepeatDistance,
280280
RepeatDistanceUnit,
281+
Priority,
281282

282283
// rendering
283284
ScaleVisibility,

src/app/qgslabelinggui.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
831831
setDataDefinedProperty( mMaxCharAngleDDBtn, QgsPalLayerSettings::CurvedCharAngleInOut, lyr );
832832
setDataDefinedProperty( mRepeatDistanceDDBtn, QgsPalLayerSettings::RepeatDistance, lyr );
833833
setDataDefinedProperty( mRepeatDistanceUnitDDBtn, QgsPalLayerSettings::RepeatDistanceUnit, lyr );
834+
setDataDefinedProperty( mPriorityDDBtn, QgsPalLayerSettings::Priority, lyr );
834835

835836
// data defined-only
836837
setDataDefinedProperty( mCoordXDDBtn, QgsPalLayerSettings::PositionX, lyr );
@@ -1051,6 +1052,9 @@ void QgsLabelingGui::populateDataDefinedButtons( QgsPalLayerSettings& s )
10511052
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
10521053
mLineDistanceUnitDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DistanceUnits ),
10531054
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
1055+
mPriorityDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Priority ),
1056+
QgsDataDefinedButton::AnyType, tr( "double [0.0-10.0]" ) );
1057+
10541058
// TODO: is this necessary? maybe just use the data defined-only rotation?
10551059
//mPointAngleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::OffsetRotation ),
10561060
// QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );

src/core/pal/feature.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ namespace pal
7777
, repeatDist( 0.0 )
7878
, alwaysShow( false )
7979
, mFixedQuadrant( false )
80+
, mPriority( -1.0 )
8081
{
8182
assert( finite( lx ) && finite( ly ) );
8283
}
@@ -86,6 +87,11 @@ namespace pal
8687

8788
}
8889

90+
double Feature::calculatePriority() const
91+
{
92+
return mPriority >= 0 ? mPriority : layer->getPriority();
93+
}
94+
8995
////////////
9096

9197
FeaturePart::FeaturePart( Feature *feat, const GEOSGeometry* geom )

src/core/pal/feature.h

+36-2
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,55 @@ namespace pal
8585

8686
void setLabelInfo( LabelInfo* info ) { labelInfo = info; }
8787
void setDistLabel( double dist ) { distlabel = dist; }
88-
//Set label position of the feature to fixed x/y values
88+
/** Set label position of the feature to fixed x/y values */
8989
void setFixedPosition( double x, double y ) { fixedPos = true; fixedPosX = x; fixedPosY = y;}
9090
void setQuadOffset( double x, double y ) { quadOffset = true; quadOffsetX = x; quadOffsetY = y;}
9191

9292
/** Sets whether the quadrant for the label must be respected. This can be used
9393
* to fix the quadrant for specific features when using an "around point" placement.
94+
* @see fixedQuadrant
9495
*/
9596
void setFixedQuadrant( bool fixed ) { mFixedQuadrant = fixed; }
97+
98+
/** Returns whether the quadrant for the label is fixed.
99+
* @see setFixedQuadrant
100+
*/
96101
bool fixedQuadrant() const { return mFixedQuadrant; }
97102

98103
void setPosOffset( double x, double y ) { offsetPos = true; offsetPosX = x; offsetPosY = y;}
99104
bool fixedPosition() const { return fixedPos; }
100-
//Set label rotation to fixed value
105+
106+
/** Set label rotation to fixed value
107+
*/
101108
void setFixedAngle( double a ) { fixedRotation = true; fixedAngle = a; }
102109
void setRepeatDistance( double dist ) { repeatDist = dist; }
103110
double repeatDistance() const { return repeatDist; }
104111
void setAlwaysShow( bool bl ) { alwaysShow = bl; }
105112

113+
/** Sets the priority for labeling the feature.
114+
* @param priority feature's priority, as a value between 0 (highest priority)
115+
* and 1 (lowest priority). Set to -1.0 to use the layer's default priority
116+
* for this feature.
117+
* @see priority
118+
* @see calculatePriority
119+
*/
120+
void setPriority( double priority ) { mPriority = priority; }
121+
122+
/** Returns the feature's labeling priority.
123+
* @returns feature's priority, as a value between 0 (highest priority)
124+
* and 1 (lowest priority). Returns -1.0 if feature will use the layer's default priority.
125+
* @see setPriority
126+
* @see calculatePriority
127+
*/
128+
double priority() const { return mPriority; }
129+
130+
/** Calculates the priority for the feature. This will be the feature's priority if set,
131+
* otherwise the layer's default priority.
132+
* @see setPriority
133+
* @see priority
134+
*/
135+
double calculatePriority() const;
136+
106137
protected:
107138
Layer *layer;
108139
PalGeometry *userGeom;
@@ -136,6 +167,9 @@ namespace pal
136167
private:
137168

138169
bool mFixedQuadrant;
170+
171+
//-1 if layer priority should be used
172+
double mPriority;
139173
};
140174

141175
/**

src/core/pal/layer.h

-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ namespace pal
192192
* \ brief set the layer priority
193193
*
194194
* The best priority is 0, the worst is 1
195-
* Should be links with a slider in a nice gui
196195
*/
197196
void setPriority( double priority );
198197

src/core/pal/pal.cpp

+6-15
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ namespace pal
206206
QLinkedList<Feats*>* fFeats;
207207
RTree<PointSet*, double, 2, double> *obstacles;
208208
RTree<LabelPosition*, double, 2, double> *candidates;
209-
double priority;
210209
double bbox_min[2];
211210
double bbox_max[2];
212211
} FeatCallBackCtx;
@@ -275,7 +274,7 @@ namespace pal
275274
ft->shape = NULL;
276275
ft->nblp = nblp;
277276
ft->lPos = lPos;
278-
ft->priority = context->priority;
277+
ft->priority = ft_ptr->getFeature()->calculatePriority();
279278
context->fFeats->append( ft );
280279
}
281280
else
@@ -320,7 +319,7 @@ namespace pal
320319
return true;
321320
}
322321

323-
Problem* Pal::extract( int nbLayers, const QStringList& layersName, double *layersFactor, double lambda_min, double phi_min, double lambda_max, double phi_max, double scale )
322+
Problem* Pal::extract( int nbLayers, const QStringList& layersName, double lambda_min, double phi_min, double lambda_max, double phi_max, double scale )
324323
{
325324
// to store obstacles
326325
RTree<PointSet*, double, 2, double> *obstacles = new RTree<PointSet*, double, 2, double>();
@@ -399,7 +398,6 @@ namespace pal
399398

400399

401400
context->layer = layer;
402-
context->priority = layersFactor[i];
403401
// lookup for feature (and generates candidates list)
404402

405403
context->layer->mMutex.lock();
@@ -614,29 +612,26 @@ namespace pal
614612
int nbLayers = layers->size();
615613

616614
QStringList layersName;
617-
double *priorities = new double[nbLayers];
618615
Layer *layer;
619616
i = 0;
620617
for ( QList<Layer*>::iterator it = layers->begin(); it != layers->end(); ++it )
621618
{
622619
layer = *it;
623620
layersName << layer->name;
624-
priorities[i] = layer->defaultPriority;
625621
i++;
626622
}
627623
mMutex.unlock();
628624

629-
std::list<LabelPosition*> * solution = labeller( nbLayers, layersName, priorities, scale, bbox, stats, displayAll );
625+
std::list<LabelPosition*> * solution = labeller( nbLayers, layersName, scale, bbox, stats, displayAll );
630626

631-
delete[] priorities;
632627
return solution;
633628
}
634629

635630

636631
/*
637632
* BIG MACHINE
638633
*/
639-
std::list<LabelPosition*>* Pal::labeller( int nbLayers, const QStringList& layersName, double *layersFactor, double scale, double bbox[4], PalStat **stats, bool displayAll )
634+
std::list<LabelPosition*>* Pal::labeller( int nbLayers, const QStringList& layersName, double scale, double bbox[4], PalStat **stats, bool displayAll )
640635
{
641636
#ifdef _DEBUG_
642637
std::cout << "LABELLER (selection)" << std::endl;
@@ -662,7 +657,7 @@ namespace pal
662657

663658
// First, extract the problem
664659
// TODO which is the minimum scale? (> 0, >= 0, >= 1, >1 )
665-
if ( scale < 1 || ( prob = extract( nbLayers, layersName, layersFactor, bbox[0], bbox[1], bbox[2], bbox[3], scale ) ) == NULL )
660+
if ( scale < 1 || ( prob = extract( nbLayers, layersName, bbox[0], bbox[1], bbox[2], bbox[3], scale ) ) == NULL )
666661
{
667662

668663
#ifdef _VERBOSE_
@@ -750,21 +745,17 @@ namespace pal
750745
int nbLayers = layers->size();
751746

752747
QStringList layersName;
753-
double *priorities = new double[nbLayers];
754748
Layer *layer;
755749
int i = 0;
756750
for ( QList<Layer*>::iterator it = layers->begin(); it != layers->end(); ++it )
757751
{
758752
layer = *it;
759753
layersName << layer->name;
760-
priorities[i] = layer->defaultPriority;
761754
i++;
762755
}
763756
mMutex.unlock();
764757

765-
Problem* prob = extract( nbLayers, layersName, priorities, bbox[0], bbox[1], bbox[2], bbox[3], scale );
766-
767-
delete[] priorities;
758+
Problem* prob = extract( nbLayers, layersName, bbox[0], bbox[1], bbox[2], bbox[3], scale );
768759

769760
return prob;
770761
}

src/core/pal/pal.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ namespace pal
202202
*
203203
* @param nbLayers # layers
204204
* @param layersName names of layers to label
205-
* @param layersFactor layers priorities array
206205
* @param scale map scale is '1:scale'
207206
* @param bbox map extent
208207
* @param stat will be filled with labelling process statistics, can be NULL
@@ -214,7 +213,6 @@ namespace pal
214213
*/
215214
std::list<LabelPosition*> *labeller( int nbLayers,
216215
const QStringList &layersName,
217-
double *layersFactor,
218216
double scale, double bbox[4],
219217
PalStat **stat,
220218
bool displayAll );
@@ -380,14 +378,13 @@ namespace pal
380378
*
381379
* @param nbLayers number of layers to extract
382380
* @param layersName layers name to be extracted
383-
* @param layersFactor layer's factor (priority between layers, 0 is the best, 1 the worst)
384381
* @param lambda_min xMin bounding-box
385382
* @param phi_min yMin bounding-box
386383
* @param lambda_max xMax bounding-box
387384
* @param phi_max yMax bounding-box
388385
* @param scale the scale (1:scale)
389386
*/
390-
Problem* extract( int nbLayers, const QStringList& layersName, double *layersFactor,
387+
Problem* extract( int nbLayers, const QStringList& layersName,
391388
double lambda_min, double phi_min,
392389
double lambda_max, double phi_max,
393390
double scale );

src/core/qgspallabeling.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ QgsPalLayerSettings::QgsPalLayerSettings()
292292
mDataDefinedNames.insert( CurvedCharAngleInOut, QPair<QString, int>( "CurvedCharAngleInOut", -1 ) );
293293
mDataDefinedNames.insert( RepeatDistance, QPair<QString, int>( "RepeatDistance", -1 ) );
294294
mDataDefinedNames.insert( RepeatDistanceUnit, QPair<QString, int>( "RepeatDistanceUnit", -1 ) );
295+
mDataDefinedNames.insert( Priority, QPair<QString, int>( "Priority", -1 ) );
296+
295297
// (data defined only)
296298
mDataDefinedNames.insert( PositionX, QPair<QString, int>( "PositionX", 9 ) );
297299
mDataDefinedNames.insert( PositionY, QPair<QString, int>( "PositionY", 10 ) );
@@ -2173,6 +2175,19 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
21732175
feat->setFixedQuadrant( true );
21742176
}
21752177

2178+
// data defined priority?
2179+
if ( dataDefinedEvaluate( QgsPalLayerSettings::Priority, exprVal ) )
2180+
{
2181+
bool ok;
2182+
double priorityD = exprVal.toDouble( &ok );
2183+
if ( ok )
2184+
{
2185+
priorityD = qBound( 0.0, priorityD, 10.0 );
2186+
priorityD = 1 - priorityD / 10.0; // convert 0..10 --> 1..0
2187+
feat->setPriority( priorityD );
2188+
}
2189+
}
2190+
21762191
//add parameters for data defined labeling to QgsPalGeometry
21772192
QMap< DataDefinedProperties, QVariant >::const_iterator dIt = dataDefinedValues.constBegin();
21782193
for ( ; dIt != dataDefinedValues.constEnd(); ++dIt )

src/core/qgspallabeling.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ class CORE_EXPORT QgsPalLayerSettings
253253
Rotation = 14, //data defined rotation
254254
RepeatDistance = 84,
255255
RepeatDistanceUnit = 86,
256+
Priority = 87,
256257

257258
// rendering
258259
ScaleVisibility = 23,
@@ -556,7 +557,7 @@ class CORE_EXPORT QgsPalLayerSettings
556557

557558
void parseDropShadow();
558559

559-
/**Checks if a feature is larger than a minimum size (in mm)
560+
/** Checks if a feature is larger than a minimum size (in mm)
560561
@return true if above size, false if below*/
561562
bool checkMinimumSizeMM( const QgsRenderContext& ct, const QgsGeometry* geom, double minSize ) const;
562563

0 commit comments

Comments
 (0)