Skip to content
Permalink
Browse files

[rotated_ticks] allow to set a margin for outwards facing annotations

to help avoiding overlaps and/or out of bounds annotations
  • Loading branch information
olivierdalang committed Aug 31, 2020
1 parent 04c5b81 commit b80e252a4e76ec247795d02c537a63430ad66b8d
@@ -278,9 +278,11 @@ bool QgsLayoutItemMapGrid::writeXml( QDomElement &elem, QDomDocument &doc, const
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksLengthMode" ), mRotatedTicksLengthMode );
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksEnabled" ), mRotatedTicksEnabled );
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksMinimumAngle" ), QString::number( mRotatedTicksMinimumAngle ) );
mapGridElem.setAttribute( QStringLiteral( "rotatedTicksMarginToCorner" ), QString::number( mRotatedTicksMarginToCorner ) );
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsLengthMode" ), mRotatedAnnotationsLengthMode );
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsEnabled" ), mRotatedAnnotationsEnabled );
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsMinimumAngle" ), QString::number( mRotatedAnnotationsMinimumAngle ) );
mapGridElem.setAttribute( QStringLiteral( "rotatedAnnotationsMarginToCorner" ), QString::number( mRotatedAnnotationsMarginToCorner ) );
if ( mCRS.isValid() )
{
mCRS.writeXml( mapGridElem, doc );
@@ -346,9 +348,11 @@ bool QgsLayoutItemMapGrid::readXml( const QDomElement &itemElem, const QDomDocum
mRotatedTicksLengthMode = TickLengthMode( itemElem.attribute( QStringLiteral( "rotatedTicksLengthMode" ), QStringLiteral( "0" ) ).toInt() );
mRotatedTicksEnabled = itemElem.attribute( QStringLiteral( "rotatedTicksEnabled" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
mRotatedTicksMinimumAngle = itemElem.attribute( QStringLiteral( "rotatedTicksMinimumAngle" ), QStringLiteral( "0" ) ).toDouble();
mRotatedTicksMarginToCorner = itemElem.attribute( QStringLiteral( "rotatedTicksMarginToCorner" ), QStringLiteral( "0" ) ).toDouble();
mRotatedAnnotationsLengthMode = TickLengthMode( itemElem.attribute( QStringLiteral( "rotatedAnnotationsLengthMode" ), QStringLiteral( "0" ) ).toInt() );
mRotatedAnnotationsEnabled = itemElem.attribute( QStringLiteral( "rotatedAnnotationsEnabled" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
mRotatedAnnotationsMinimumAngle = itemElem.attribute( QStringLiteral( "rotatedAnnotationsMinimumAngle" ), QStringLiteral( "0" ) ).toDouble();
mRotatedAnnotationsMarginToCorner = itemElem.attribute( QStringLiteral( "rotatedAnnotationsMarginToCorner" ), QStringLiteral( "0" ) ).toDouble();

QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral( "lineStyle" ) );
if ( !lineStyleElem.isNull() )
@@ -666,9 +670,9 @@ void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions() const
it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
QVector2D normS = borderToNormal2D( it->startAnnotation.border );
it->startAnnotation.angle = abs( M_PI / 2.0 - acos( QVector2D::dotProduct( it->startAnnotation.vector, normS ) / ( it->startAnnotation.vector.length() * normS.length() ) ) );
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() );
QVector2D normE = borderToNormal2D( it->endAnnotation.border );
it->endAnnotation.angle = abs( M_PI / 2.0 - acos( QVector2D::dotProduct( it->endAnnotation.vector, normE ) / ( it->endAnnotation.vector.length() * normE.length() ) ) );
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() );
}
}

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

// If the angle is below the threshold, we don't draw the annotation
if ( annot.angle < mRotatedTicksMinimumAngle * M_PI / 180.0 )
if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle )
continue;

// Skip outwards facing annotations that are below mRotatedTicksMarginToCorner
bool facingLeft;
bool facingRight;
if ( mGridFrameStyle == QgsLayoutItemMapGrid::InteriorExteriorTicks )
{
facingLeft = ( annot.angle != 0 );
facingRight = ( annot.angle != 0 );
}
else if ( mGridFrameStyle == QgsLayoutItemMapGrid::ExteriorTicks )
{
facingLeft = ( annot.angle > 0 );
facingRight = ( annot.angle < 0 );
}
else
{
facingLeft = ( annot.angle < 0 );
facingRight = ( annot.angle > 0 );
}

if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) ||
( facingRight && annot.position.x() > mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
continue;
if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() > mMap->rect().width() - mRotatedTicksMarginToCorner ) ||
( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
continue;
if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() > mMap->rect().height() - mRotatedTicksMarginToCorner ) ||
( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
continue;
if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) ||
( facingRight && annot.position.y() > mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
continue;

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


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

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


if ( extension || !context.painter() )
return;

// Skip outwards facing annotations that are below mRotatedAnnotationsMarginToCorner
bool facingLeft = ( annot.angle < 0 );
bool facingRight = ( annot.angle > 0 );
if ( anotPos == QgsLayoutItemMapGrid::OutsideMapFrame )
{
facingLeft = !facingLeft;
facingRight = !facingRight;
}
if ( annot.border == BorderSide::Top && ( ( facingLeft && xpos < mRotatedAnnotationsMarginToCorner ) ||
( facingRight && xpos > mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
return;
if ( annot.border == BorderSide::Bottom && ( ( facingLeft && xpos > mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ||
( facingRight && xpos < mRotatedAnnotationsMarginToCorner ) ) )
return;
if ( annot.border == BorderSide::Left && ( ( facingLeft && ypos > mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ||
( facingRight && ypos < mRotatedAnnotationsMarginToCorner ) ) )
return;
if ( annot.border == BorderSide::Right && ( ( facingLeft && ypos < mRotatedAnnotationsMarginToCorner ) ||
( facingRight && ypos > mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
return;

QgsScopedQPainterState painterState( context.painter() );
context.painter()->translate( QPointF( xpos, ypos ) );
context.painter()->rotate( rotation );
@@ -846,6 +846,18 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
*/
double rotatedTicksMinimumAngle() const { return mRotatedTicksMinimumAngle; }

/**
* Sets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
* \see rotatedTicksMarginToCorner()
*/
void setRotatedTicksMarginToCorner( const double margin ) { mRotatedTicksMarginToCorner = margin; }

/**
* Gets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
* \see setRotatedTicksMarginToCorner()
*/
double rotatedTicksMarginToCorner() const { return mRotatedTicksMarginToCorner; }

/**
* Enable/disable annotations rotation for rotated or reprojected grids.
* \see rotatedAnnotationsEnabled()
@@ -882,6 +894,18 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
*/
double rotatedAnnotationsMinimumAngle() const { return mRotatedAnnotationsMinimumAngle; }

/**
* Sets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
* \see rotatedAnnotationsMarginToCorner()
*/
void setRotatedAnnotationsMarginToCorner( const double margin ) { mRotatedAnnotationsMarginToCorner = margin; }

/**
* Gets the \a margin to corners (in canvas units) below which outwards facing ticks are not drawn.
* \see setRotatedAnnotationsMarginToCorner()
*/
double rotatedAnnotationsMarginToCorner() const { return mRotatedAnnotationsMarginToCorner; }

/**
* Sets the grid frame margin (in layout units).
* This property controls distance between the map frame and the grid frame.
@@ -1103,9 +1127,11 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
bool mRotatedTicksEnabled = false;
TickLengthMode mRotatedTicksLengthMode = QgsLayoutItemMapGrid::OrthogonalTicks;
double mRotatedTicksMinimumAngle = 0.0;
double mRotatedTicksMarginToCorner = 0.0;
bool mRotatedAnnotationsEnabled = false;
TickLengthMode mRotatedAnnotationsLengthMode = QgsLayoutItemMapGrid::OrthogonalTicks;
double mRotatedAnnotationsMinimumAngle = 0.0;
double mRotatedAnnotationsMarginToCorner = 0.0;

double mMinimumIntervalWidth = 50;
double mMaximumIntervalWidth = 100;
@@ -66,9 +66,11 @@ QgsLayoutMapGridWidget::QgsLayoutMapGridWidget( QgsLayoutItemMapGrid *mapGrid, Q
connect( mRotatedTicksCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapGridWidget::mRotatedTicksCheckBox_toggled );
connect( mRotatedTicksLengthModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapGridWidget::mRotatedTicksLengthModeComboBox_currentIndexChanged );
connect( mRotatedTicksThresholdSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedTicksThresholdSpinBox_valueChanged );
connect( mRotatedTicksMarginToCornerSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedTicksMarginToCornerSpinBox_valueChanged );
connect( mRotatedAnnotationsCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapGridWidget::mRotatedAnnotationsCheckBox_toggled );
connect( mRotatedAnnotationsLengthModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutMapGridWidget::mRotatedAnnotationsLengthModeComboBox_currentIndexChanged );
connect( mRotatedAnnotationsThresholdSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedAnnotationsThresholdSpinBox_valueChanged );
connect( mRotatedAnnotationsMarginToCornerSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mRotatedAnnotationsMarginToCornerSpinBox_valueChanged );
connect( mGridFramePenSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mGridFramePenSizeSpinBox_valueChanged );
connect( mGridFramePenColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutMapGridWidget::mGridFramePenColorButton_colorChanged );
connect( mGridFrameFill1ColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutMapGridWidget::mGridFrameFill1ColorButton_colorChanged );
@@ -345,6 +347,7 @@ void QgsLayoutMapGridWidget::toggleFrameControls( bool frameEnabled, bool frameF
mRotatedTicksCheckBox->setEnabled( rotationEnabled );
mRotatedTicksLengthModeComboBox->setEnabled( rotationEnabled );
mRotatedTicksThresholdSpinBox->setEnabled( rotationEnabled );
mRotatedTicksMarginToCornerSpinBox->setEnabled( rotationEnabled );
}

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

mRotatedAnnotationsCheckBox->setChecked( mMapGrid->rotatedAnnotationsEnabled() );
mRotatedAnnotationsLengthModeComboBox->setCurrentIndex( mRotatedAnnotationsLengthModeComboBox->findData( mMapGrid->rotatedAnnotationsLengthMode() ) );
mRotatedAnnotationsThresholdSpinBox->setValue( mMapGrid->rotatedAnnotationsMinimumAngle() );
mRotatedAnnotationsMarginToCornerSpinBox->setValue( mMapGrid->rotatedAnnotationsMarginToCorner() );

initFrameDisplayBox( mFrameDivisionsLeftComboBox, mMapGrid->frameDivisions( QgsLayoutItemMapGrid::Left ) );
initFrameDisplayBox( mFrameDivisionsRightComboBox, mMapGrid->frameDivisions( QgsLayoutItemMapGrid::Right ) );
@@ -931,6 +936,20 @@ void QgsLayoutMapGridWidget::mRotatedTicksThresholdSpinBox_valueChanged( double
mMap->update();
mMap->endCommand();
}

void QgsLayoutMapGridWidget::mRotatedTicksMarginToCornerSpinBox_valueChanged( double val )
{
if ( !mMapGrid || !mMap )
{
return;
}

mMap->beginCommand( tr( "Change Rotated Ticks Margin to Corner" ) );
mMapGrid->setRotatedTicksMarginToCorner( val );
mMap->update();
mMap->endCommand();
}

void QgsLayoutMapGridWidget::mRotatedAnnotationsCheckBox_toggled( bool state )
{
if ( !mMapGrid || !mMap )
@@ -971,6 +990,18 @@ void QgsLayoutMapGridWidget::mRotatedAnnotationsThresholdSpinBox_valueChanged( d
mMap->endCommand();
}

void QgsLayoutMapGridWidget::mRotatedAnnotationsMarginToCornerSpinBox_valueChanged( double val )
{
if ( !mMapGrid || !mMap )
{
return;
}

mMap->beginCommand( tr( "Change Rotated Annotations Margin to Corner" ) );
mMapGrid->setRotatedAnnotationsMarginToCorner( val );
mMap->update();
mMap->endCommand();
}

void QgsLayoutMapGridWidget::intervalUnitChanged( int )
{
@@ -53,9 +53,11 @@ class GUI_EXPORT QgsLayoutMapGridWidget: public QgsLayoutItemBaseWidget, private
void mRotatedTicksCheckBox_toggled( bool checked );
void mRotatedTicksLengthModeComboBox_currentIndexChanged( int );
void mRotatedTicksThresholdSpinBox_valueChanged( double val );
void mRotatedTicksMarginToCornerSpinBox_valueChanged( double val );
void mRotatedAnnotationsCheckBox_toggled( bool checked );
void mRotatedAnnotationsLengthModeComboBox_currentIndexChanged( int );
void mRotatedAnnotationsThresholdSpinBox_valueChanged( double val );
void mRotatedAnnotationsMarginToCornerSpinBox_valueChanged( double val );
void mGridFrameMarginSpinBox_valueChanged( double val );
void mFrameStyleComboBox_currentIndexChanged( int );
void mGridFramePenSizeSpinBox_valueChanged( double d );
@@ -717,6 +717,26 @@
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="label_annot_corner">
<property name="text">
<string>Margin to map corner</string>
</property>
</widget>
</item>
<item row="17" column="1" colspan="4">
<widget class="QDoubleSpinBox" name="mRotatedTicksMarginToCornerSpinBox">
<property name="toolTip">
<string>Outwards facing ticks closer to the corners that this margin will be ignored. This only makes sense for rotated grids.</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -944,6 +964,26 @@
</property>
</widget>
</item>
<item row="20" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Margin to map corner</string>
</property>
</widget>
</item>
<item row="20" column="1" colspan="2">
<widget class="QDoubleSpinBox" name="mRotatedAnnotationsMarginToCornerSpinBox">
<property name="toolTip">
<string>Outwards facing annotations closer to the corners that this margin will be ignored. This only makes sense for rotated grids.</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -1048,6 +1088,7 @@
<tabstop>mRotatedTicksCheckBox</tabstop>
<tabstop>mRotatedTicksLengthModeComboBox</tabstop>
<tabstop>mRotatedTicksThresholdSpinBox</tabstop>
<tabstop>mRotatedTicksMarginToCornerSpinBox</tabstop>
<tabstop>mDrawAnnotationGroupBox</tabstop>
<tabstop>mAnnotationFormatComboBox</tabstop>
<tabstop>mAnnotationFormatButton</tabstop>
@@ -1070,6 +1111,7 @@
<tabstop>mRotatedAnnotationsCheckBox</tabstop>
<tabstop>mRotatedAnnotationsLengthModeComboBox</tabstop>
<tabstop>mRotatedAnnotationsThresholdSpinBox</tabstop>
<tabstop>mRotatedAnnotationsMarginToCornerSpinBox</tabstop>
</tabstops>
<resources>
<include location="../../../images/images.qrc"/>

0 comments on commit b80e252

Please sign in to comment.
You can’t perform that action at this time.