mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
[FEATURE][labeling] Add priority control for obstacles
Allows you to make labels prefer to overlap features from certain layers rather than others. Can also be data defined, so that certain features are more likely to be covered than others.
This commit is contained in:
parent
c97733ea27
commit
b4311877f7
@ -299,6 +299,7 @@ class QgsPalLayerSettings
|
||||
FontMinPixel,
|
||||
FontMaxPixel,
|
||||
IsObstacle,
|
||||
ObstacleFactor,
|
||||
|
||||
// (data defined only)
|
||||
Show,
|
||||
@ -469,6 +470,11 @@ class QgsPalLayerSettings
|
||||
|
||||
double minFeatureSize; // minimum feature size to be labelled (in mm)
|
||||
bool obstacle; // whether features for layer are obstacles to labels of other layers
|
||||
|
||||
/** Obstacle factor, where 1.0 = default, < 1.0 more likely to be covered by labels,
|
||||
* > 1.0 less likely to be covered
|
||||
*/
|
||||
double obstacleFactor;
|
||||
|
||||
/** Controls how features act as obstacles for labels
|
||||
*/
|
||||
|
@ -361,7 +361,10 @@ void QgsLabelingGui::init()
|
||||
|
||||
mPrioritySlider->setValue( lyr.priority );
|
||||
mChkNoObstacle->setChecked( lyr.obstacle );
|
||||
mObstacleFactorSlider->setValue( lyr.obstacleFactor * 50 );
|
||||
mObstacleTypeComboBox->setCurrentIndex( mObstacleTypeComboBox->findData( lyr.obstacleType ) );
|
||||
mPolygonObstacleTypeFrame->setEnabled( lyr.obstacle );
|
||||
mObstaclePriorityFrame->setEnabled( lyr.obstacle );
|
||||
chkLabelPerFeaturePart->setChecked( lyr.labelPerPart );
|
||||
mPalShowAllLabelsForLayerChkBx->setChecked( lyr.displayAll );
|
||||
chkMergeLines->setChecked( lyr.mergeLines );
|
||||
@ -657,6 +660,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
|
||||
lyr.priority = mPrioritySlider->value();
|
||||
lyr.obstacle = mChkNoObstacle->isChecked() || mLabelModeComboBox->currentIndex() == 2;
|
||||
lyr.obstacleFactor = mObstacleFactorSlider->value() / 50.0;
|
||||
lyr.obstacleType = ( QgsPalLayerSettings::ObstacleType )mObstacleTypeComboBox->itemData( mObstacleTypeComboBox->currentIndex() ).toInt();
|
||||
lyr.labelPerPart = chkLabelPerFeaturePart->isChecked();
|
||||
lyr.displayAll = mPalShowAllLabelsForLayerChkBx->isChecked();
|
||||
@ -857,6 +861,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
setDataDefinedProperty( mShowLabelDDBtn, QgsPalLayerSettings::Show, lyr );
|
||||
setDataDefinedProperty( mAlwaysShowDDBtn, QgsPalLayerSettings::AlwaysShow, lyr );
|
||||
setDataDefinedProperty( mIsObstacleDDBtn, QgsPalLayerSettings::IsObstacle, lyr );
|
||||
setDataDefinedProperty( mObstacleFactorDDBtn, QgsPalLayerSettings::ObstacleFactor, lyr );
|
||||
|
||||
return lyr;
|
||||
}
|
||||
@ -1125,6 +1130,8 @@ void QgsLabelingGui::populateDataDefinedButtons( QgsPalLayerSettings& s )
|
||||
|
||||
mIsObstacleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::IsObstacle ),
|
||||
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
|
||||
mObstacleFactorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ObstacleFactor ),
|
||||
QgsDataDefinedButton::AnyType, tr( "double [0.0-10.0]" ) );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::changeTextColor( const QColor &color )
|
||||
@ -1714,6 +1721,7 @@ void QgsLabelingGui::on_mDirectSymbRightToolBtn_clicked()
|
||||
void QgsLabelingGui::on_mChkNoObstacle_toggled( bool active )
|
||||
{
|
||||
mPolygonObstacleTypeFrame->setEnabled( active );
|
||||
mObstaclePriorityFrame->setEnabled( active );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::showBackgroundRadius( bool show )
|
||||
|
@ -72,8 +72,11 @@ namespace pal
|
||||
break;
|
||||
}
|
||||
|
||||
//scale cost by obstacle's factor
|
||||
double obstacleCost = obstacle->getFeature()->obstacleFactor() * double( n );
|
||||
|
||||
// label cost is penalized
|
||||
lp->setCost( lp->getCost() + double( n ) );
|
||||
lp->setCost( lp->getCost() + obstacleCost );
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,6 +76,7 @@ namespace pal
|
||||
, alwaysShow( false )
|
||||
, mFixedQuadrant( false )
|
||||
, mIsObstacle( true )
|
||||
, mObstacleFactor( 1.0 )
|
||||
, mPriority( -1.0 )
|
||||
{
|
||||
assert( finite( lx ) && finite( ly ) );
|
||||
|
@ -120,6 +120,21 @@ namespace pal
|
||||
*/
|
||||
double isObstacle() const { return mIsObstacle; }
|
||||
|
||||
/** Sets the obstacle factor for the feature. The factor controls the penalty
|
||||
* for labels overlapping this feature.
|
||||
* @param factor larger factors ( > 1.0 ) will result in labels
|
||||
* which are less likely to cover this feature, smaller factors ( < 1.0 ) mean labels
|
||||
* are more likely to cover this feature (where required)
|
||||
* @see obstacleFactor
|
||||
*/
|
||||
void setObstacleFactor( double factor ) { mObstacleFactor = factor; }
|
||||
|
||||
/** Returns the obstacle factor for the feature. The factor controls the penalty
|
||||
* for labels overlapping this feature.
|
||||
* @see setObstacleFactor
|
||||
*/
|
||||
double obstacleFactor() const { return mObstacleFactor; }
|
||||
|
||||
/** Sets the priority for labeling the feature.
|
||||
* @param priority feature's priority, as a value between 0 (highest priority)
|
||||
* and 1 (lowest priority). Set to -1.0 to use the layer's default priority
|
||||
@ -174,6 +189,7 @@ namespace pal
|
||||
|
||||
bool mFixedQuadrant;
|
||||
bool mIsObstacle;
|
||||
double mObstacleFactor;
|
||||
|
||||
//-1 if layer priority should be used
|
||||
double mPriority;
|
||||
|
@ -200,6 +200,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
limitNumLabels = false;
|
||||
maxNumLabels = 2000;
|
||||
obstacle = true;
|
||||
obstacleFactor = 1.0;
|
||||
obstacleType = PolygonInterior;
|
||||
|
||||
// scale factors
|
||||
@ -295,6 +296,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
mDataDefinedNames.insert( RepeatDistanceUnit, QPair<QString, int>( "RepeatDistanceUnit", -1 ) );
|
||||
mDataDefinedNames.insert( Priority, QPair<QString, int>( "Priority", -1 ) );
|
||||
mDataDefinedNames.insert( IsObstacle, QPair<QString, int>( "IsObstacle", -1 ) );
|
||||
mDataDefinedNames.insert( ObstacleFactor, QPair<QString, int>( "ObstacleFactor", -1 ) );
|
||||
|
||||
// (data defined only)
|
||||
mDataDefinedNames.insert( PositionX, QPair<QString, int>( "PositionX", 9 ) );
|
||||
@ -415,6 +417,7 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
|
||||
limitNumLabels = s.limitNumLabels;
|
||||
maxNumLabels = s.maxNumLabels;
|
||||
obstacle = s.obstacle;
|
||||
obstacleFactor = s.obstacleFactor;
|
||||
obstacleType = s.obstacleType;
|
||||
|
||||
// shape background
|
||||
@ -924,6 +927,7 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
|
||||
limitNumLabels = layer->customProperty( "labeling/limitNumLabels", QVariant( false ) ).toBool();
|
||||
maxNumLabels = layer->customProperty( "labeling/maxNumLabels", QVariant( 2000 ) ).toInt();
|
||||
obstacle = layer->customProperty( "labeling/obstacle", QVariant( true ) ).toBool();
|
||||
obstacleFactor = layer->customProperty( "labeling/obstacleFactor", QVariant( 1.0 ) ).toDouble();
|
||||
obstacleType = ( ObstacleType )layer->customProperty( "labeling/obstacleType", QVariant( PolygonInterior ) ).toUInt();
|
||||
|
||||
readDataDefinedPropertyMap( layer, dataDefinedProperties );
|
||||
@ -1077,6 +1081,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
|
||||
layer->setCustomProperty( "labeling/limitNumLabels", limitNumLabels );
|
||||
layer->setCustomProperty( "labeling/maxNumLabels", maxNumLabels );
|
||||
layer->setCustomProperty( "labeling/obstacle", obstacle );
|
||||
layer->setCustomProperty( "labeling/obstacleFactor", obstacleFactor );
|
||||
layer->setCustomProperty( "labeling/obstacleType", ( unsigned int )obstacleType );
|
||||
|
||||
writeDataDefinedPropertyMap( layer, dataDefinedProperties );
|
||||
@ -2214,6 +2219,20 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
|
||||
feat->setIsObstacle( exprVal.toBool() );
|
||||
}
|
||||
|
||||
double featObstacleFactor = obstacleFactor;
|
||||
if ( dataDefinedEvaluate( QgsPalLayerSettings::ObstacleFactor, exprVal ) )
|
||||
{
|
||||
bool ok;
|
||||
double factorD = exprVal.toDouble( &ok );
|
||||
if ( ok )
|
||||
{
|
||||
factorD = qBound( 0.0, factorD, 10.0 );
|
||||
factorD = factorD / 5.0 + 0.0001; // convert 0 -> 10 to 0.0001 -> 2.0
|
||||
featObstacleFactor = factorD;
|
||||
}
|
||||
}
|
||||
feat->setObstacleFactor( featObstacleFactor );
|
||||
|
||||
//add parameters for data defined labeling to QgsPalGeometry
|
||||
QMap< DataDefinedProperties, QVariant >::const_iterator dIt = dataDefinedValues.constBegin();
|
||||
for ( ; dIt != dataDefinedValues.constEnd(); ++dIt )
|
||||
|
@ -274,6 +274,7 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
FontMinPixel = 25,
|
||||
FontMaxPixel = 26,
|
||||
IsObstacle = 88,
|
||||
ObstacleFactor = 89,
|
||||
|
||||
// (data defined only)
|
||||
Show = 15,
|
||||
@ -445,6 +446,11 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
double minFeatureSize; // minimum feature size to be labelled (in mm)
|
||||
bool obstacle; // whether features for layer are obstacles to labels of other layers
|
||||
|
||||
/** Obstacle factor, where 1.0 = default, < 1.0 more likely to be covered by labels,
|
||||
* > 1.0 less likely to be covered
|
||||
*/
|
||||
double obstacleFactor;
|
||||
|
||||
/** Controls how features act as obstacles for labels
|
||||
*/
|
||||
ObstacleType obstacleType;
|
||||
|
@ -3488,8 +3488,8 @@ font-style: italic;</string>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>427</width>
|
||||
<y>-466</y>
|
||||
<width>578</width>
|
||||
<height>829</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -4818,9 +4818,9 @@ font-style: italic;</string>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-361</y>
|
||||
<y>-401</y>
|
||||
<width>578</width>
|
||||
<height>724</height>
|
||||
<height>764</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
@ -5517,6 +5517,58 @@ font-style: italic;</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="mObstaclePriorityFrame">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_18">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="text">
|
||||
<string>Low priority</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="mObstacleFactorSlider">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_41">
|
||||
<property name="text">
|
||||
<string>High priority</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsDataDefinedButton" name="mObstacleFactorDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="mPolygonObstacleTypeFrame">
|
||||
<property name="frameShape">
|
||||
@ -5981,8 +6033,8 @@ font-style: italic;</string>
|
||||
<slot>setCurrentIndex(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>47</x>
|
||||
<y>524</y>
|
||||
<x>34</x>
|
||||
<y>599</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>633</x>
|
||||
|
Loading…
x
Reference in New Issue
Block a user