Skip to content

Commit

Permalink
Prioritize moving unplaced labels in the move label tool
Browse files Browse the repository at this point in the history
These are most likely the ones which users are trying to move
when there's overlapping labels
  • Loading branch information
nyalldawson committed Jul 21, 2019
1 parent 87282e5 commit bae321a
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 6 deletions.
5 changes: 4 additions & 1 deletion python/core/auto_generated/qgspallabeling.sip.in
Expand Up @@ -20,7 +20,7 @@ class QgsLabelPosition
public:

QgsLabelPosition( QgsFeatureId id, double r, const QVector< QgsPointXY > &corners, const QgsRectangle &rect, double w, double h, const QString &layer, const QString &labeltext, const QFont &labelfont, bool upside_down, bool diagram = false, bool pinned = false, const QString &providerId = QString(),
const QgsGeometry &labelGeometry = QgsGeometry() );
const QgsGeometry &labelGeometry = QgsGeometry(), bool isUnplaced = false );
%Docstring
Constructor for QgsLabelPosition.

Expand All @@ -38,6 +38,7 @@ Constructor for QgsLabelPosition.
:param pinned: ``True`` if label has pinned placement
:param providerId: ID of associated label provider
:param labelGeometry: polygon geometry of label boundary
:param isUnplaced: set to ``True`` if label was unplaced (e.g. due to collisions with other labels)
%End

QgsLabelPosition();
Expand Down Expand Up @@ -71,6 +72,8 @@ Constructor for QgsLabelPosition
bool isPinned;

QString providerID;

bool isUnplaced;
};


Expand Down
12 changes: 12 additions & 0 deletions src/app/qgsmaptoollabel.cpp
Expand Up @@ -71,6 +71,18 @@ bool QgsMapToolLabel::labelAtPosition( QMouseEvent *e, QgsLabelPosition &p )
if ( !activeLayerLabels.empty() )
labelPosList = activeLayerLabels;

// prioritize unplaced labels
QList<QgsLabelPosition> unplacedLabels;
for ( const QgsLabelPosition &pos : qgis::as_const( labelPosList ) )
{
if ( pos.isUnplaced )
{
unplacedLabels.append( pos );
}
}
if ( !unplacedLabels.empty() )
labelPosList = unplacedLabels;

if ( labelPosList.count() > 1 )
{
// multiple candidates found, so choose the smallest (i.e. most difficult to select otherwise)
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgslabelsearchtree.cpp
Expand Up @@ -75,7 +75,7 @@ void QgsLabelSearchTree::labelsInRect( const QgsRectangle &r, QList<QgsLabelPosi
}
}

bool QgsLabelSearchTree::insertLabel( pal::LabelPosition *labelPos, QgsFeatureId featureId, const QString &layerName, const QString &labeltext, const QFont &labelfont, bool diagram, bool pinned, const QString &providerId )
bool QgsLabelSearchTree::insertLabel( pal::LabelPosition *labelPos, QgsFeatureId featureId, const QString &layerName, const QString &labeltext, const QFont &labelfont, bool diagram, bool pinned, const QString &providerId, bool isUnplaced )
{
if ( !labelPos )
{
Expand Down Expand Up @@ -107,7 +107,7 @@ bool QgsLabelSearchTree::insertLabel( pal::LabelPosition *labelPos, QgsFeatureId

QgsGeometry labelGeometry( QgsGeometry::fromPolygonXY( QVector<QgsPolylineXY>() << cornerPoints ) );
std::unique_ptr< QgsLabelPosition > newEntry = qgis::make_unique< QgsLabelPosition >( featureId, labelPos->getAlpha() + mMapSettings.rotation(), cornerPoints, QgsRectangle( c_min[0], c_min[1], c_max[0], c_max[1] ),
labelPos->getWidth(), labelPos->getHeight(), layerName, labeltext, labelfont, labelPos->getUpsideDown(), diagram, pinned, providerId, labelGeometry );
labelPos->getWidth(), labelPos->getHeight(), layerName, labeltext, labelfont, labelPos->getUpsideDown(), diagram, pinned, providerId, labelGeometry, isUnplaced );
mSpatialIndex.Insert( c_min, c_max, newEntry.get() );
mOwnedPositions.emplace_back( std::move( newEntry ) );

Expand Down
2 changes: 1 addition & 1 deletion src/core/qgslabelsearchtree.h
Expand Up @@ -79,7 +79,7 @@ class CORE_EXPORT QgsLabelSearchTree
* \returns TRUE in case of success
* \note not available in Python bindings
*/
bool insertLabel( pal::LabelPosition *labelPos, QgsFeatureId featureId, const QString &layerName, const QString &labeltext, const QFont &labelfont, bool diagram = false, bool pinned = false, const QString &providerId = QString() ) SIP_SKIP;
bool insertLabel( pal::LabelPosition *labelPos, QgsFeatureId featureId, const QString &layerName, const QString &labeltext, const QFont &labelfont, bool diagram = false, bool pinned = false, const QString &providerId = QString(), bool isUnplaced = false ) SIP_SKIP;

/**
* Sets the map \a settings associated with the labeling run.
Expand Down
10 changes: 9 additions & 1 deletion src/core/qgspallabeling.h
Expand Up @@ -97,9 +97,10 @@ class CORE_EXPORT QgsLabelPosition
* \param pinned TRUE if label has pinned placement
* \param providerId ID of associated label provider
* \param labelGeometry polygon geometry of label boundary
* \param isUnplaced set to TRUE if label was unplaced (e.g. due to collisions with other labels)
*/
QgsLabelPosition( QgsFeatureId id, double r, const QVector< QgsPointXY > &corners, const QgsRectangle &rect, double w, double h, const QString &layer, const QString &labeltext, const QFont &labelfont, bool upside_down, bool diagram = false, bool pinned = false, const QString &providerId = QString(),
const QgsGeometry &labelGeometry = QgsGeometry() )
const QgsGeometry &labelGeometry = QgsGeometry(), bool isUnplaced = false )
: featureId( id )
, rotation( r )
, cornerPoints( corners )
Expand All @@ -114,6 +115,7 @@ class CORE_EXPORT QgsLabelPosition
, isDiagram( diagram )
, isPinned( pinned )
, providerID( providerId )
, isUnplaced( isUnplaced )
{}

//! Constructor for QgsLabelPosition
Expand Down Expand Up @@ -183,6 +185,12 @@ class CORE_EXPORT QgsLabelPosition
* \since QGIS 2.14
*/
QString providerID;

/**
* TRUE if label position corresponds to an unplaced label.
* \since QGIS 3.10
*/
bool isUnplaced = false;
};


Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsvectorlayerlabelprovider.cpp
Expand Up @@ -439,7 +439,7 @@ void QgsVectorLayerLabelProvider::drawUnplacedLabel( QgsRenderContext &context,

// add to the results
QString labeltext = label->getFeaturePart()->feature()->labelText();
mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, tmpLyr.format().font(), false, lf->hasFixedPosition(), mProviderId );
mEngine->results()->mLabelSearchTree->insertLabel( label, label->getFeaturePart()->featureId(), mLayerId, labeltext, tmpLyr.format().font(), false, lf->hasFixedPosition(), mProviderId, true );
}

void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, QgsRenderContext &context, QgsPalLayerSettings &tmpLyr, QgsTextRenderer::TextPart drawType, double dpiRatio ) const
Expand Down

0 comments on commit bae321a

Please sign in to comment.