Skip to content

Commit

Permalink
[ui] Fix moving of label on polygon layers _along_ the perimeter
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn authored and nyalldawson committed Jun 22, 2023
1 parent c9e0970 commit cccfe07
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 10 deletions.
3 changes: 2 additions & 1 deletion src/app/labeling/qgsmaptoollabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ void QgsMapToolLabel::createRubberBands()
// instead, just use the boundary of the polygon for the rubber band
geom = QgsGeometry( geom.constGet()->boundary() );
}
else if ( geom.type() == Qgis::GeometryType::Line )

if ( geom.type() == Qgis::GeometryType::Line || geom.type() == Qgis::GeometryType::Polygon )
{
mOffsetFromLineStartRubberBand = new QgsRubberBand( mCanvas, Qgis::GeometryType::Point );
mOffsetFromLineStartRubberBand->setColor( lineColor );
Expand Down
31 changes: 24 additions & 7 deletions src/app/labeling/qgsmaptoolmovelabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e )
{
const QgsPointXY pointMapCoords = e->mapPoint();

bool isCurvedOrLine { mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line };
bool isCurvedOrLine = mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::PerimeterCurved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line;
if ( isCurvedOrLine )
{
// Determine the closest point on the feature
Expand All @@ -81,7 +81,15 @@ void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e )

// In map's CRS
const QgsGeometry pointMapGeometry { QgsGeometry::fromPointXY( pointMapCoords ) };
QgsGeometry featureMapGeometry { feature.geometry() };
QgsGeometry featureMapGeometry;
if ( feature.geometry().type() == Qgis::GeometryType::Polygon )
{
featureMapGeometry = QgsGeometry( feature.geometry().constGet()->boundary() );
}
else
{
featureMapGeometry = feature.geometry();
}
featureMapGeometry.transform( ms.layerTransform( mCurrentLabel.layer ) );

if ( featureMapGeometry.distance( pointMapGeometry ) / mCanvas->mapUnitsPerPixel() > mLabelTearFromLineThreshold )
Expand Down Expand Up @@ -251,7 +259,7 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
mCurrentLabel.settings.placement = Qgis::LabelPlacement::Horizontal;
}

const bool isCurvedOrLine { mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line };
const bool isCurvedOrLine = mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::PerimeterCurved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line;

if ( isCurvedOrLine && !mCurrentLabel.pos.isDiagram && ! labelAnchorPercentMovable( vlayer, mCurrentLabel.settings, lineAnchorPercentCol, lineAnchorClippingCol, lineAnchorTypeCol, lineAnchorTextPointCol ) )
{
Expand Down Expand Up @@ -424,7 +432,7 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
bool lineAnchorTypeSuccess = false;
bool lineAnchorTextPointSuccess = false;

bool isCurvedOrLine { ! mAnchorDetached &&( mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line ) };
bool isCurvedOrLine = !mAnchorDetached && ( mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::PerimeterCurved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line );

if ( !isCalloutMove && isCurvedOrLine && !currentLabelDataDefinedLineAnchorPercent( lineAnchorPercentOrig, lineAnchorPercentSuccess, lineAnchorPercentCol,
lineAnchorClippingOrig, lineAnchorClippingSuccess, lineAnchorClippingCol,
Expand All @@ -445,15 +453,24 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
// Handle curved offset
if ( isCurvedOrLine )
{

const QgsFeature feature { mCurrentLabel.layer->getFeature( featureId ) };
const QgsMapSettings &ms = mCanvas->mapSettings();

// In layer's CRS:
const QgsPointXY releaseCoordsTransformed = ms.mapToLayerCoordinates( mCurrentLabel.layer, releaseCoords );
const QgsGeometry releaseCoordsGeometry = QgsGeometry::fromPointXY( releaseCoordsTransformed );

const double lineAnchorPercent { feature.geometry().lineLocatePoint( releaseCoordsGeometry ) / feature.geometry().length() };
double lineAnchorPercent = 0.0;
if ( feature.geometry().type() == Qgis::GeometryType::Polygon )
{
QgsGeometry boundary( feature.geometry().constGet()->boundary() );
lineAnchorPercent = boundary.lineLocatePoint( releaseCoordsGeometry ) / boundary.length();
}
else
{
lineAnchorPercent = feature.geometry().lineLocatePoint( releaseCoordsGeometry ) / feature.geometry().length();
}

vlayer->beginEditCommand( tr( "Moved curved label offset" ) + QStringLiteral( " '%1'" ).arg( currentLabelText( 24 ) ) );
bool success = false;

Expand Down Expand Up @@ -648,7 +665,7 @@ void QgsMapToolMoveLabel::keyReleaseEvent( QKeyEvent *e )
// delete the stored label/callout position
mAnchorDetached = false;
const bool isCalloutMove = !mCurrentCallout.layerID.isEmpty();
const bool isCurvedOrLine { mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line };
const bool isCurvedOrLine = mCurrentLabel.settings.placement == Qgis::LabelPlacement::Curved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::PerimeterCurved || mCurrentLabel.settings.placement == Qgis::LabelPlacement::Line;
QgsVectorLayer *vlayer = !isCalloutMove ? mCurrentLabel.layer : qobject_cast< QgsVectorLayer * >( QgsMapTool::layer( mCurrentCallout.layerID ) );
const QgsFeatureId featureId = !isCalloutMove ? mCurrentLabel.pos.featureId : mCurrentCallout.featureId;
if ( vlayer )
Expand Down
2 changes: 1 addition & 1 deletion src/core/labeling/qgspallabeling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2227,7 +2227,7 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
QgsLabelLineSettings lineSettings = mLineSettings;
lineSettings.updateDataDefinedProperties( mDataDefinedProperties, context.expressionContext() );

if ( geom.type() == Qgis::GeometryType::Line )
if ( geom.type() == Qgis::GeometryType::Line || placement == Qgis::LabelPlacement::Line || placement == Qgis::LabelPlacement::PerimeterCurved )
{
switch ( lineSettings.anchorClipping() )
{
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgstextformatwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,7 @@ void QgsTextFormatWidget::updatePlacementWidgets()
mPlacementRepeatGroupBox->setVisible( currentGeometryType == Qgis::GeometryType::Line || ( currentGeometryType == Qgis::GeometryType::Polygon &&
( currentPlacement == Qgis::LabelPlacement::Line || currentPlacement == Qgis::LabelPlacement::PerimeterCurved ) ) );
mPlacementOverrunGroupBox->setVisible( currentGeometryType == Qgis::GeometryType::Line && currentPlacement != Qgis::LabelPlacement::Horizontal );
mLineAnchorGroupBox->setVisible( currentGeometryType == Qgis::GeometryType::Line );
mLineAnchorGroupBox->setVisible( currentGeometryType == Qgis::GeometryType::Line || currentPlacement == Qgis::LabelPlacement::Line || currentPlacement == Qgis::LabelPlacement::PerimeterCurved );
mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );

mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
Expand Down

0 comments on commit cccfe07

Please sign in to comment.