36 #include "qgssettings.h" 
   49 #define MAX_GRID_LINES 1000  
   80   return qobject_cast<QgsLayoutItemMapGrid *>( 
item );
 
   86   return qobject_cast<QgsLayoutItemMapGrid *>( 
item );
 
   91   QList< QgsLayoutItemMapGrid * > list;
 
  114   QDomNodeList mapGridNodeList = elem.elementsByTagName( QStringLiteral( 
"ComposerMapGrid" ) );
 
  115   for ( 
int i = 0; i < mapGridNodeList.size(); ++i )
 
  117     QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
 
  119     mapGrid->
readXml( mapGridElem, doc, context );
 
  133   return std::max( std::max( std::max( top, right ), bottom ), left );
 
  147       double gridTop = 0.0;
 
  148       double gridRight = 0.0;
 
  149       double gridBottom = 0.0;
 
  150       double gridLeft = 0.0;
 
  152       top = std::max( top, gridTop );
 
  153       right = std::max( right, gridRight );
 
  154       bottom = std::max( bottom, gridBottom );
 
  155       left = std::max( left, gridLeft );
 
  171       return QVector2D( 0, 1 );
 
  173       return QVector2D( -1, 0 );
 
  175       return QVector2D( 0, -1 );
 
  177       return QVector2D( 1, 0 );
 
  185   return QVector2D( borderVector.y(), -borderVector.x() );
 
  194   QgsSettings settings;
 
  195   QString defaultFontString = settings.value( QStringLiteral( 
"LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString();
 
  196   if ( !defaultFontString.isEmpty() )
 
  199     font.setFamily( defaultFontString );
 
  200     mAnnotationFormat.
setFont( font );
 
  203   createDefaultGridLineSymbol();
 
  204   createDefaultGridMarkerSymbol();
 
  217 void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
 
  219   QVariantMap properties;
 
  220   properties.insert( QStringLiteral( 
"color" ), QStringLiteral( 
"0,0,0,255" ) );
 
  221   properties.insert( QStringLiteral( 
"width" ), QStringLiteral( 
"0.3" ) );
 
  222   properties.insert( QStringLiteral( 
"capstyle" ), QStringLiteral( 
"flat" ) );
 
  226 void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
 
  228   QVariantMap properties;
 
  229   properties.insert( QStringLiteral( 
"name" ), QStringLiteral( 
"circle" ) );
 
  230   properties.insert( QStringLiteral( 
"size" ), QStringLiteral( 
"2.0" ) );
 
  231   properties.insert( QStringLiteral( 
"color" ), QStringLiteral( 
"0,0,0,255" ) );
 
  237   if ( mGridLineSymbol )
 
  239     mGridLineSymbol->setWidth( width );
 
  245   if ( mGridLineSymbol )
 
  247     mGridLineSymbol->setColor( 
c );
 
  258   QDomElement mapGridElem = doc.createElement( QStringLiteral( 
"ComposerMapGrid" ) );
 
  259   mapGridElem.setAttribute( QStringLiteral( 
"gridStyle" ), mGridStyle );
 
  260   mapGridElem.setAttribute( QStringLiteral( 
"intervalX" ), 
qgsDoubleToString( mGridIntervalX ) );
 
  261   mapGridElem.setAttribute( QStringLiteral( 
"intervalY" ), 
qgsDoubleToString( mGridIntervalY ) );
 
  262   mapGridElem.setAttribute( QStringLiteral( 
"offsetX" ), 
qgsDoubleToString( mGridOffsetX ) );
 
  263   mapGridElem.setAttribute( QStringLiteral( 
"offsetY" ), 
qgsDoubleToString( mGridOffsetY ) );
 
  264   mapGridElem.setAttribute( QStringLiteral( 
"crossLength" ), 
qgsDoubleToString( mCrossLength ) );
 
  266   QDomElement lineStyleElem = doc.createElement( QStringLiteral( 
"lineStyle" ) );
 
  268   lineStyleElem.appendChild( gridLineStyleElem );
 
  269   mapGridElem.appendChild( lineStyleElem );
 
  271   QDomElement markerStyleElem = doc.createElement( QStringLiteral( 
"markerStyle" ) );
 
  273   markerStyleElem.appendChild( gridMarkerStyleElem );
 
  274   mapGridElem.appendChild( markerStyleElem );
 
  276   mapGridElem.setAttribute( QStringLiteral( 
"gridFrameStyle" ), mGridFrameStyle );
 
  277   mapGridElem.setAttribute( QStringLiteral( 
"gridFrameSideFlags" ), mGridFrameSides );
 
  278   mapGridElem.setAttribute( QStringLiteral( 
"gridFrameWidth" ), 
qgsDoubleToString( mGridFrameWidth ) );
 
  279   mapGridElem.setAttribute( QStringLiteral( 
"gridFrameMargin" ), 
qgsDoubleToString( mGridFrameMargin ) );
 
  280   mapGridElem.setAttribute( QStringLiteral( 
"gridFramePenThickness" ), 
qgsDoubleToString( mGridFramePenThickness ) );
 
  284   mapGridElem.setAttribute( QStringLiteral( 
"leftFrameDivisions" ), mLeftFrameDivisions );
 
  285   mapGridElem.setAttribute( QStringLiteral( 
"rightFrameDivisions" ), mRightFrameDivisions );
 
  286   mapGridElem.setAttribute( QStringLiteral( 
"topFrameDivisions" ), mTopFrameDivisions );
 
  287   mapGridElem.setAttribute( QStringLiteral( 
"bottomFrameDivisions" ), mBottomFrameDivisions );
 
  288   mapGridElem.setAttribute( QStringLiteral( 
"rotatedTicksLengthMode" ), mRotatedTicksLengthMode );
 
  289   mapGridElem.setAttribute( QStringLiteral( 
"rotatedTicksEnabled" ), mRotatedTicksEnabled );
 
  290   mapGridElem.setAttribute( QStringLiteral( 
"rotatedTicksMinimumAngle" ), QString::number( mRotatedTicksMinimumAngle ) );
 
  291   mapGridElem.setAttribute( QStringLiteral( 
"rotatedTicksMarginToCorner" ), QString::number( mRotatedTicksMarginToCorner ) );
 
  292   mapGridElem.setAttribute( QStringLiteral( 
"rotatedAnnotationsLengthMode" ), mRotatedAnnotationsLengthMode );
 
  293   mapGridElem.setAttribute( QStringLiteral( 
"rotatedAnnotationsEnabled" ), mRotatedAnnotationsEnabled );
 
  294   mapGridElem.setAttribute( QStringLiteral( 
"rotatedAnnotationsMinimumAngle" ), QString::number( mRotatedAnnotationsMinimumAngle ) );
 
  295   mapGridElem.setAttribute( QStringLiteral( 
"rotatedAnnotationsMarginToCorner" ), QString::number( mRotatedAnnotationsMarginToCorner ) );
 
  301   mapGridElem.setAttribute( QStringLiteral( 
"annotationFormat" ), mGridAnnotationFormat );
 
  302   mapGridElem.setAttribute( QStringLiteral( 
"showAnnotation" ), mShowGridAnnotation );
 
  303   mapGridElem.setAttribute( QStringLiteral( 
"annotationExpression" ), mGridAnnotationExpressionString );
 
  304   mapGridElem.setAttribute( QStringLiteral( 
"leftAnnotationDisplay" ), mLeftGridAnnotationDisplay );
 
  305   mapGridElem.setAttribute( QStringLiteral( 
"rightAnnotationDisplay" ), mRightGridAnnotationDisplay );
 
  306   mapGridElem.setAttribute( QStringLiteral( 
"topAnnotationDisplay" ), mTopGridAnnotationDisplay );
 
  307   mapGridElem.setAttribute( QStringLiteral( 
"bottomAnnotationDisplay" ), mBottomGridAnnotationDisplay );
 
  308   mapGridElem.setAttribute( QStringLiteral( 
"leftAnnotationPosition" ), mLeftGridAnnotationPosition );
 
  309   mapGridElem.setAttribute( QStringLiteral( 
"rightAnnotationPosition" ), mRightGridAnnotationPosition );
 
  310   mapGridElem.setAttribute( QStringLiteral( 
"topAnnotationPosition" ), mTopGridAnnotationPosition );
 
  311   mapGridElem.setAttribute( QStringLiteral( 
"bottomAnnotationPosition" ), mBottomGridAnnotationPosition );
 
  312   mapGridElem.setAttribute( QStringLiteral( 
"leftAnnotationDirection" ), mLeftGridAnnotationDirection );
 
  313   mapGridElem.setAttribute( QStringLiteral( 
"rightAnnotationDirection" ), mRightGridAnnotationDirection );
 
  314   mapGridElem.setAttribute( QStringLiteral( 
"topAnnotationDirection" ), mTopGridAnnotationDirection );
 
  315   mapGridElem.setAttribute( QStringLiteral( 
"bottomAnnotationDirection" ), mBottomGridAnnotationDirection );
 
  316   mapGridElem.setAttribute( QStringLiteral( 
"frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) );
 
  317   mapGridElem.appendChild( mAnnotationFormat.
writeXml( doc, context ) );
 
  318   mapGridElem.setAttribute( QStringLiteral( 
"annotationPrecision" ), mGridAnnotationPrecision );
 
  319   mapGridElem.setAttribute( QStringLiteral( 
"unit" ), mGridUnit );
 
  320   mapGridElem.setAttribute( QStringLiteral( 
"blendMode" ), mBlendMode );
 
  321   mapGridElem.setAttribute( QStringLiteral( 
"minimumIntervalWidth" ), QString::number( mMinimumIntervalWidth ) );
 
  322   mapGridElem.setAttribute( QStringLiteral( 
"maximumIntervalWidth" ), QString::number( mMaximumIntervalWidth ) );
 
  325   elem.appendChild( mapGridElem );
 
  332   if ( itemElem.isNull() )
 
  341   mGridIntervalX = itemElem.attribute( QStringLiteral( 
"intervalX" ), QStringLiteral( 
"0" ) ).toDouble();
 
  342   mGridIntervalY = itemElem.attribute( QStringLiteral( 
"intervalY" ), QStringLiteral( 
"0" ) ).toDouble();
 
  343   mGridOffsetX = itemElem.attribute( QStringLiteral( 
"offsetX" ), QStringLiteral( 
"0" ) ).toDouble();
 
  344   mGridOffsetY = itemElem.attribute( QStringLiteral( 
"offsetY" ), QStringLiteral( 
"0" ) ).toDouble();
 
  345   mCrossLength = itemElem.attribute( QStringLiteral( 
"crossLength" ), QStringLiteral( 
"3" ) ).toDouble();
 
  346   mGridFrameStyle = 
static_cast< QgsLayoutItemMapGrid::FrameStyle >( itemElem.attribute( QStringLiteral( 
"gridFrameStyle" ), QStringLiteral( 
"0" ) ).toInt() );
 
  347   mGridFrameSides = 
static_cast< QgsLayoutItemMapGrid::FrameSideFlags 
>( itemElem.attribute( QStringLiteral( 
"gridFrameSideFlags" ), QStringLiteral( 
"15" ) ).toInt() );
 
  348   mGridFrameWidth = itemElem.attribute( QStringLiteral( 
"gridFrameWidth" ), QStringLiteral( 
"2.0" ) ).toDouble();
 
  349   mGridFrameMargin = itemElem.attribute( QStringLiteral( 
"gridFrameMargin" ), QStringLiteral( 
"0.0" ) ).toDouble();
 
  350   mGridFramePenThickness = itemElem.attribute( QStringLiteral( 
"gridFramePenThickness" ), QStringLiteral( 
"0.3" ) ).toDouble();
 
  358   mRotatedTicksLengthMode = 
TickLengthMode( itemElem.attribute( QStringLiteral( 
"rotatedTicksLengthMode" ), QStringLiteral( 
"0" ) ).toInt() );
 
  359   mRotatedTicksEnabled = itemElem.attribute( QStringLiteral( 
"rotatedTicksEnabled" ), QStringLiteral( 
"0" ) ) != QLatin1String( 
"0" );
 
  360   mRotatedTicksMinimumAngle = itemElem.attribute( QStringLiteral( 
"rotatedTicksMinimumAngle" ), QStringLiteral( 
"0" ) ).toDouble();
 
  361   mRotatedTicksMarginToCorner = itemElem.attribute( QStringLiteral( 
"rotatedTicksMarginToCorner" ), QStringLiteral( 
"0" ) ).toDouble();
 
  362   mRotatedAnnotationsLengthMode = 
TickLengthMode( itemElem.attribute( QStringLiteral( 
"rotatedAnnotationsLengthMode" ), QStringLiteral( 
"0" ) ).toInt() );
 
  363   mRotatedAnnotationsEnabled = itemElem.attribute( QStringLiteral( 
"rotatedAnnotationsEnabled" ), QStringLiteral( 
"0" ) ) != QLatin1String( 
"0" );
 
  364   mRotatedAnnotationsMinimumAngle = itemElem.attribute( QStringLiteral( 
"rotatedAnnotationsMinimumAngle" ), QStringLiteral( 
"0" ) ).toDouble();
 
  365   mRotatedAnnotationsMarginToCorner = itemElem.attribute( QStringLiteral( 
"rotatedAnnotationsMarginToCorner" ), QStringLiteral( 
"0" ) ).toDouble();
 
  367   QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral( 
"lineStyle" ) );
 
  368   if ( !lineStyleElem.isNull() )
 
  370     QDomElement symbolElem = lineStyleElem.firstChildElement( QStringLiteral( 
"symbol" ) );
 
  371     if ( !symbolElem.isNull() )
 
  373       mGridLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
 
  380     mGridLineSymbol->setWidth( itemElem.attribute( QStringLiteral( 
"penWidth" ), QStringLiteral( 
"0" ) ).toDouble() );
 
  381     mGridLineSymbol->setColor( QColor( itemElem.attribute( QStringLiteral( 
"penColorRed" ), QStringLiteral( 
"0" ) ).toInt(),
 
  382                                        itemElem.attribute( QStringLiteral( 
"penColorGreen" ), QStringLiteral( 
"0" ) ).toInt(),
 
  383                                        itemElem.attribute( QStringLiteral( 
"penColorBlue" ), QStringLiteral( 
"0" ) ).toInt() ) );
 
  386   QDomElement markerStyleElem = itemElem.firstChildElement( QStringLiteral( 
"markerStyle" ) );
 
  387   if ( !markerStyleElem.isNull() )
 
  389     QDomElement symbolElem = markerStyleElem.firstChildElement( QStringLiteral( 
"symbol" ) );
 
  390     if ( !symbolElem.isNull() )
 
  392       mGridMarkerSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context ) );
 
  396   if ( !mCRS.
readXml( itemElem ) )
 
  399   mBlendMode = 
static_cast< QPainter::CompositionMode 
>( itemElem.attribute( QStringLiteral( 
"blendMode" ), QStringLiteral( 
"0" ) ).toUInt() );
 
  402   mShowGridAnnotation = ( itemElem.attribute( QStringLiteral( 
"showAnnotation" ), QStringLiteral( 
"0" ) ) != QLatin1String( 
"0" ) );
 
  404   mGridAnnotationExpressionString = itemElem.attribute( QStringLiteral( 
"annotationExpression" ) );
 
  405   mGridAnnotationExpression.reset();
 
  410   mLeftGridAnnotationDisplay = 
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral( 
"leftAnnotationDisplay" ), QStringLiteral( 
"0" ) ).toInt() );
 
  411   mRightGridAnnotationDisplay = 
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral( 
"rightAnnotationDisplay" ), QStringLiteral( 
"0" ) ).toInt() );
 
  413   mBottomGridAnnotationDisplay = 
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral( 
"bottomAnnotationDisplay" ), QStringLiteral( 
"0" ) ).toInt() );
 
  419   mAnnotationFrameDistance = itemElem.attribute( QStringLiteral( 
"frameAnnotationDistance" ), QStringLiteral( 
"0" ) ).toDouble();
 
  421   if ( !itemElem.firstChildElement( 
"text-style" ).isNull() )
 
  423     mAnnotationFormat.
readXml( itemElem, context );
 
  430       font.fromString( itemElem.attribute( 
"annotationFont", QString() ) );
 
  432     mAnnotationFormat.
setFont( font );
 
  433     mAnnotationFormat.
setSize( font.pointSizeF() );
 
  438   mGridAnnotationPrecision = itemElem.attribute( QStringLiteral( 
"annotationPrecision" ), QStringLiteral( 
"3" ) ).toInt();
 
  439   int gridUnitInt = itemElem.attribute( QStringLiteral( 
"unit" ), QString::number( 
MapUnit ) ).toInt();
 
  441   mMinimumIntervalWidth = itemElem.attribute( QStringLiteral( 
"minimumIntervalWidth" ), QStringLiteral( 
"50" ) ).toDouble();
 
  442   mMaximumIntervalWidth = itemElem.attribute( QStringLiteral( 
"maximumIntervalWidth" ), QStringLiteral( 
"100" ) ).toDouble();
 
  444   refreshDataDefinedProperties();
 
  454   mTransformDirty = 
true;
 
  460   return mBlendMode != QPainter::CompositionMode_SourceOver;
 
  463 QPolygonF QgsLayoutItemMapGrid::scalePolygon( 
const QPolygonF &polygon, 
const double scale )
 const 
  465   QTransform t = QTransform::fromScale( scale, scale );
 
  466   return t.map( polygon );
 
  469 void QgsLayoutItemMapGrid::drawGridCrsTransform( 
QgsRenderContext &context, 
double dotsPerMM, 
bool calculateLinesOnly )
 const 
  471   if ( !
mMap || !mEvaluatedEnabled )
 
  478   if ( mapPolygon != mPrevMapPolygon )
 
  480     mTransformDirty = 
true;
 
  481     mPrevMapPolygon = mapPolygon;
 
  484   if ( mTransformDirty )
 
  486     calculateCrsTransformLines();
 
  490   if ( !calculateLinesOnly )
 
  494       QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
 
  495       for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
 
  497         drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
 
  502       double maxX = 
mMap->rect().width();
 
  503       double maxY = 
mMap->rect().height();
 
  505       QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
 
  506       for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
 
  508         double x = intersectionIt->x();
 
  509         double y = intersectionIt->y();
 
  513           QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
 
  514           line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
 
  515           line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
 
  516           QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
 
  517           line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
 
  518           line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
 
  521           drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
 
  522           drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
 
  526           drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
 
  533 void QgsLayoutItemMapGrid::calculateCrsTransformLines()
 const 
  537   if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
 
  544   xGridLinesCrsTransform( crsBoundingRect, inverseTr );
 
  545   yGridLinesCrsTransform( crsBoundingRect, inverseTr );
 
  552     QList< QgsGeometry > xLines;
 
  553     QList< QgsGeometry > yLines;
 
  554     QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
 
  555     for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
 
  559       for ( 
int i = 0; i < gridIt->line.size(); ++i )
 
  561         line.append( 
QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
 
  563       if ( gridIt->coordinateType == AnnotationCoordinate::Longitude )
 
  565       else if ( gridIt->coordinateType == AnnotationCoordinate::Latitude )
 
  570     mTransformedIntersections.clear();
 
  571     QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
 
  572     for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
 
  574       QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
 
  575       for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
 
  579         if ( intersects.
isNull() )
 
  587           mTransformedIntersections << vertex;
 
  595   mTransformDirty = 
false;
 
  600   if ( !
mMap || !mEvaluatedEnabled )
 
  604   QPaintDevice *paintDevice = p->device();
 
  611   p->setCompositionMode( mBlendMode );
 
  614   QRectF thisPaintRect = QRectF( 0, 0, 
mMap->rect().width(), 
mMap->rect().height() );
 
  615   p->setClipRect( thisPaintRect );
 
  616   if ( thisPaintRect != mPrevPaintRect )
 
  619     mTransformDirty = 
true;
 
  620     mPrevPaintRect = thisPaintRect;
 
  624   double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
 
  625   p->scale( 1 / dotsPerMM, 1 / dotsPerMM ); 
 
  641         drawGridCrsTransform( context, dotsPerMM );
 
  648       drawGridNoTransform( context, dotsPerMM );
 
  653   p->setClipping( 
false );
 
  657   p->setClipRect( 
mMap->mapRectFromScene( 
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
 
  662     updateGridLinesAnnotationsPositions();
 
  669   if ( mShowGridAnnotation )
 
  675 void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
 const 
  677   QList< GridLine >::iterator it = mGridLines.begin();
 
  678   for ( ; it != mGridLines.end(); ++it )
 
  680     it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
 
  681     it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
 
  682     it->startAnnotation.position = QVector2D( it->line.first() );
 
  683     it->endAnnotation.position = QVector2D( it->line.last() );
 
  684     it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
 
  685     it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
 
  687     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() );
 
  689     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() );
 
  693 void QgsLayoutItemMapGrid::drawGridNoTransform( 
QgsRenderContext &context, 
double dotsPerMM, 
bool calculateLinesOnly )
 const 
  700   if ( calculateLinesOnly )
 
  703   QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
 
  704   QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
 
  712     for ( ; vIt != mGridLines.constEnd(); ++vIt )
 
  714       if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
 
  716       line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
 
  717       drawGridLine( line, context );
 
  720     for ( ; hIt != mGridLines.constEnd(); ++hIt )
 
  722       if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
 
  724       line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
 
  725       drawGridLine( line, context );
 
  731     QPointF intersectionPoint, crossEnd1, crossEnd2;
 
  732     for ( ; vIt != mGridLines.constEnd(); ++vIt )
 
  734       if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
 
  737       l1 = QLineF( vIt->line.first(), vIt->line.last() );
 
  740       hIt = mGridLines.constBegin();
 
  741       for ( ; hIt != mGridLines.constEnd(); ++hIt )
 
  743         if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
 
  746         l2 = QLineF( hIt->line.first(), hIt->line.last() );
 
  748 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
  749         if ( l2.intersect( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
 
  751         if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
 
  757             crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
 
  759             crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
 
  762             drawGridLine( QLineF( crossEnd1  * dotsPerMM, crossEnd2  * dotsPerMM ), context );
 
  766             drawGridMarker( intersectionPoint * dotsPerMM, context );
 
  778     hIt = mGridLines.constBegin();
 
  779     for ( ; hIt != mGridLines.constEnd(); ++hIt )
 
  781       if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
 
  784       l1 = QLineF( hIt->line.first(), hIt->line.last() );
 
  786       vIt = mGridLines.constBegin();
 
  787       for ( ; vIt != mGridLines.constEnd(); ++vIt )
 
  789         if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
 
  792         l2 = QLineF( vIt->line.first(), vIt->line.last() );
 
  794 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
  795         if ( l2.intersect( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
 
  797         if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
 
  801           crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
 
  803           crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 )  ?
 
  806           drawGridLine( QLineF( crossEnd1  * dotsPerMM, crossEnd2  * dotsPerMM ), context );
 
  813 void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
 const 
  822   switch ( mGridFrameStyle )
 
  826       drawGridFrameZebra( p, extension );
 
  831       drawGridFrameTicks( p, extension );
 
  836       drawGridFrameLine( p, extension );
 
  847 void QgsLayoutItemMapGrid::drawGridLine( 
const QLineF &line, 
QgsRenderContext &context )
 const 
  850   poly << line.p1() << line.p2();
 
  851   drawGridLine( poly, context );
 
  854 void QgsLayoutItemMapGrid::drawGridLine( 
const QPolygonF &line, 
QgsRenderContext &context )
 const 
  861   mGridLineSymbol->startRender( context );
 
  862   mGridLineSymbol->renderPolyline( line, 
nullptr, context );
 
  863   mGridLineSymbol->stopRender( context );
 
  866 void QgsLayoutItemMapGrid::drawGridMarker( QPointF point, 
QgsRenderContext &context )
 const 
  873   mGridMarkerSymbol->startRender( context );
 
  874   mGridMarkerSymbol->renderPoint( point, 
nullptr, context );
 
  875   mGridMarkerSymbol->stopRender( context );
 
  878 void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
 const 
  898 void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p, BorderSide border, 
double *extension )
 const 
  907     *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
 
  911   double currentCoord = 0.0;
 
  918   bool drawTLBox = 
false;
 
  919   bool drawTRBox = 
false;
 
  920   bool drawBLBox = 
false;
 
  921   bool drawBRBox = 
false;
 
  923   QMap< double, double > pos = QMap< double, double >();
 
  924   QList< GridLine >::const_iterator it = mGridLines.constBegin();
 
  925   for ( ; it != mGridLines.constEnd(); ++it )
 
  928     for ( 
int i = 0 ; i < 2 ; ++i )
 
  930       GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
 
  933       if ( annot.border != border )
 
  936       if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
 
  940         pos.insert( annot.position.y(), it->coordinate );
 
  942         pos.insert( annot.position.x(), it->coordinate );
 
  949     pos.insert( 
mMap->rect().height(), 
mMap->rect().height() );
 
  965     pos.insert( 
mMap->rect().width(), 
mMap->rect().width() );
 
  969   QPen framePen = QPen( mGridFramePenColor );
 
  970   framePen.setWidthF( mEvaluatedGridFrameLineThickness );
 
  971   framePen.setJoinStyle( Qt::MiterJoin );
 
  972   p->setPen( framePen );
 
  974   QMap< double, double >::const_iterator posIt = pos.constBegin();
 
  975   for ( ; posIt != pos.constEnd(); ++posIt )
 
  977     p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
 
  980       height = posIt.key() - currentCoord;
 
  981       width = mEvaluatedGridFrameWidth;
 
  982       x = ( border == 
QgsLayoutItemMapGrid::Left ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) : 
mMap->rect().width() + mEvaluatedGridFrameMargin;
 
  987       height = mEvaluatedGridFrameWidth;
 
  988       width = posIt.key() - currentCoord;
 
  990       y = ( border == 
QgsLayoutItemMapGrid::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) : 
mMap->rect().height() + mEvaluatedGridFrameMargin;
 
  992     p->drawRect( QRectF( x, y, width, height ) );
 
  993     currentCoord = posIt.key();
 
 1000     width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) ;
 
 1001     p->setBrush( QBrush( mGridFrameFillColor1 ) );
 
 1003       p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
 
 1005       p->drawRect( QRectF( 
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
 
 1007       p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), 
mMap->rect().height(), width, height ) );
 
 1009       p->drawRect( QRectF( 
mMap->rect().width(), 
mMap->rect().height(), width, height ) );
 
 1013 void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
 const 
 1023     QPen framePen = QPen( mGridFramePenColor );
 
 1024     framePen.setWidthF( mEvaluatedGridFrameLineThickness );
 
 1025     framePen.setCapStyle( Qt::FlatCap );
 
 1026     p->setBrush( Qt::NoBrush );
 
 1027     p->setPen( framePen );
 
 1030   QList< GridLine >::iterator it = mGridLines.begin();
 
 1031   for ( ; it != mGridLines.end(); ++it )
 
 1034     for ( 
int i = 0 ; i < 2 ; ++i )
 
 1036       GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
 
 1038       if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
 
 1042       if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
 
 1050         facingLeft = ( annot.angle != 0 );
 
 1051         facingRight = ( annot.angle != 0 );
 
 1055         facingLeft = ( annot.angle > 0 );
 
 1056         facingRight = ( annot.angle < 0 );
 
 1060         facingLeft = ( annot.angle < 0 );
 
 1061         facingRight = ( annot.angle > 0 );
 
 1064       if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) ||
 
 1065            ( facingRight && annot.position.x() > 
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
 
 1067       if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() > 
mMap->rect().width() - mRotatedTicksMarginToCorner ) ||
 
 1068            ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
 
 1070       if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() > 
mMap->rect().height() - mRotatedTicksMarginToCorner ) ||
 
 1071            ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
 
 1073       if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) ||
 
 1074            ( facingRight && annot.position.y() > 
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
 
 1078       QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
 
 1080       double fA = mEvaluatedGridFrameMargin; 
 
 1081       double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth; 
 
 1083       if ( mRotatedTicksEnabled && mRotatedTicksLengthMode == 
OrthogonalTicks )
 
 1085         fA /= QVector2D::dotProduct( vector, normalVector );
 
 1086         fB /= QVector2D::dotProduct( vector, normalVector );
 
 1093           extension->UpdateBorder( annot.border, fB );
 
 1101         pA = annot.position + fA * vector;
 
 1102         pB = annot.position + fB * vector;
 
 1106         pA = annot.position - fA * vector;
 
 1107         pB = annot.position - fB * vector;
 
 1111         pA = annot.position - fB * vector;
 
 1112         pB = annot.position + ( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
 
 1114       p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
 
 1120 void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
 const 
 1130     QPen framePen = QPen( mGridFramePenColor );
 
 1131     framePen.setWidthF( mEvaluatedGridFrameLineThickness );
 
 1132     framePen.setCapStyle( Qt::SquareCap );
 
 1133     p->setBrush( Qt::NoBrush );
 
 1134     p->setPen( framePen );
 
 1144       p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
 
 1152       p->drawLine( QLineF( 
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 
mMap->rect().width() + mEvaluatedGridFrameMargin, 
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
 
 1158       extension->UpdateBorder( 
QgsLayoutItemMapGrid::Top, mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 );
 
 1160       p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
 
 1168       p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 
mMap->rect().height() + mEvaluatedGridFrameMargin, 
mMap->rect().width() + mEvaluatedGridFrameMargin, 
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
 
 1171   if ( ! extension && drawDiagonals )
 
 1176       const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
 
 1177       const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
 
 1178       p->drawLine( QLineF( 0, 0, X1, Y1 ) );
 
 1183       const double X1 = 
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
 
 1184       const double Y1 = 
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
 
 1185       p->drawLine( QLineF( 
mMap->rect().width(), 
mMap->rect().height(), X1, Y1 ) );
 
 1190       const double X1 = 
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
 
 1191       const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
 
 1192       p->drawLine( QLineF( 
mMap->rect().width(), 0, X1, Y1 ) );
 
 1197       const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
 
 1198       const double Y1 = 
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
 
 1199       p->drawLine( QLineF( 0, 
mMap->rect().height(), X1, Y1 ) );
 
 1205     GridExtension *extension )
 const 
 1207   QString currentAnnotationString;
 
 1208   QList< GridLine >::const_iterator it = mGridLines.constBegin();
 
 1209   for ( ; it != mGridLines.constEnd(); ++it )
 
 1211     currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext );
 
 1212     drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
 
 1213     drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
 
 1217 void QgsLayoutItemMapGrid::drawCoordinateAnnotation( 
QgsRenderContext &context, GridLineAnnotation annot, 
const QString &annotationString, 
const AnnotationCoordinate coordinateType, GridExtension *extension )
 const 
 1224   if ( ! shouldShowAnnotationForSide( coordinateType, annot.border ) )
 
 1236   double xpos = annot.position.x();
 
 1237   double ypos = annot.position.y();
 
 1238   QPointF anchor = QPointF();
 
 1245   if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
 
 1249   QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
 
 1252   double f = mEvaluatedAnnotationFrameDistance;
 
 1260     f += mEvaluatedGridFrameWidth;
 
 1261   if ( hasBorderWidth )
 
 1262     f += mEvaluatedGridFrameLineThickness / 2.0;
 
 1267   if ( mRotatedAnnotationsEnabled && mRotatedAnnotationsLengthMode == 
OrthogonalTicks )
 
 1269     f /= QVector2D::dotProduct( vector, normalVector );
 
 1272   QVector2D pos = annot.position + f * vector;
 
 1285     rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
 
 1287     if ( rotation <= -90 || rotation > 90 )
 
 1290       anchor.setX( outside ? 0 : textWidth ); 
 
 1294       anchor.setX( outside ? textWidth : 0 ); 
 
 1298       anchor.setY( 0.5 * textHeight ); 
 
 1300       anchor.setY( -1.5 * textHeight ); 
 
 1302       anchor.setY( -0.5 * textHeight ); 
 
 1308     anchor.setX( 0.5 * textWidth ); 
 
 1309     anchor.setY( -0.5 * textHeight ); 
 
 1311       anchor.setY( outside ? 0 : -textHeight ); 
 
 1313       anchor.setX( outside ? 0 : textWidth ); 
 
 1315       anchor.setY( outside ? -textHeight : 0 ); 
 
 1317       anchor.setX( outside ? textWidth : 0 ); 
 
 1322     anchor.setX( 0.5 * textWidth ); 
 
 1323     anchor.setY( -0.5 * textHeight ); 
 
 1325       anchor.setX( outside ? 0 : textWidth ); 
 
 1327       anchor.setY( outside ? -textHeight : 0 ); 
 
 1329       anchor.setX( outside ? textWidth : 0 ); 
 
 1331       anchor.setY( outside ? 0 : -textHeight ); 
 
 1336     anchor.setX( 0.5 * textWidth ); 
 
 1337     anchor.setY( -0.5 * textHeight ); 
 
 1339       anchor.setX( outside ? textWidth : 0 ); 
 
 1341       anchor.setY( outside ? 0 : -textHeight ); 
 
 1343       anchor.setX( outside ? 0 : textWidth ); 
 
 1345       anchor.setY( outside ? -textHeight : 0 ); 
 
 1350     rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
 
 1351     anchor.setX( 0.5 * textWidth ); 
 
 1353       anchor.setY( -textHeight ); 
 
 1361     extension->UpdateBorder( frameBorder, -f + textWidth );
 
 1363     extension->UpdateAll( textWidth / 2.0 );
 
 1366   if ( extension || !context.
painter() )
 
 1370   bool facingLeft = ( annot.angle < 0 );
 
 1371   bool facingRight = ( annot.angle > 0 );
 
 1374     facingLeft = !facingLeft;
 
 1375     facingRight = !facingRight;
 
 1377   if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ||
 
 1378        ( facingRight && annot.position.x() > 
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
 
 1380   if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() > 
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ||
 
 1381        ( facingRight && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ) )
 
 1383   if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() > 
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ||
 
 1384        ( facingRight && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ) )
 
 1386   if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ||
 
 1387        ( facingRight && annot.position.y() > 
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
 
 1391   context.
painter()->translate( QPointF( xpos, ypos ) );
 
 1392   context.
painter()->rotate( rotation );
 
 1393   context.
painter()->translate( -anchor );
 
 1401   bool geographic = 
false;
 
 1415     double wrappedX = std::fmod( value, 360.0 );
 
 1416     if ( wrappedX > 180.0 )
 
 1418       value = wrappedX - 360.0;
 
 1420     else if ( wrappedX < -180.0 )
 
 1422       value = wrappedX + 360.0;
 
 1428     return QString::number( value, 
'f', mGridAnnotationPrecision );
 
 1434     double coordRounded = 
qgsRound( value, mGridAnnotationPrecision );
 
 1438       if ( !geographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
 
 1440         hemisphere = value < 0 ? QObject::tr( 
"W" ) : QObject::tr( 
"E" );
 
 1446       if ( !geographic || coordRounded != 0.0 )
 
 1448         hemisphere = value < 0 ? QObject::tr( 
"S" ) : QObject::tr( 
"N" );
 
 1454       return QString::number( std::fabs( value ), 
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
 
 1458       return QString::number( std::fabs( value ), 
'f', mGridAnnotationPrecision ) + hemisphere;
 
 1465     if ( !mGridAnnotationExpression )
 
 1467       mGridAnnotationExpression.reset( 
new QgsExpression( mGridAnnotationExpressionString ) );
 
 1468       mGridAnnotationExpression->prepare( &expressionContext );
 
 1470     return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
 
 1474   QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FormatFlags();
 
 1475   switch ( mGridAnnotationFormat )
 
 1494       flags = QgsCoordinateFormatter::FormatFlags();
 
 1504       flags = QgsCoordinateFormatter::FormatFlags();
 
 1525 int QgsLayoutItemMapGrid::xGridLines()
 const 
 1527   if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
 
 1534   QRectF mapBoundingRect = mapPolygon.boundingRect();
 
 1535   double gridIntervalY = mEvaluatedIntervalY;
 
 1536   double gridOffsetY = mEvaluatedOffsetY;
 
 1537   double annotationScale = 1.0;
 
 1538   switch ( mGridUnit )
 
 1543       mapBoundingRect = 
mMap->rect();
 
 1544       mapPolygon = QPolygonF( 
mMap->rect() );
 
 1545       if ( mGridUnit == 
CM )
 
 1547         annotationScale = 0.1;
 
 1548         gridIntervalY *= 10;
 
 1560   double roundCorrection = mapBoundingRect.top() > 0 ? 1.0 : 0.0;
 
 1561   double currentLevel = 
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
 
 1563   int gridLineCount = 0;
 
 1568     double yCanvasCoord;
 
 1569     while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount < 
MAX_GRID_LINES )
 
 1571       yCanvasCoord = 
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
 
 1573       newLine.coordinate = currentLevel * annotationScale;
 
 1574       newLine.coordinateType = AnnotationCoordinate::Latitude;
 
 1575       newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF( 
mMap->rect().width(), yCanvasCoord );
 
 1576       mGridLines.append( newLine );
 
 1577       currentLevel += gridIntervalY;
 
 1584   QVector<QLineF> borderLines;
 
 1585   borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
 
 1586   borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
 
 1587   borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
 
 1588   borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
 
 1590   QVector<QPointF> intersectionList; 
 
 1592   while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount < 
MAX_GRID_LINES )
 
 1594     intersectionList.clear();
 
 1595     QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
 
 1597     QVector<QLineF>::const_iterator it = borderLines.constBegin();
 
 1598     for ( ; it != borderLines.constEnd(); ++it )
 
 1600       QPointF intersectionPoint;
 
 1601 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 1602       if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
 
 1604       if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
 
 1607         intersectionList.push_back( intersectionPoint );
 
 1608         if ( intersectionList.size() >= 2 )
 
 1615     if ( intersectionList.size() >= 2 )
 
 1618       newLine.coordinate = currentLevel;
 
 1619       newLine.coordinateType = AnnotationCoordinate::Latitude;
 
 1621       mGridLines.append( newLine );
 
 1624     currentLevel += gridIntervalY;
 
 1631 int QgsLayoutItemMapGrid::yGridLines()
 const 
 1633   if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
 
 1639   QRectF mapBoundingRect = mapPolygon.boundingRect();
 
 1640   double gridIntervalX = mEvaluatedIntervalX;
 
 1641   double gridOffsetX = mEvaluatedOffsetX;
 
 1642   double annotationScale = 1.0;
 
 1643   switch ( mGridUnit )
 
 1648       mapBoundingRect = 
mMap->rect();
 
 1649       mapPolygon = QPolygonF( 
mMap->rect() );
 
 1650       if ( mGridUnit == 
CM )
 
 1652         annotationScale = 0.1;
 
 1653         gridIntervalX *= 10;
 
 1665   double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0;
 
 1666   double currentLevel = 
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
 
 1668   int gridLineCount = 0;
 
 1672     double xCanvasCoord;
 
 1673     while ( currentLevel <= mapBoundingRect.right() && gridLineCount < 
MAX_GRID_LINES )
 
 1675       xCanvasCoord = 
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
 
 1678       newLine.coordinate = currentLevel * annotationScale;
 
 1679       newLine.coordinateType = AnnotationCoordinate::Longitude;
 
 1680       newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord, 
mMap->rect().height() );
 
 1681       mGridLines.append( newLine );
 
 1682       currentLevel += gridIntervalX;
 
 1689   QVector<QLineF> borderLines;
 
 1690   borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
 
 1691   borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
 
 1692   borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
 
 1693   borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
 
 1695   QVector<QPointF> intersectionList; 
 
 1697   while ( currentLevel <= mapBoundingRect.right() && gridLineCount < 
MAX_GRID_LINES )
 
 1699     intersectionList.clear();
 
 1700     QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
 
 1702     QVector<QLineF>::const_iterator it = borderLines.constBegin();
 
 1703     for ( ; it != borderLines.constEnd(); ++it )
 
 1705       QPointF intersectionPoint;
 
 1706 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 1707       if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
 
 1709       if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
 
 1712         intersectionList.push_back( intersectionPoint );
 
 1713         if ( intersectionList.size() >= 2 )
 
 1720     if ( intersectionList.size() >= 2 )
 
 1723       newLine.coordinate = currentLevel;
 
 1724       newLine.coordinateType = AnnotationCoordinate::Longitude;
 
 1726       mGridLines.append( newLine );
 
 1729     currentLevel += gridIntervalX;
 
 1737   if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
 
 1742   double roundCorrection = bbox.
yMaximum() > 0 ? 1.0 : 0.0;
 
 1743   double currentLevel = 
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
 
 1747   double step = ( maxX - minX ) / 20;
 
 1749   bool crosses180 = 
false;
 
 1750   bool crossed180 = 
false;
 
 1755     step = ( maxX + 360.0 - minX ) / 20;
 
 1761   int gridLineCount = 0;
 
 1765     double currentX = minX;
 
 1769       if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
 
 1782         QgsDebugMsg( QStringLiteral( 
"Caught CRS exception %1" ).arg( cse.
what() ) );
 
 1786       if ( crosses180 && currentX > 180.0 )
 
 1794     QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, 
QgsRectangle( 
mMap->rect() ) );
 
 1795     QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
 
 1796     for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
 
 1798       if ( !( *lineIt ).isEmpty() )
 
 1801         newLine.coordinate = currentLevel;
 
 1802         newLine.coordinateType = AnnotationCoordinate::Latitude;
 
 1803         newLine.line = QPolygonF( *lineIt );
 
 1804         mGridLines.append( newLine );
 
 1808     currentLevel -= mEvaluatedIntervalY;
 
 1816   if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
 
 1821   double roundCorrection = bbox.
xMinimum() > 0 ? 1.0 : 0.0;
 
 1822   double currentLevel = 
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
 
 1826   double step = ( maxY - minY ) / 20;
 
 1831   bool crosses180 = 
false;
 
 1832   bool crossed180 = 
false;
 
 1839   int gridLineCount = 0;
 
 1840   while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount < 
MAX_GRID_LINES )
 
 1843     double currentY = minY;
 
 1847       if ( currentY > maxY )
 
 1861         QgsDebugMsg( QStringLiteral( 
"Caught CRS exception %1" ).arg( cse.
what() ) );
 
 1867     QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, 
QgsRectangle( 
mMap->rect() ) );
 
 1868     QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
 
 1869     for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
 
 1871       if ( !( *lineIt ).isEmpty() )
 
 1874         newLine.coordinate = currentLevel;
 
 1875         newLine.coordinateType = AnnotationCoordinate::Longitude;
 
 1876         newLine.line = QPolygonF( *lineIt );
 
 1877         mGridLines.append( newLine );
 
 1881     currentLevel += mEvaluatedIntervalX;
 
 1882     if ( crosses180 && currentLevel > 180.0 )
 
 1884       currentLevel -= 360.0;
 
 1913       return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
 
 1915       return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
 
 1917       return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
 
 1919       return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
 
 1934   if ( ddValue.compare( QLatin1String( 
"x_only" ), Qt::CaseInsensitive ) == 0 )
 
 1936   else if ( ddValue.compare( QLatin1String( 
"y_only" ), Qt::CaseInsensitive ) == 0 )
 
 1938   else if ( ddValue.compare( QLatin1String( 
"disabled" ), Qt::CaseInsensitive ) == 0 )
 
 1940   else if ( ddValue.compare( QLatin1String( 
"all" ), Qt::CaseInsensitive ) == 0 )
 
 1947 void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
 
 1952   switch ( mGridUnit )
 
 1965       if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
 
 1967         mEvaluatedEnabled = 
false;
 
 1972         const double mapWidthMapUnits = mapWidth();
 
 1973         double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
 
 1974         double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
 
 1976         mEvaluatedIntervalX = interval;
 
 1977         mEvaluatedIntervalY = interval;
 
 2000 double QgsLayoutItemMapGrid::mapWidth()
 const 
 2011     return mapExtent.
width();
 
 2028 bool sortByDistance( QPair<qreal, QgsLayoutItemMapGrid::BorderSide> a, QPair<qreal, QgsLayoutItemMapGrid::BorderSide> b )
 
 2030   return a.first < b.first;
 
 2043   if ( ( p.y() <= tolerance && p.x() <= tolerance ) 
 
 2044        || ( p.y() <= tolerance && p.x() >= ( 
mMap->rect().width() - tolerance ) ) 
 
 2045        || ( p.y() >= ( 
mMap->rect().height() - tolerance ) && p.x() <= tolerance ) 
 
 2046        || ( p.y() >= ( 
mMap->rect().height() - tolerance ) && p.x() >= ( 
mMap->rect().width() - tolerance ) ) 
 
 2052       if ( p.x() <= tolerance )
 
 2063       if ( p.y() <= tolerance )
 
 2075   QList< QPair<qreal, QgsLayoutItemMapGrid::BorderSide > > distanceToSide;
 
 2081   std::sort( distanceToSide.begin(), distanceToSide.end(), 
sortByDistance );
 
 2082   return distanceToSide.at( 0 ).second;
 
 2087   mGridLineSymbol.reset( symbol );
 
 2092   return mGridLineSymbol.get();
 
 2097   return mGridLineSymbol.get();
 
 2102   mGridMarkerSymbol.reset( symbol );
 
 2107   return mGridMarkerSymbol.get();
 
 2112   return mGridMarkerSymbol.get();
 
 2117   mAnnotationFormat.
setFont( font );
 
 2118   if ( font.pointSizeF() > 0 )
 
 2120     mAnnotationFormat.
setSize( font.pointSizeF() );
 
 2123   else if ( font.pixelSize() > 0 )
 
 2125     mAnnotationFormat.
setSize( font.pixelSize() );
 
 2132   return mAnnotationFormat.
toQFont();
 
 2137   mAnnotationFormat.
setColor( color );
 
 2142   return mAnnotationFormat.
color();
 
 2150       mLeftGridAnnotationDisplay = display;
 
 2153       mRightGridAnnotationDisplay = display;
 
 2156       mTopGridAnnotationDisplay = display;
 
 2159       mBottomGridAnnotationDisplay = display;
 
 2163   refreshDataDefinedProperties();
 
 2177       return mLeftGridAnnotationDisplay;
 
 2179       return mRightGridAnnotationDisplay;
 
 2181       return mTopGridAnnotationDisplay;
 
 2183       return mBottomGridAnnotationDisplay;
 
 2185   return mBottomGridAnnotationDisplay; 
 
 2192   double bottom = 0.0;
 
 2195   return std::max( std::max( std::max( top, right ), bottom ), left );
 
 2205   if ( !
mMap || !mEvaluatedEnabled )
 
 2215   GridExtension extension;
 
 2218   switch ( mGridUnit )
 
 2225         drawGridCrsTransform( context, 0, 
true );
 
 2232       drawGridNoTransform( context, 0, 
true );
 
 2237     updateGridLinesAnnotationsPositions();
 
 2241     drawGridFrame( 
nullptr, &extension );
 
 2244   if ( mShowGridAnnotation )
 
 2249   top = extension.top;
 
 2250   right = extension.right;
 
 2251   bottom = extension.bottom;
 
 2252   left = extension.left;
 
 2258   refreshDataDefinedProperties();
 
 2263   if ( unit == mGridUnit )
 
 2268   mTransformDirty = 
true;
 
 2277   mGridIntervalX = interval;
 
 2278   mTransformDirty = 
true;
 
 2279   refreshDataDefinedProperties();
 
 2288   mGridIntervalY = interval;
 
 2289   mTransformDirty = 
true;
 
 2290   refreshDataDefinedProperties();
 
 2299   mGridOffsetX = offset;
 
 2300   mTransformDirty = 
true;
 
 2301   refreshDataDefinedProperties();
 
 2310   mGridOffsetY = offset;
 
 2311   mTransformDirty = 
true;
 
 2312   refreshDataDefinedProperties();
 
 2321   mMinimumIntervalWidth = minWidth;
 
 2322   mTransformDirty = 
true;
 
 2323   refreshDataDefinedProperties();
 
 2332   mMaximumIntervalWidth = maxWidth;
 
 2333   mTransformDirty = 
true;
 
 2334   refreshDataDefinedProperties();
 
 2339   if ( 
style == mGridStyle )
 
 2344   mTransformDirty = 
true;
 
 2349   mCrossLength = length;
 
 2350   refreshDataDefinedProperties();
 
 2358       mLeftGridAnnotationDirection = direction;
 
 2361       mRightGridAnnotationDirection = direction;
 
 2364       mTopGridAnnotationDirection = direction;
 
 2367       mBottomGridAnnotationDirection = direction;
 
 2380   mGridFrameSides = flags;
 
 2386     mGridFrameSides |= flag;
 
 2388     mGridFrameSides &= ~flag;
 
 2393   return mGridFrameSides;
 
 2402   context.
setHighlightedVariables( QStringList() << QStringLiteral( 
"grid_number" ) << QStringLiteral( 
"grid_axis" ) );
 
 2408   if ( mGridLineSymbol )
 
 2414   if ( mGridMarkerSymbol )
 
 2426   mTransformDirty = 
true;
 
 2427   refreshDataDefinedProperties();
 
 2434   return mGridFrameSides.testFlag( flag );
 
 2439   mGridFrameWidth = width;
 
 2440   refreshDataDefinedProperties();
 
 2445   mGridFrameMargin = margin;
 
 2446   refreshDataDefinedProperties();
 
 2451   mGridFramePenThickness = width;
 
 2452   refreshDataDefinedProperties();
 
 2457   mLeftGridAnnotationDirection = direction;
 
 2458   mRightGridAnnotationDirection = direction;
 
 2459   mTopGridAnnotationDirection = direction;
 
 2460   mBottomGridAnnotationDirection = direction;
 
 2468       mLeftGridAnnotationPosition = position;
 
 2471       mRightGridAnnotationPosition = position;
 
 2474       mTopGridAnnotationPosition = position;
 
 2477       mBottomGridAnnotationPosition = position;
 
 2493       return mLeftGridAnnotationPosition;
 
 2495       return mRightGridAnnotationPosition;
 
 2497       return mTopGridAnnotationPosition;
 
 2499       return mBottomGridAnnotationPosition;
 
 2501   return mLeftGridAnnotationPosition; 
 
 2506   mAnnotationFrameDistance = distance;
 
 2507   refreshDataDefinedProperties();
 
 2514     return mLeftGridAnnotationDirection;
 
 2520       return mLeftGridAnnotationDirection;
 
 2522       return mRightGridAnnotationDirection;
 
 2524       return mTopGridAnnotationDirection;
 
 2526       return mBottomGridAnnotationDirection;
 
 2528   return mLeftGridAnnotationDirection; 
 
 2536       mLeftFrameDivisions = divisions;
 
 2539       mRightFrameDivisions = divisions;
 
 2542       mTopFrameDivisions = divisions;
 
 2545       mBottomFrameDivisions = divisions;
 
 2549   refreshDataDefinedProperties();
 
 2562       return mLeftFrameDivisions;
 
 2564       return mRightFrameDivisions;
 
 2566       return mTopFrameDivisions;
 
 2568       return mBottomFrameDivisions;
 
 2570   return mLeftFrameDivisions; 
 
 2584     QRectF mbr = mapPolygon.boundingRect();
 
 2585     QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
 
 2591       QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
 
 2592       QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
 
 2594       lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
 
 2595       upperRight = tr.transform( upperRight.x(), upperRight.y() );
 
 2597       if ( lowerLeft.x() > upperRight.x() )
 
 2605         crsRect = tr.transformBoundingBox( mapBoundingRect );
 
 2610       crsRect = tr.transformBoundingBox( mapBoundingRect );
 
 2618     QgsDebugMsg( QStringLiteral( 
"Caught CRS exception %1" ).arg( cse.
what() ) );
 
 2624 QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap( 
const QPolygonF &line, 
const QgsRectangle &rect )
 
 2632   QList<QPolygonF> trimmedLines;
 
 2633   QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
 
 2634   for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
 
 2636     trimmedLines << ( *geomIt ).asQPolygonF();
 
 2638   return trimmedLines;
 
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Custom exception class for Coordinate Reference System related exceptions.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
QgsUnitTypes::DistanceUnit lengthUnits() const
Returns the units of distance for length calculations made by this object.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
Class for parsing and evaluation of expressions (formerly called "search strings").
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
A geometry is the spatial representation of a feature.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
QList< QgsLayoutItemMapGrid * > asList() const
Returns a list of QgsLayoutItemMapGrids contained by the stack.
void calculateMaxGridExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void removeGrid(const QString &gridId)
Removes a grid with matching gridId from the stack and deletes the corresponding QgsLayoutItemMapGrid...
double maxGridExtension() const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void addGrid(QgsLayoutItemMapGrid *grid)
Adds a new map grid to the stack and takes ownership of the grid.
QgsLayoutItemMapGrid * grid(const QString &gridId) const
Returns a reference to a grid with matching gridId within the stack.
bool readXml(const QDomElement &elem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets the item stack's state from a DOM document, where element is a DOM node corresponding to a 'Layo...
QgsLayoutItemMapGrid & operator[](int index)
Returns a reference to a grid at the specified index within the stack.
void moveGridUp(const QString &gridId)
Moves a grid with matching gridId up the stack, causing it to be rendered above other grids.
void moveGridDown(const QString &gridId)
Moves a grid with matching gridId down the stack, causing it to be rendered below other grids.
QgsLayoutItemMapGridStack(QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGridStack, attached to the specified map.
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
void setFrameSideFlags(QgsLayoutItemMapGrid::FrameSideFlags flags)
Sets flags for grid frame sides.
GridStyle
Grid drawing style.
@ Markers
Draw markers at intersections of grid lines.
@ Cross
Draw line crosses at intersections of grid lines.
@ FrameAnnotationsOnly
No grid lines over the map, only draw frame and annotations.
void calculateMaxExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect.
GridUnit
Unit for grid values.
@ CM
Grid units in centimeters.
@ MM
Grid units in millimeters.
@ DynamicPageSizeBased
Dynamically sized, based on a on-page size range.
@ MapUnit
Grid units follow map units.
bool writeXml(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Stores map item state in a DOM element, where element is the DOM element corresponding to a 'LayoutMa...
void refresh() override
Refreshes the object, causing a recalculation of any property overrides.
GridStyle style() const
Returns the grid's style, which controls how the grid is drawn over the map's contents.
void setFrameSideFlag(QgsLayoutItemMapGrid::FrameSideFlag flag, bool on=true)
Sets whether the grid frame is drawn for a certain side of the map item.
FrameSideFlag
Flags for controlling which side of the map a frame is drawn on.
@ FrameTop
Top side of map.
@ FrameBottom
Bottom side of map.
@ FrameLeft
Left side of map.
@ FrameRight
Right side of map.
Q_DECL_DEPRECATED void setAnnotationFontColor(const QColor &color)
Sets the font color used for drawing grid annotations.
void draw(QPainter *painter) override
Draws the item on to a destination painter.
void setIntervalY(double interval)
Sets the interval between grid lines in the y-direction.
Q_DECL_DEPRECATED QColor annotationFontColor() const
Returns the font color used for drawing grid annotations.
void setFramePenSize(const double width)
Sets the width of the stroke drawn in the grid frame.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
void setAnnotationDisplay(DisplayMode display, BorderSide border)
Sets what types of grid annotations should be drawn for a specified side of the map frame,...
Q_DECL_DEPRECATED QFont annotationFont() const
Returns the font used for drawing grid annotations.
double maxExtension() const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect (in layout u...
AnnotationPosition
Position for grid annotations.
@ InsideMapFrame
Draw annotations inside the map frame.
@ OutsideMapFrame
Draw annotations outside the map frame.
void setAnnotationPosition(AnnotationPosition position, BorderSide side)
Sets the position for the grid annotations on a specified side of the map frame.
AnnotationPosition annotationPosition(BorderSide side) const
Returns the position for the grid annotations on a specified side of the map frame.
void setUnits(GridUnit unit)
Sets the unit to use for grid measurements such as the interval and offset for grid lines.
QgsLayoutItemMapGrid::FrameSideFlags frameSideFlags() const
Returns the flags which control which sides of the map item the grid frame is drawn on.
bool readXml(const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets the map item state from a DOM document, where element is the DOM node corresponding to a 'Layout...
bool testFrameSideFlag(FrameSideFlag flag) const
Tests whether the grid frame should be drawn on a specified side of the map item.
void setFrameDivisions(DisplayMode divisions, BorderSide side)
Sets what type of grid divisions should be used for frames on a specified side of the map.
void setMinimumIntervalWidth(double width)
Sets the minimum width (in millimeters) for grid segments.
AnnotationCoordinate
Annotation coordinate type.
@ Latitude
Coordinate is a latitude value.
@ Longitude
Coordinate is a longitude value.
void setIntervalX(double interval)
Sets the interval between grid lines in the x-direction.
void setCrossLength(const double length)
Sets the length (in layout units) of the cross segments drawn for the grid.
void setEnabled(bool enabled) override
Controls whether the item will be drawn.
DisplayMode
Display settings for grid annotations and frames.
@ LongitudeOnly
Show longitude/x annotations/divisions only.
@ ShowAll
Show both latitude and longitude annotations/divisions.
@ LatitudeOnly
Show latitude/y annotations/divisions only.
void setAnnotationFrameDistance(const double distance)
Sets the distance between the map frame and annotations.
void crsChanged()
Emitted whenever the grid's CRS is changed.
void setFrameMargin(const double margin)
Sets the grid frame margin (in layout units).
QgsLayoutItemMapGrid(const QString &name, QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGrid.
~QgsLayoutItemMapGrid() override
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used for drawing grid points.
void setMaximumIntervalWidth(double width)
Sets the maximum width (in millimeters) for grid segments.
bool usesAdvancedEffects() const override
Returns true if the item is drawn using advanced effects, such as blend modes.
Q_DECL_DEPRECATED void setAnnotationFont(const QFont &font)
Sets the font used for drawing grid annotations.
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used for drawing grid lines.
QgsCoordinateReferenceSystem crs() const
Retrieves the CRS for the grid.
TickLengthMode
Tick length mode (useful for rotated grids)
@ OrthogonalTicks
Align ticks orthogonaly.
AnnotationFormat
Format for displaying grid annotations.
@ DegreeMinuteSecondNoSuffix
Degree/minutes/seconds, use - for S/W coordinates.
@ DegreeMinuteSecondPadded
Degree/minutes/seconds, with minutes using leading zeros where required.
@ DegreeMinuteSecond
Degree/minutes/seconds, use NSEW suffix.
@ DecimalWithSuffix
Decimal degrees, use NSEW suffix.
@ DegreeMinute
Degree/minutes, use NSEW suffix.
@ DegreeMinuteNoSuffix
Degree/minutes, use - for S/W coordinates.
@ Decimal
Decimal degrees, use - for S/W coordinates.
@ DegreeMinutePadded
Degree/minutes, with minutes using leading zeros where required.
@ CustomFormat
Custom expression-based format.
DisplayMode frameDivisions(BorderSide side) const
Returns the type of grid divisions which are used for frames on a specified side of the map.
AnnotationDirection
Direction of grid annotations.
@ OnTick
Draw annotations parallel to tick (on the line)
@ Horizontal
Draw annotations horizontally.
@ Vertical
Draw annotations vertically, ascending.
@ AboveTick
Draw annotations parallel to tick (above the line)
@ UnderTick
Draw annotations parallel to tick (under the line)
@ VerticalDescending
Draw annotations vertically, descending.
GridUnit units() const
Returns the units used for grid measurements such as the interval and offset for grid lines.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs for the grid.
void setOffsetY(double offset)
Sets the offset for grid lines in the y-direction.
const QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol used for drawing grid points.
const QgsLineSymbol * lineSymbol() const
Returns the line symbol used for drawing grid lines.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
FrameStyle
Style for grid frame.
@ Zebra
Black/white pattern.
@ InteriorTicks
Tick markers drawn inside map frame.
@ LineBorder
Simple solid line frame.
@ InteriorExteriorTicks
Tick markers drawn both inside and outside the map frame.
@ LineBorderNautical
Simple solid line frame, with nautical style diagonals on corners.
@ ExteriorTicks
Tick markers drawn outside map frame.
@ NoFrame
Disable grid frame.
@ ZebraNautical
Black/white pattern, with nautical style diagonals on corners.
void setFrameWidth(const double width)
Sets the grid frame width (in layout units).
DisplayMode annotationDisplay(BorderSide border) const
Returns the display mode for the grid annotations on a specified side of the map frame.
void setOffsetX(double offset)
Sets the offset for grid lines in the x-direction.
BorderSide
Border sides for annotations.
AnnotationDirection annotationDirection(BorderSide border) const
Returns the direction for drawing frame annotations, on the specified side of the map.
void setAnnotationDirection(AnnotationDirection direction, BorderSide side)
Sets the direction for drawing frame annotations for the specified map side.
void setGridLineColor(const QColor &color)
Sets the color of grid lines.
void setGridLineWidth(double width)
Sets the width of grid lines (in layout units).
void setStyle(GridStyle style)
Sets the grid style, which controls how the grid is drawn over the map's contents.
A collection of map items which are drawn above the map content in a QgsLayoutItemMap.
void addItem(QgsLayoutItemMapItem *item)
Adds a new map item to the stack and takes ownership of the item.
void removeItem(const QString &itemId)
Removes an item which matching itemId from the stack and deletes the corresponding QgsLayoutItemMapIt...
QgsLayoutItemMapItem * item(int index) const
Returns a reference to the item at the specified index within the stack.
void moveItemUp(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items.
void removeItems()
Clears the item stack and deletes all QgsLayoutItemMapItems contained by the stack.
QList< QgsLayoutItemMapItem * > mItems
void moveItemDown(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items.
An item which is drawn inside a QgsLayoutItemMap, e.g., a grid or map overview.
QgsLayoutItemMap * mMap
Associated map.
virtual bool readXml(const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context)
Sets the map item state from a DOM document, where element is the DOM node corresponding to a 'Layout...
virtual bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Stores map item state in a DOM element, where element is the DOM element corresponding to a 'LayoutMa...
virtual void setEnabled(bool enabled)
Controls whether the item will be drawn.
bool enabled() const
Returns whether the item will be drawn.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Layout graphical items for displaying a map.
void extentChanged()
Emitted when the map's extent changes.
QPointF mapToItemCoords(QPointF mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset)
void updateBoundingRect()
Updates the bounding rect of this item. Call this function before doing any changes related to annota...
void mapRotationChanged(double newRotation)
Emitted when the map's rotation changes.
void crsChanged()
Emitted when the map's coordinate reference system is changed.
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
QgsRectangle extent() const
Returns the current map extent.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
bool frameEnabled() const
Returns true if the item includes a frame.
QgsPropertyCollection mDataDefinedProperties
const QgsLayout * layout() const
Returns the layout the object is attached to.
QPointer< QgsLayout > mLayout
@ MapGridIntervalX
Map grid interval X.
@ MapGridAnnotationDisplayBottom
Map annotation display bottom.
@ MapGridIntervalY
Map grid interval Y.
@ MapGridFrameSize
Map grid frame size.
@ MapGridFrameDivisionsBottom
Map frame division display bottom.
@ MapGridAnnotationDisplayRight
Map annotation display right.
@ MapGridFrameMargin
Map grid frame margin.
@ MapGridOffsetX
Map grid offset X.
@ MapGridLabelDistance
Map grid label distance.
@ MapGridAnnotationDisplayLeft
Map annotation display left.
@ MapGridFrameDivisionsLeft
Map frame division display left.
@ MapGridEnabled
Map grid enabled.
@ MapGridFrameLineThickness
Map grid frame line thickness.
@ MapGridFrameDivisionsRight
Map frame division display right.
@ MapGridFrameDivisionsTop
Map frame division display top.
@ MapGridCrossSize
Map grid cross size.
@ MapGridOffsetY
Map grid offset Y.
@ MapGridAnnotationDisplayTop
Map annotation display top.
QgsLayoutRenderContext::Flags flags() const
Returns the current combination of flags used for rendering the layout.
@ FlagAntialiasing
Use antialiasing when drawing items.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static double calculatePrettySize(double minimumSize, double maximumSize)
Calculates a "pretty" size which falls between the range [minimumSize, maximumSize].
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
A line symbol type, for rendering LineString and MultiLineString geometries.
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
A marker symbol type, for rendering Point and MultiPoint geometries.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
A class to represent a 2D point.
bool isEmpty() const SIP_HOLDGIL
Returns true if the geometry is empty.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Contains information about the context of a rendering operation.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
Scoped object for saving and restoring a QPainter object's state.
Scoped object for temporary scaling of a QgsRenderContext for pixel based rendering.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
static QColor decodeColor(const QString &str)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QString encodeColor(const QColor &color)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
QFont toQFont() const
Returns a QFont matching the relevant settings from this text format.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
QColor color() const
Returns the color that text will be rendered in.
static double textWidth(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics=nullptr)
Returns the width of a text based on a given format.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode=Point, QFontMetricsF *fontMetrics=nullptr)
Returns the height of a text based on a given format.
static void drawText(const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, VAlignment vAlignment=AlignTop)
Draws text within a rectangle using the specified settings.
DistanceUnit
Units of distance.
@ DistanceUnknownUnit
Unknown distance unit.
@ LayoutMillimeters
Millimeters.
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
@ RenderPoints
Points (e.g., for font sizes)
@ RenderMillimeters
Millimeters.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QgsLayoutItemMapGrid::DisplayMode gridAnnotationDisplayModeFromDD(QString ddValue, QgsLayoutItemMapGrid::DisplayMode defValue)
bool sortByDistance(QPair< qreal, QgsLayoutItemMapGrid::BorderSide > a, QPair< qreal, QgsLayoutItemMapGrid::BorderSide > b)
QVector2D borderToNormal2D(QgsLayoutItemMapGrid::BorderSide border)
QVector2D borderToVector2D(QgsLayoutItemMapGrid::BorderSide border)
const QgsCoordinateReferenceSystem & crs
Single variable definition for use within a QgsExpressionContextScope.
Contains information relating to the style entity currently being visited.