Skip to content

Commit b80e252

Browse files
committedAug 31, 2020
[rotated_ticks] allow to set a margin for outwards facing annotations
to help avoiding overlaps and/or out of bounds annotations
1 parent 04c5b81 commit b80e252

File tree

5 files changed

+162
-6
lines changed

5 files changed

+162
-6
lines changed
 

‎src/core/layout/qgslayoutitemmapgrid.cpp

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,11 @@ bool QgsLayoutItemMapGrid::writeXml( QDomElement &elem, QDomDocument &doc, const
278278
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksLengthMode" ), mRotatedTicksLengthMode );
279279
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksEnabled" ), mRotatedTicksEnabled );
280280
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksMinimumAngle" ), QString::number( mRotatedTicksMinimumAngle ) );
281+
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksMarginToCorner" ), QString::number( mRotatedTicksMarginToCorner ) );
281282
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsLengthMode" ), mRotatedAnnotationsLengthMode );
282283
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsEnabled" ), mRotatedAnnotationsEnabled );
283284
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsMinimumAngle" ), QString::number( mRotatedAnnotationsMinimumAngle ) );
285+
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsMarginToCorner" ), QString::number( mRotatedAnnotationsMarginToCorner ) );
284286
if ( mCRS.isValid() )
285287
{
286288
mCRS.writeXml( mapGridElem, doc );
@@ -346,9 +348,11 @@ bool QgsLayoutItemMapGrid::readXml( const QDomElement &itemElem, const QDomDocum
346348
mRotatedTicksLengthMode = TickLengthMode( itemElem.attribute( QStringLiteral( "rotatedTicksLengthMode" ), QStringLiteral( "0" ) ).toInt() );
347349
mRotatedTicksEnabled = itemElem.attribute( QStringLiteral( "rotatedTicksEnabled" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
348350
mRotatedTicksMinimumAngle = itemElem.attribute( QStringLiteral( "rotatedTicksMinimumAngle" ), QStringLiteral( "0" ) ).toDouble();
351+
mRotatedTicksMarginToCorner = itemElem.attribute( QStringLiteral( "rotatedTicksMarginToCorner" ), QStringLiteral( "0" ) ).toDouble();
349352
mRotatedAnnotationsLengthMode = TickLengthMode( itemElem.attribute( QStringLiteral( "rotatedAnnotationsLengthMode" ), QStringLiteral( "0" ) ).toInt() );
350353
mRotatedAnnotationsEnabled = itemElem.attribute( QStringLiteral( "rotatedAnnotationsEnabled" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
351354
mRotatedAnnotationsMinimumAngle = itemElem.attribute( QStringLiteral( "rotatedAnnotationsMinimumAngle" ), QStringLiteral( "0" ) ).toDouble();
355+
mRotatedAnnotationsMarginToCorner = itemElem.attribute( QStringLiteral( "rotatedAnnotationsMarginToCorner" ), QStringLiteral( "0" ) ).toDouble();
352356

353357
QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral( "lineStyle" ) );
354358
if ( !lineStyleElem.isNull() )
@@ -666,9 +670,9 @@ void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions() const
666670
it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
667671
it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
668672
QVector2D normS = borderToNormal2D( it->startAnnotation.border );
669-
it->startAnnotation.angle = abs( M_PI / 2.0 - acos( QVector2D::dotProduct( it->startAnnotation.vector, normS ) / ( it->startAnnotation.vector.length() * normS.length() ) ) );
673+
it->startAnnotation.angle = atan2( it->startAnnotation.vector.x() * normS.y() - it->startAnnotation.vector.y() * normS.x(), it->startAnnotation.vector.x() * normS.x() + it->startAnnotation.vector.y() * normS.y() );
670674
QVector2D normE = borderToNormal2D( it->endAnnotation.border );
671-
it->endAnnotation.angle = abs( M_PI / 2.0 - acos( QVector2D::dotProduct( it->endAnnotation.vector, normE ) / ( it->endAnnotation.vector.length() * normE.length() ) ) );
675+
it->endAnnotation.angle = atan2( it->endAnnotation.vector.x() * normE.y() - it->endAnnotation.vector.y() * normE.x(), it->endAnnotation.vector.x() * normE.x() + it->endAnnotation.vector.y() * normE.y() );
672676
}
673677
}
674678

@@ -1013,7 +1017,39 @@ void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *exten
10131017
continue;
10141018

10151019
// If the angle is below the threshold, we don't draw the annotation
1016-
if ( annot.angle < mRotatedTicksMinimumAngle * M_PI / 180.0 )
1020+
if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle )
1021+
continue;
1022+
1023+
// Skip outwards facing annotations that are below mRotatedTicksMarginToCorner
1024+
bool facingLeft;
1025+
bool facingRight;
1026+
if ( mGridFrameStyle == QgsLayoutItemMapGrid::InteriorExteriorTicks )
1027+
{
1028+
facingLeft = ( annot.angle != 0 );
1029+
facingRight = ( annot.angle != 0 );
1030+
}
1031+
else if ( mGridFrameStyle == QgsLayoutItemMapGrid::ExteriorTicks )
1032+
{
1033+
facingLeft = ( annot.angle > 0 );
1034+
facingRight = ( annot.angle < 0 );
1035+
}
1036+
else
1037+
{
1038+
facingLeft = ( annot.angle < 0 );
1039+
facingRight = ( annot.angle > 0 );
1040+
}
1041+
1042+
if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) ||
1043+
( facingRight && annot.position.x() > mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1044+
continue;
1045+
if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() > mMap->rect().width() - mRotatedTicksMarginToCorner ) ||
1046+
( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1047+
continue;
1048+
if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() > mMap->rect().height() - mRotatedTicksMarginToCorner ) ||
1049+
( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1050+
continue;
1051+
if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) ||
1052+
( facingRight && annot.position.y() > mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
10171053
continue;
10181054

10191055
QVector2D normalVector = borderToNormal2D( annot.border );
@@ -1179,9 +1215,8 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QgsRenderContext &context,
11791215
AnnotationPosition anotPos = annotationPosition( frameBorder );
11801216
AnnotationDirection anotDir = annotationDirection( frameBorder );
11811217

1182-
11831218
// If the angle is below the threshold, we don't draw the annotation
1184-
if ( annot.angle < mRotatedAnnotationsMinimumAngle * M_PI / 180.0 )
1219+
if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle )
11851220
return;
11861221

11871222
QVector2D normalVector = borderToNormal2D( annot.border );
@@ -1302,10 +1337,30 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QgsRenderContext &context,
13021337
extension->UpdateAll( textWidth / 2.0 );
13031338
}
13041339

1305-
13061340
if ( extension || !context.painter() )
13071341
return;
13081342

1343+
// Skip outwards facing annotations that are below mRotatedAnnotationsMarginToCorner
1344+
bool facingLeft = ( annot.angle < 0 );
1345+
bool facingRight = ( annot.angle > 0 );
1346+
if ( anotPos == QgsLayoutItemMapGrid::OutsideMapFrame )
1347+
{
1348+
facingLeft = !facingLeft;
1349+
facingRight = !facingRight;
1350+
}
1351+
if ( annot.border == BorderSide::Top && ( ( facingLeft && xpos < mRotatedAnnotationsMarginToCorner ) ||
1352+
( facingRight && xpos > mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
1353+
return;
1354+
if ( annot.border == BorderSide::Bottom && ( ( facingLeft && xpos > mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ||
1355+
( facingRight && xpos < mRotatedAnnotationsMarginToCorner ) ) )
1356+
return;
1357+
if ( annot.border == BorderSide::Left && ( ( facingLeft && ypos > mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ||
1358+
( facingRight && ypos < mRotatedAnnotationsMarginToCorner ) ) )
1359+
return;
1360+
if ( annot.border == BorderSide::Right && ( ( facingLeft && ypos < mRotatedAnnotationsMarginToCorner ) ||
1361+
( facingRight && ypos > mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
1362+
return;
1363+
13091364
QgsScopedQPainterState painterState( context.painter() );
13101365
context.painter()->translate( QPointF( xpos, ypos ) );
13111366
context.painter()->rotate( rotation );

‎src/core/layout/qgslayoutitemmapgrid.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,18 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
846846
*/
847847
double rotatedTicksMinimumAngle() const { return mRotatedTicksMinimumAngle; }
848848

849+
/**
850+
* Sets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
851+
* \see rotatedTicksMarginToCorner()
852+
*/
853+
void setRotatedTicksMarginToCorner( const double margin ) { mRotatedTicksMarginToCorner = margin; }
854+
855+
/**
856+
* Gets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
857+
* \see setRotatedTicksMarginToCorner()
858+
*/
859+
double rotatedTicksMarginToCorner() const { return mRotatedTicksMarginToCorner; }
860+
849861
/**
850862
* Enable/disable annotations rotation for rotated or reprojected grids.
851863
* \see rotatedAnnotationsEnabled()
@@ -882,6 +894,18 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
882894
*/
883895
double rotatedAnnotationsMinimumAngle() const { return mRotatedAnnotationsMinimumAngle; }
884896

897+
/**
898+
* Sets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
899+
* \see rotatedAnnotationsMarginToCorner()
900+
*/
901+
void setRotatedAnnotationsMarginToCorner( const double margin ) { mRotatedAnnotationsMarginToCorner = margin; }
902+
903+
/**
904+
* Gets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
905+
* \see setRotatedAnnotationsMarginToCorner()
906+
*/
907+
double rotatedAnnotationsMarginToCorner() const { return mRotatedAnnotationsMarginToCorner; }
908+
885909
/**
886910
* Sets the grid frame margin (in layout units).
887911
* This property controls distance between the map frame and the grid frame.
@@ -1103,9 +1127,11 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
11031127
bool mRotatedTicksEnabled = false;
11041128
TickLengthMode mRotatedTicksLengthMode = QgsLayoutItemMapGrid::OrthogonalTicks;
11051129
double mRotatedTicksMinimumAngle = 0.0;
1130+
double mRotatedTicksMarginToCorner = 0.0;
11061131
bool mRotatedAnnotationsEnabled = false;
11071132
TickLengthMode mRotatedAnnotationsLengthMode = QgsLayoutItemMapGrid::OrthogonalTicks;
11081133
double mRotatedAnnotationsMinimumAngle = 0.0;
1134+
double mRotatedAnnotationsMarginToCorner = 0.0;
11091135

11101136
double mMinimumIntervalWidth = 50;
11111137
double mMaximumIntervalWidth = 100;

‎src/gui/layout/qgslayoutmapgridwidget.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ QgsLayoutMapGridWidget::QgsLayoutMapGridWidget( QgsLayoutItemMapGrid *mapGrid, Q
6666
connect( mRotatedTicksCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapGridWidget::mRotatedTicksCheckBox_toggled );
6767
connect( mRotatedTicksLengthModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapGridWidget::mRotatedTicksLengthModeComboBox_currentIndexChanged );
6868
connect( mRotatedTicksThresholdSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedTicksThresholdSpinBox_valueChanged );
69+
connect( mRotatedTicksMarginToCornerSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedTicksMarginToCornerSpinBox_valueChanged );
6970
connect( mRotatedAnnotationsCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapGridWidget::mRotatedAnnotationsCheckBox_toggled );
7071
connect( mRotatedAnnotationsLengthModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapGridWidget::mRotatedAnnotationsLengthModeComboBox_currentIndexChanged );
7172
connect( mRotatedAnnotationsThresholdSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedAnnotationsThresholdSpinBox_valueChanged );
73+
connect( mRotatedAnnotationsMarginToCornerSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedAnnotationsMarginToCornerSpinBox_valueChanged );
7274
connect( mGridFramePenSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mGridFramePenSizeSpinBox_valueChanged );
7375
connect( mGridFramePenColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutMapGridWidget::mGridFramePenColorButton_colorChanged );
7476
connect( mGridFrameFill1ColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutMapGridWidget::mGridFrameFill1ColorButton_colorChanged );
@@ -345,6 +347,7 @@ void QgsLayoutMapGridWidget::toggleFrameControls( bool frameEnabled, bool frameF
345347
mRotatedTicksCheckBox->setEnabled( rotationEnabled );
346348
mRotatedTicksLengthModeComboBox->setEnabled( rotationEnabled );
347349
mRotatedTicksThresholdSpinBox->setEnabled( rotationEnabled );
350+
mRotatedTicksMarginToCornerSpinBox->setEnabled( rotationEnabled );
348351
}
349352

350353
void QgsLayoutMapGridWidget::insertAnnotationPositionEntries( QComboBox *c )
@@ -567,10 +570,12 @@ void QgsLayoutMapGridWidget::setGridItems()
567570
mRotatedTicksCheckBox->setChecked( mMapGrid->rotatedTicksEnabled() );
568571
mRotatedTicksLengthModeComboBox->setCurrentIndex( mRotatedTicksLengthModeComboBox->findData( mMapGrid->rotatedTicksLengthMode() ) );
569572
mRotatedTicksThresholdSpinBox->setValue( mMapGrid->rotatedTicksMinimumAngle() );
573+
mRotatedTicksMarginToCornerSpinBox->setValue( mMapGrid->rotatedTicksMarginToCorner() );
570574

571575
mRotatedAnnotationsCheckBox->setChecked( mMapGrid->rotatedAnnotationsEnabled() );
572576
mRotatedAnnotationsLengthModeComboBox->setCurrentIndex( mRotatedAnnotationsLengthModeComboBox->findData( mMapGrid->rotatedAnnotationsLengthMode() ) );
573577
mRotatedAnnotationsThresholdSpinBox->setValue( mMapGrid->rotatedAnnotationsMinimumAngle() );
578+
mRotatedAnnotationsMarginToCornerSpinBox->setValue( mMapGrid->rotatedAnnotationsMarginToCorner() );
574579

575580
initFrameDisplayBox( mFrameDivisionsLeftComboBox, mMapGrid->frameDivisions( QgsLayoutItemMapGrid::Left ) );
576581
initFrameDisplayBox( mFrameDivisionsRightComboBox, mMapGrid->frameDivisions( QgsLayoutItemMapGrid::Right ) );
@@ -931,6 +936,20 @@ void QgsLayoutMapGridWidget::mRotatedTicksThresholdSpinBox_valueChanged( double
931936
mMap->update();
932937
mMap->endCommand();
933938
}
939+
940+
void QgsLayoutMapGridWidget::mRotatedTicksMarginToCornerSpinBox_valueChanged( double val )
941+
{
942+
if ( !mMapGrid || !mMap )
943+
{
944+
return;
945+
}
946+
947+
mMap->beginCommand( tr( "Change Rotated Ticks Margin to Corner" ) );
948+
mMapGrid->setRotatedTicksMarginToCorner( val );
949+
mMap->update();
950+
mMap->endCommand();
951+
}
952+
934953
void QgsLayoutMapGridWidget::mRotatedAnnotationsCheckBox_toggled( bool state )
935954
{
936955
if ( !mMapGrid || !mMap )
@@ -971,6 +990,18 @@ void QgsLayoutMapGridWidget::mRotatedAnnotationsThresholdSpinBox_valueChanged( d
971990
mMap->endCommand();
972991
}
973992

993+
void QgsLayoutMapGridWidget::mRotatedAnnotationsMarginToCornerSpinBox_valueChanged( double val )
994+
{
995+
if ( !mMapGrid || !mMap )
996+
{
997+
return;
998+
}
999+
1000+
mMap->beginCommand( tr( "Change Rotated Annotations Margin to Corner" ) );
1001+
mMapGrid->setRotatedAnnotationsMarginToCorner( val );
1002+
mMap->update();
1003+
mMap->endCommand();
1004+
}
9741005

9751006
void QgsLayoutMapGridWidget::intervalUnitChanged( int )
9761007
{

‎src/gui/layout/qgslayoutmapgridwidget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,11 @@ class GUI_EXPORT QgsLayoutMapGridWidget: public QgsLayoutItemBaseWidget, private
5353
void mRotatedTicksCheckBox_toggled( bool checked );
5454
void mRotatedTicksLengthModeComboBox_currentIndexChanged( int );
5555
void mRotatedTicksThresholdSpinBox_valueChanged( double val );
56+
void mRotatedTicksMarginToCornerSpinBox_valueChanged( double val );
5657
void mRotatedAnnotationsCheckBox_toggled( bool checked );
5758
void mRotatedAnnotationsLengthModeComboBox_currentIndexChanged( int );
5859
void mRotatedAnnotationsThresholdSpinBox_valueChanged( double val );
60+
void mRotatedAnnotationsMarginToCornerSpinBox_valueChanged( double val );
5961
void mGridFrameMarginSpinBox_valueChanged( double val );
6062
void mFrameStyleComboBox_currentIndexChanged( int );
6163
void mGridFramePenSizeSpinBox_valueChanged( double d );

‎src/ui/layout/qgslayoutmapgridwidgetbase.ui

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,26 @@
717717
</property>
718718
</widget>
719719
</item>
720+
<item row="17" column="0">
721+
<widget class="QLabel" name="label_annot_corner">
722+
<property name="text">
723+
<string>Margin to map corner</string>
724+
</property>
725+
</widget>
726+
</item>
727+
<item row="17" column="1" colspan="4">
728+
<widget class="QDoubleSpinBox" name="mRotatedTicksMarginToCornerSpinBox">
729+
<property name="toolTip">
730+
<string>Outwards facing ticks closer to the corners that this margin will be ignored. This only makes sense for rotated grids.</string>
731+
</property>
732+
<property name="decimals">
733+
<number>0</number>
734+
</property>
735+
<property name="value">
736+
<double>0.000000000000000</double>
737+
</property>
738+
</widget>
739+
</item>
720740
</layout>
721741
</widget>
722742
</item>
@@ -944,6 +964,26 @@
944964
</property>
945965
</widget>
946966
</item>
967+
<item row="20" column="0">
968+
<widget class="QLabel" name="label_12">
969+
<property name="text">
970+
<string>Margin to map corner</string>
971+
</property>
972+
</widget>
973+
</item>
974+
<item row="20" column="1" colspan="2">
975+
<widget class="QDoubleSpinBox" name="mRotatedAnnotationsMarginToCornerSpinBox">
976+
<property name="toolTip">
977+
<string>Outwards facing annotations closer to the corners that this margin will be ignored. This only makes sense for rotated grids.</string>
978+
</property>
979+
<property name="decimals">
980+
<number>0</number>
981+
</property>
982+
<property name="value">
983+
<double>0.000000000000000</double>
984+
</property>
985+
</widget>
986+
</item>
947987
</layout>
948988
</widget>
949989
</item>
@@ -1048,6 +1088,7 @@
10481088
<tabstop>mRotatedTicksCheckBox</tabstop>
10491089
<tabstop>mRotatedTicksLengthModeComboBox</tabstop>
10501090
<tabstop>mRotatedTicksThresholdSpinBox</tabstop>
1091+
<tabstop>mRotatedTicksMarginToCornerSpinBox</tabstop>
10511092
<tabstop>mDrawAnnotationGroupBox</tabstop>
10521093
<tabstop>mAnnotationFormatComboBox</tabstop>
10531094
<tabstop>mAnnotationFormatButton</tabstop>
@@ -1070,6 +1111,7 @@
10701111
<tabstop>mRotatedAnnotationsCheckBox</tabstop>
10711112
<tabstop>mRotatedAnnotationsLengthModeComboBox</tabstop>
10721113
<tabstop>mRotatedAnnotationsThresholdSpinBox</tabstop>
1114+
<tabstop>mRotatedAnnotationsMarginToCornerSpinBox</tabstop>
10731115
</tabstops>
10741116
<resources>
10751117
<include location="../../../images/images.qrc"/>

0 commit comments

Comments
 (0)
Please sign in to comment.