54#include "moc_qgslayoutitemmapgrid.cpp"
56using namespace Qt::StringLiterals;
58#define MAX_GRID_LINES 1000
87 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
93 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
98 QList< QgsLayoutItemMapGrid * > list;
121 const QDomNodeList mapGridNodeList = elem.elementsByTagName( u
"ComposerMapGrid"_s );
122 for (
int i = 0; i < mapGridNodeList.size(); ++i )
124 const QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
126 mapGrid->
readXml( mapGridElem, doc, context );
140 return std::max( std::max( std::max( top, right ), bottom ), left );
154 double gridTop = 0.0;
155 double gridRight = 0.0;
156 double gridBottom = 0.0;
157 double gridLeft = 0.0;
158 grid->calculateMaxExtension( gridTop, gridRight, gridBottom, gridLeft );
159 top = std::max( top, gridTop );
160 right = std::max( right, gridRight );
161 bottom = std::max( bottom, gridBottom );
162 left = std::max( left, gridLeft );
178 return QVector2D( 0, 1 );
180 return QVector2D( -1, 0 );
182 return QVector2D( 0, -1 );
184 return QVector2D( 1, 0 );
192 return QVector2D( borderVector.y(), -borderVector.x() );
197 , mGridFrameSides(
Qgis::MapGridFrameSideFlag::
Left |
Qgis::MapGridFrameSideFlag::
Right |
Qgis::MapGridFrameSideFlag::Top |
Qgis::MapGridFrameSideFlag::Bottom )
201 if ( !defaultFontString.isEmpty() )
204 QgsFontUtils::setFontFamily( font, defaultFontString );
205 mAnnotationFormat.setFont( font );
208 createDefaultGridLineSymbol();
209 createDefaultGridMarkerSymbol();
214 if ( !mCRS.isValid() )
221void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
223 QVariantMap properties;
224 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
225 properties.insert( u
"width"_s, u
"0.3"_s );
226 properties.insert( u
"capstyle"_s, u
"flat"_s );
230void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
232 QVariantMap properties;
233 properties.insert( u
"name"_s, u
"circle"_s );
234 properties.insert( u
"size"_s, u
"2.0"_s );
235 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
241 if ( mGridLineSymbol )
243 mGridLineSymbol->setWidth( width );
249 if ( mGridLineSymbol )
251 mGridLineSymbol->setColor(
c );
262 QDomElement mapGridElem = doc.createElement( u
"ComposerMapGrid"_s );
263 mapGridElem.setAttribute( u
"gridStyle"_s,
static_cast< int >( mGridStyle ) );
270 QDomElement lineStyleElem = doc.createElement( u
"lineStyle"_s );
272 lineStyleElem.appendChild( gridLineStyleElem );
273 mapGridElem.appendChild( lineStyleElem );
275 QDomElement markerStyleElem = doc.createElement( u
"markerStyle"_s );
277 markerStyleElem.appendChild( gridMarkerStyleElem );
278 mapGridElem.appendChild( markerStyleElem );
280 mapGridElem.setAttribute( u
"gridFrameStyle"_s,
static_cast< int >( mGridFrameStyle ) );
281 mapGridElem.setAttribute( u
"gridFrameSideFlags"_s, mGridFrameSides );
282 mapGridElem.setAttribute( u
"gridFrameWidth"_s,
qgsDoubleToString( mGridFrameWidth ) );
283 mapGridElem.setAttribute( u
"gridFrameMargin"_s,
qgsDoubleToString( mGridFrameMargin ) );
284 mapGridElem.setAttribute( u
"gridFramePenThickness"_s,
qgsDoubleToString( mGridFramePenThickness ) );
288 mapGridElem.setAttribute( u
"leftFrameDivisions"_s,
static_cast< int >( mLeftFrameDivisions ) );
289 mapGridElem.setAttribute( u
"rightFrameDivisions"_s,
static_cast< int >( mRightFrameDivisions ) );
290 mapGridElem.setAttribute( u
"topFrameDivisions"_s,
static_cast< int >( mTopFrameDivisions ) );
291 mapGridElem.setAttribute( u
"bottomFrameDivisions"_s,
static_cast< int >( mBottomFrameDivisions ) );
292 mapGridElem.setAttribute( u
"rotatedTicksLengthMode"_s,
static_cast< int >( mRotatedTicksLengthMode ) );
293 mapGridElem.setAttribute( u
"rotatedTicksEnabled"_s, mRotatedTicksEnabled );
294 mapGridElem.setAttribute( u
"rotatedTicksMinimumAngle"_s, QString::number( mRotatedTicksMinimumAngle ) );
295 mapGridElem.setAttribute( u
"rotatedTicksMarginToCorner"_s, QString::number( mRotatedTicksMarginToCorner ) );
296 mapGridElem.setAttribute( u
"rotatedAnnotationsLengthMode"_s,
static_cast< int >( mRotatedAnnotationsLengthMode ) );
297 mapGridElem.setAttribute( u
"rotatedAnnotationsEnabled"_s, mRotatedAnnotationsEnabled );
298 mapGridElem.setAttribute( u
"rotatedAnnotationsMinimumAngle"_s, QString::number( mRotatedAnnotationsMinimumAngle ) );
299 mapGridElem.setAttribute( u
"rotatedAnnotationsMarginToCorner"_s, QString::number( mRotatedAnnotationsMarginToCorner ) );
300 if ( mCRS.isValid() )
302 mCRS.writeXml( mapGridElem, doc );
305 mapGridElem.setAttribute( u
"annotationFormat"_s,
static_cast< int >( mGridAnnotationFormat ) );
306 mapGridElem.setAttribute( u
"showAnnotation"_s, mShowGridAnnotation );
307 mapGridElem.setAttribute( u
"annotationExpression"_s, mGridAnnotationExpressionString );
308 mapGridElem.setAttribute( u
"leftAnnotationDisplay"_s,
static_cast< int >( mLeftGridAnnotationDisplay ) );
309 mapGridElem.setAttribute( u
"rightAnnotationDisplay"_s,
static_cast< int >( mRightGridAnnotationDisplay ) );
310 mapGridElem.setAttribute( u
"topAnnotationDisplay"_s,
static_cast< int >( mTopGridAnnotationDisplay ) );
311 mapGridElem.setAttribute( u
"bottomAnnotationDisplay"_s,
static_cast< int >( mBottomGridAnnotationDisplay ) );
312 mapGridElem.setAttribute( u
"leftAnnotationPosition"_s,
static_cast< int >( mLeftGridAnnotationPosition ) );
313 mapGridElem.setAttribute( u
"rightAnnotationPosition"_s,
static_cast< int >( mRightGridAnnotationPosition ) );
314 mapGridElem.setAttribute( u
"topAnnotationPosition"_s,
static_cast< int >( mTopGridAnnotationPosition ) );
315 mapGridElem.setAttribute( u
"bottomAnnotationPosition"_s,
static_cast< int >( mBottomGridAnnotationPosition ) );
316 mapGridElem.setAttribute( u
"leftAnnotationDirection"_s,
static_cast< int >( mLeftGridAnnotationDirection ) );
317 mapGridElem.setAttribute( u
"rightAnnotationDirection"_s,
static_cast< int >( mRightGridAnnotationDirection ) );
318 mapGridElem.setAttribute( u
"topAnnotationDirection"_s,
static_cast< int >( mTopGridAnnotationDirection ) );
319 mapGridElem.setAttribute( u
"bottomAnnotationDirection"_s,
static_cast< int >( mBottomGridAnnotationDirection ) );
320 mapGridElem.setAttribute( u
"frameAnnotationDistance"_s, QString::number( mAnnotationFrameDistance ) );
321 mapGridElem.appendChild( mAnnotationFormat.writeXml( doc, context ) );
322 mapGridElem.setAttribute( u
"annotationPrecision"_s, mGridAnnotationPrecision );
323 mapGridElem.setAttribute( u
"unit"_s,
static_cast< int >( mGridUnit ) );
324 mapGridElem.setAttribute( u
"blendMode"_s, mBlendMode );
325 mapGridElem.setAttribute( u
"minimumIntervalWidth"_s, QString::number( mMinimumIntervalWidth ) );
326 mapGridElem.setAttribute( u
"maximumIntervalWidth"_s, QString::number( mMaximumIntervalWidth ) );
334 elem.appendChild( mapGridElem );
341 if ( itemElem.isNull() )
349 mGridStyle =
static_cast< Qgis::MapGridStyle >( itemElem.attribute( u
"gridStyle"_s, u
"0"_s ).toInt() );
350 mGridIntervalX = itemElem.attribute( u
"intervalX"_s, u
"0"_s ).toDouble();
351 mGridIntervalY = itemElem.attribute( u
"intervalY"_s, u
"0"_s ).toDouble();
352 mGridOffsetX = itemElem.attribute( u
"offsetX"_s, u
"0"_s ).toDouble();
353 mGridOffsetY = itemElem.attribute( u
"offsetY"_s, u
"0"_s ).toDouble();
354 mCrossLength = itemElem.attribute( u
"crossLength"_s, u
"3"_s ).toDouble();
355 mGridFrameStyle =
static_cast< Qgis::MapGridFrameStyle >( itemElem.attribute( u
"gridFrameStyle"_s, u
"0"_s ).toInt() );
357 mGridFrameWidth = itemElem.attribute( u
"gridFrameWidth"_s, u
"2.0"_s ).toDouble();
358 mGridFrameMargin = itemElem.attribute( u
"gridFrameMargin"_s, u
"0.0"_s ).toDouble();
359 mGridFramePenThickness = itemElem.attribute( u
"gridFramePenThickness"_s, u
"0.3"_s ).toDouble();
367 mRotatedTicksLengthMode =
static_cast< Qgis::MapGridTickLengthMode >( itemElem.attribute( u
"rotatedTicksLengthMode"_s, u
"0"_s ).toInt() );
368 mRotatedTicksEnabled = itemElem.attribute( u
"rotatedTicksEnabled"_s, u
"0"_s ) !=
"0"_L1;
369 mRotatedTicksMinimumAngle = itemElem.attribute( u
"rotatedTicksMinimumAngle"_s, u
"0"_s ).toDouble();
370 mRotatedTicksMarginToCorner = itemElem.attribute( u
"rotatedTicksMarginToCorner"_s, u
"0"_s ).toDouble();
371 mRotatedAnnotationsLengthMode =
static_cast< Qgis::MapGridTickLengthMode >( itemElem.attribute( u
"rotatedAnnotationsLengthMode"_s, u
"0"_s ).toInt() );
372 mRotatedAnnotationsEnabled = itemElem.attribute( u
"rotatedAnnotationsEnabled"_s, u
"0"_s ) !=
"0"_L1;
373 mRotatedAnnotationsMinimumAngle = itemElem.attribute( u
"rotatedAnnotationsMinimumAngle"_s, u
"0"_s ).toDouble();
374 mRotatedAnnotationsMarginToCorner = itemElem.attribute( u
"rotatedAnnotationsMarginToCorner"_s, u
"0"_s ).toDouble();
376 const QDomElement lineStyleElem = itemElem.firstChildElement( u
"lineStyle"_s );
377 if ( !lineStyleElem.isNull() )
379 const QDomElement symbolElem = lineStyleElem.firstChildElement( u
"symbol"_s );
380 if ( !symbolElem.isNull() )
389 mGridLineSymbol->setWidth( itemElem.attribute( u
"penWidth"_s, u
"0"_s ).toDouble() );
390 mGridLineSymbol->setColor(
391 QColor( itemElem.attribute( u
"penColorRed"_s, u
"0"_s ).toInt(), itemElem.attribute( u
"penColorGreen"_s, u
"0"_s ).toInt(), itemElem.attribute( u
"penColorBlue"_s, u
"0"_s ).toInt() )
395 const QDomElement markerStyleElem = itemElem.firstChildElement( u
"markerStyle"_s );
396 if ( !markerStyleElem.isNull() )
398 const QDomElement symbolElem = markerStyleElem.firstChildElement( u
"symbol"_s );
399 if ( !symbolElem.isNull() )
405 if ( !mCRS.readXml( itemElem ) )
408 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( u
"blendMode"_s, u
"0"_s ).toUInt() );
411 mShowGridAnnotation = ( itemElem.attribute( u
"showAnnotation"_s, u
"0"_s ) !=
"0"_L1 );
413 mGridAnnotationExpressionString = itemElem.attribute( u
"annotationExpression"_s );
414 mGridAnnotationExpression.reset();
428 mAnnotationFrameDistance = itemElem.attribute( u
"frameAnnotationDistance"_s, u
"0"_s ).toDouble();
430 if ( !itemElem.firstChildElement(
"text-style" ).isNull() )
432 mAnnotationFormat.readXml( itemElem, context );
439 font.fromString( itemElem.attribute(
"annotationFont", QString() ) );
441 mAnnotationFormat.setFont( font );
442 mAnnotationFormat.setSize( font.pointSizeF() );
447 mGridAnnotationPrecision = itemElem.attribute( u
"annotationPrecision"_s, u
"3"_s ).toInt();
448 const int gridUnitInt = itemElem.attribute( u
"unit"_s, QString::number(
static_cast< int >(
Qgis::MapGridUnit::MapUnits ) ) ).toInt();
450 mMinimumIntervalWidth = itemElem.attribute( u
"minimumIntervalWidth"_s, u
"50"_s ).toDouble();
451 mMaximumIntervalWidth = itemElem.attribute( u
"maximumIntervalWidth"_s, u
"100"_s ).toDouble();
455 refreshDataDefinedProperties();
465 mTransformDirty =
true;
471 return mBlendMode != QPainter::CompositionMode_SourceOver;
474QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
476 const QTransform t = QTransform::fromScale( scale, scale );
477 return t.map( polygon );
480void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
482 if ( !
mMap || !mEvaluatedEnabled )
488 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
489 if ( mapPolygon != mPrevMapPolygon )
491 mTransformDirty =
true;
492 mPrevMapPolygon = mapPolygon;
495 if ( mTransformDirty )
497 calculateCrsTransformLines();
501 if ( !calculateLinesOnly )
503 int countLongitudeLines = 0;
504 int countLatitudeLines = 0;
505 for (
const GridLine &line : mGridLines )
507 switch ( line.coordinateType )
510 countLongitudeLines++;
513 countLatitudeLines++;
518 int latitudeLineIndex = 0;
519 int longitudeLineIndex = 0;
522 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
524 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
526 switch ( gridIt->coordinateType )
529 longitudeLineIndex++;
543 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
546 if ( drawnCount >= MAX_GRID_LINES )
552 const double maxX =
mMap->rect().width();
553 const double maxY =
mMap->rect().height();
555 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
557 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
559 const double x = intersectionIt->x();
560 const double y = intersectionIt->y();
564 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
565 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
566 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
567 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
568 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
569 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
572 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
573 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
577 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
581 if ( drawnCount >= MAX_GRID_LINES )
588void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
590 QgsRectangle crsBoundingRect;
591 QgsCoordinateTransform inverseTr;
592 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
599 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
600 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
607 QList< QgsGeometry > xLines;
608 QList< QgsGeometry > yLines;
609 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
610 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
613 for (
int i = 0; i < gridIt->line.size(); ++i )
615 line.append( QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
624 mTransformedIntersections.clear();
625 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
626 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
628 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
629 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
632 const QgsGeometry intersects = ( *yLineIt ).intersection( ( *xLineIt ) );
633 if ( intersects.
isNull() )
638 QgsPointXY vertex = intersects.
vertexAt( i );
641 mTransformedIntersections << vertex;
649 mTransformDirty =
false;
654 if ( !
mMap || !mEvaluatedEnabled )
658 QPaintDevice *paintDevice = p->device();
665 p->setCompositionMode( mBlendMode );
668 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
669 p->setClipRect( thisPaintRect );
670 if ( thisPaintRect != mPrevPaintRect )
673 mTransformDirty =
true;
674 mPrevPaintRect = thisPaintRect;
678 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
679 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
694 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
696 drawGridCrsTransform( context, dotsPerMM );
703 drawGridNoTransform( context, dotsPerMM );
708 p->setClipping(
false );
712 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
717 updateGridLinesAnnotationsPositions();
724 if ( mShowGridAnnotation )
730void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
732 QList< GridLine >::iterator it = mGridLines.begin();
733 int annotationCount = 0;
734 for ( ; it != mGridLines.end(); ++it )
736 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
737 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
738 it->startAnnotation.position = QVector2D( it->line.first() );
739 it->endAnnotation.position = QVector2D( it->line.last() );
740 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
741 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
743 it->startAnnotation.angle
744 = 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() );
746 it->endAnnotation.angle
747 = 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() );
749 if ( annotationCount >= MAX_GRID_FRAME_OBJECTS )
754void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
758 calculateYGridLines();
759 calculateXGridLines();
761 if ( calculateLinesOnly || mGridLines.empty() )
764 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
765 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
767 int countLongitudeLines = 0;
768 int countLatitudeLines = 0;
769 for (
const GridLine &line : mGridLines )
771 switch ( line.coordinateType )
774 countLongitudeLines++;
777 countLatitudeLines++;
782 int latitudeLineIndex = 0;
783 int longitudeLineIndex = 0;
792 for ( ; vIt != mGridLines.constEnd(); ++vIt )
796 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
798 longitudeLineIndex++;
804 drawGridLine( line, context );
806 if ( drawnCount >= MAX_GRID_LINES )
810 for ( ; hIt != mGridLines.constEnd(); ++hIt )
814 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
822 drawGridLine( line, context );
824 if ( drawnCount >= MAX_GRID_LINES )
831 QPointF intersectionPoint, crossEnd1, crossEnd2;
833 for ( ; vIt != mGridLines.constEnd(); ++vIt )
838 l1 = QLineF( vIt->line.first(), vIt->line.last() );
841 hIt = mGridLines.constBegin();
842 for ( ; hIt != mGridLines.constEnd(); ++hIt )
847 l2 = QLineF( hIt->line.first(), hIt->line.last() );
849 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
859 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
863 drawGridMarker( intersectionPoint * dotsPerMM, context );
868 if ( drawnCount >= MAX_GRID_LINES )
878 hIt = mGridLines.constBegin();
879 for ( ; hIt != mGridLines.constEnd(); ++hIt )
884 l1 = QLineF( hIt->line.first(), hIt->line.last() );
886 vIt = mGridLines.constBegin();
887 for ( ; vIt != mGridLines.constEnd(); ++vIt )
892 l2 = QLineF( vIt->line.first(), vIt->line.last() );
894 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
902 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
906 if ( drawnCount >= MAX_GRID_LINES )
912void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
914 QgsScopedQPainterState painterState( p );
920 mCurrentComponentDrawCount = 0;
922 switch ( mGridFrameStyle )
926 drawGridFrameZebra( p, extension );
931 drawGridFrameTicks( p, extension );
936 drawGridFrameLine( p, extension );
944void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
947 poly << line.p1() << line.p2();
948 drawGridLine( poly, context );
951void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
953 if ( !
mMap || !
mMap->layout() || !mGridLineSymbol )
958 mGridLineSymbol->startRender( context );
959 mGridLineSymbol->renderPolyline( line,
nullptr, context );
960 mGridLineSymbol->stopRender( context );
963void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
965 if ( !
mMap || !
mMap->layout() || !mGridMarkerSymbol )
970 mGridMarkerSymbol->startRender( context );
971 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
972 mGridMarkerSymbol->stopRender( context );
975void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
995void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
Qgis::MapGridBorderSide border,
double *extension )
const
1002 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1007 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
1011 double currentCoord = 0.0;
1012 bool color1 =
false;
1018 bool drawTLBox =
false;
1019 bool drawTRBox =
false;
1020 bool drawBLBox =
false;
1021 bool drawBRBox =
false;
1023 QMap< double, double > pos = QMap< double, double >();
1024 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1025 for ( ; it != mGridLines.constEnd(); ++it )
1028 for (
int i = 0; i < 2; ++i )
1030 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1033 if ( annot.border != border )
1036 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1040 pos.insert( annot.position.y(), it->coordinate );
1042 pos.insert( annot.position.x(), it->coordinate );
1049 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
1065 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
1069 QPen framePen = QPen( mGridFramePenColor );
1070 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1071 framePen.setJoinStyle( Qt::MiterJoin );
1072 p->setPen( framePen );
1074 QMap< double, double >::const_iterator posIt = pos.constBegin();
1075 for ( ; posIt != pos.constEnd(); ++posIt )
1077 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1080 height = posIt.key() - currentCoord;
1081 width = mEvaluatedGridFrameWidth;
1087 height = mEvaluatedGridFrameWidth;
1088 width = posIt.key() - currentCoord;
1090 y = ( border ==
Qgis::MapGridBorderSide::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
1092 p->drawRect( QRectF( x, y, width, height ) );
1093 currentCoord = posIt.key();
1096 mCurrentComponentDrawCount++;
1097 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1104 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin );
1105 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1107 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1109 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1111 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1113 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1117void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1127 QPen framePen = QPen( mGridFramePenColor );
1128 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1129 framePen.setCapStyle( Qt::FlatCap );
1130 p->setBrush( Qt::NoBrush );
1131 p->setPen( framePen );
1134 QList< GridLine >::iterator it = mGridLines.begin();
1135 for ( ; it != mGridLines.end(); ++it )
1138 for (
int i = 0; i < 2; ++i )
1140 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1142 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1146 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1154 facingLeft = ( annot.angle != 0 );
1155 facingRight = ( annot.angle != 0 );
1159 facingLeft = ( annot.angle > 0 );
1160 facingRight = ( annot.angle < 0 );
1164 facingLeft = ( annot.angle < 0 );
1165 facingRight = ( annot.angle > 0 );
1169 && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1172 && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1175 && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1178 && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1182 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1184 double fA = mEvaluatedGridFrameMargin;
1185 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1189 fA /= QVector2D::dotProduct( vector, normalVector );
1190 fB /= QVector2D::dotProduct( vector, normalVector );
1197 extension->UpdateBorder( annot.border, fB );
1205 pA = annot.position +
static_cast< float >( fA ) * vector;
1206 pB = annot.position +
static_cast< float >( fB ) * vector;
1210 pA = annot.position -
static_cast< float >( fA ) * vector;
1211 pB = annot.position -
static_cast< float >( fB ) * vector;
1215 pA = annot.position -
static_cast< float >( fB ) * vector;
1216 pB = annot.position +
static_cast< float >( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1218 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1220 mCurrentComponentDrawCount++;
1221 if ( mCurrentComponentDrawCount >= MAX_GRID_TICKS )
1226void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1236 QPen framePen = QPen( mGridFramePenColor );
1237 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1238 framePen.setCapStyle( Qt::SquareCap );
1239 p->setBrush( Qt::NoBrush );
1240 p->setPen( framePen );
1250 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1259 QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1268 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1277 QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1281 if ( !extension && drawDiagonals )
1286 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1287 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1288 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1293 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1294 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1295 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1300 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1301 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1302 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1307 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1308 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1309 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1316 if ( mGridLines.empty() )
1319 mCurrentComponentDrawCount = 0;
1321 QString currentAnnotationString;
1322 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1324 QgsExpressionContextScope *gridScope =
new QgsExpressionContextScope();
1325 QgsExpressionContextScopePopper scopePopper( expressionContext, gridScope );
1327 bool geographic =
false;
1328 if ( mCRS.isValid() )
1330 geographic = mCRS.isGeographic();
1334 geographic =
mMap->crs().isGeographic();
1337 const bool forceWrap
1340 int countLongitudeLines = 0;
1341 int countLatitudeLines = 0;
1342 for (
const GridLine &line : mGridLines )
1344 switch ( line.coordinateType )
1347 countLongitudeLines++;
1350 countLatitudeLines++;
1355 int latitudeLineIndex = 0;
1356 int longitudeLineIndex = 0;
1357 for ( ; it != mGridLines.constEnd(); ++it )
1359 double value = it->coordinate;
1360 switch ( it->coordinateType )
1363 longitudeLineIndex++;
1364 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLongitudeLines,
true ) );
1365 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, longitudeLineIndex,
true ) );
1366 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"x"_s,
true ) );
1370 latitudeLineIndex++;
1371 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLatitudeLines,
true ) );
1372 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, latitudeLineIndex,
true ) );
1373 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"y"_s,
true ) );
1380 const double wrappedX = std::fmod( value, 360.0 );
1381 if ( wrappedX > 180.0 )
1383 value = wrappedX - 360.0;
1385 else if ( wrappedX < -180.0 )
1387 value = wrappedX + 360.0;
1391 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_number"_s, value,
true ) );
1393 if ( mDrawAnnotationProperty )
1396 const bool display = mDrawAnnotationProperty->valueAsBool( expressionContext,
true, &ok );
1397 if ( ok && !display )
1400 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext, geographic );
1401 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1402 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1403 mCurrentComponentDrawCount++;
1404 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1409void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
1418 if ( !shouldShowAnnotationForSide( coordinateType, annot.border ) )
1423 double dotsPerMM = 1;
1427 painterState.save();
1428 dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
1429 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1440 double textWidthPainterUnits = sizePainterUnits.width();
1442 textWidthPainterUnits *= 1.1;
1444 const double textWidthMM = textWidthPainterUnits * painterUnitsToMM;
1446 double textHeightPainterUnits = 0;
1447 if ( extension || doc.
size() > 1 )
1449 textHeightPainterUnits = sizePainterUnits.height();
1458 const double textHeightMM = textHeightPainterUnits * painterUnitsToMM;
1464 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1468 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1471 double distanceToFrameMM = mEvaluatedAnnotationFrameDistance;
1476 const bool hasExteriorMargin
1479 const bool hasBorderWidth
1482 distanceToFrameMM += mEvaluatedGridFrameWidth;
1483 if ( hasBorderWidth )
1484 distanceToFrameMM += mEvaluatedGridFrameLineThickness / 2.0;
1487 distanceToFrameMM *= -1;
1491 distanceToFrameMM /= QVector2D::dotProduct( vector, normalVector );
1494 QPointF annotationPositionMM = ( annot.position +
static_cast< float >( distanceToFrameMM ) * vector ).toPointF();
1499 double rotation = 0;
1503 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1505 if ( rotation <= -90 || rotation > 90 )
1508 anchorMM.setX( outside ? 0 : textWidthMM );
1512 anchorMM.setX( outside ? textWidthMM : 0 );
1516 anchorMM.setY( 0.5 * textHeightMM );
1518 anchorMM.setY( -1.5 * textHeightMM );
1520 anchorMM.setY( -0.5 * textHeightMM );
1525 anchorMM.setX( 0.5 * textWidthMM );
1526 anchorMM.setY( -0.5 * textHeightMM );
1528 anchorMM.setY( outside ? 0 : -textHeightMM );
1530 anchorMM.setX( outside ? 0 : textWidthMM );
1532 anchorMM.setY( outside ? -textHeightMM : 0 );
1534 anchorMM.setX( outside ? textWidthMM : 0 );
1539 anchorMM.setX( 0.5 * textWidthMM );
1540 anchorMM.setY( -0.5 * textHeightMM );
1542 anchorMM.setX( outside ? 0 : textWidthMM );
1544 anchorMM.setY( outside ? -textHeightMM : 0 );
1546 anchorMM.setX( outside ? textWidthMM : 0 );
1548 anchorMM.setY( outside ? 0 : -textHeightMM );
1553 anchorMM.setX( 0.5 * textWidthMM );
1554 anchorMM.setY( -0.5 * textHeightMM );
1556 anchorMM.setX( outside ? textWidthMM : 0 );
1558 anchorMM.setY( outside ? 0 : -textHeightMM );
1560 anchorMM.setX( outside ? 0 : textWidthMM );
1562 anchorMM.setY( outside ? -textHeightMM : 0 );
1567 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1568 anchorMM.setX( 0.5 * textWidthMM );
1570 anchorMM.setY( -textHeightMM );
1578 extension->UpdateBorder( frameBorder, -distanceToFrameMM + std::max( textHeightMM, textWidthMM ) );
1580 extension->UpdateAll( std::max( textHeightMM, textWidthMM ) / 2.0 );
1583 if ( extension || !context.
painter() )
1587 bool facingLeft = ( annot.angle < 0 );
1588 bool facingRight = ( annot.angle > 0 );
1591 facingLeft = !facingLeft;
1592 facingRight = !facingRight;
1594 const QRectF mapRect =
mMap->rect();
1596 && ( ( facingLeft && !
qgsDoubleGreaterThanOrNear( annot.position.x(),mRotatedAnnotationsMarginToCorner,ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM) )
1597 || ( facingRight && !
qgsDoubleLessThanOrNear( annot.position.x(), mapRect.width() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1600 && ( ( facingLeft && !
qgsDoubleLessThanOrNear( annot.position.x(), mapRect.width() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1601 || ( facingRight && !
qgsDoubleGreaterThanOrNear( annot.position.x(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1604 && ( ( facingLeft && !
qgsDoubleLessThanOrNear( annot.position.y(), mapRect.height() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1605 || ( facingRight && !
qgsDoubleGreaterThanOrNear( annot.position.y(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1608 && ( ( facingLeft && !
qgsDoubleGreaterThanOrNear( annot.position.y(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1609 || ( facingRight && !
qgsDoubleLessThanOrNear( annot.position.y(), mapRect.height() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1616 QPointF textPos( 0, 0 );
1617 switch ( annot.border )
1634 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1637 textPos.setX( textWidthMM / painterUnitsToMM );
1643 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1665 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1668 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1672 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1687 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1712 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1715 textPos.setX( textWidthMM / painterUnitsToMM );
1727 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1748 context.
painter()->translate( QPointF( annotationPositionMM.x(), annotationPositionMM.y() ) / painterUnitsToMM );
1749 context.
painter()->rotate( rotation );
1750 context.
painter()->translate( -anchorMM / painterUnitsToMM );
1761 return QString::number( value,
'f', mGridAnnotationPrecision );
1767 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1771 if ( !isGeographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1773 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1779 if ( !isGeographic || coordRounded != 0.0 )
1781 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1787 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1791 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1796 if ( !mGridAnnotationExpression )
1798 mGridAnnotationExpression = std::make_unique<QgsExpression>( mGridAnnotationExpressionString );
1799 mGridAnnotationExpression->prepare( &expressionContext );
1801 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1806 switch ( mGridAnnotationFormat )
1856void QgsLayoutItemMapGrid::calculateXGridLines()
const
1858 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1863 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1864 QRectF mapBoundingRect = mapPolygon.boundingRect();
1865 double gridIntervalY = mEvaluatedIntervalY;
1866 double gridOffsetY = mEvaluatedOffsetY;
1867 double annotationScale = 1.0;
1868 switch ( mGridUnit )
1873 mapBoundingRect =
mMap->rect();
1874 mapPolygon = QPolygonF(
mMap->rect() );
1877 annotationScale = 0.1;
1878 gridIntervalY *= 10;
1889 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY ) * gridIntervalY + gridOffsetY;
1891 currentLevel += gridIntervalY;
1893 int gridLineCount = 0;
1898 double yCanvasCoord;
1899 while (
qgsDoubleLessThanOrNear( currentLevel, mapBoundingRect.bottom(), GRID_LINE_CLOSE_TO_EDGE_TOLERANCE_MAP_UNITS ) && gridLineCount < MAX_GRID_OBJECTS )
1901 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1903 newLine.coordinate = currentLevel * annotationScale;
1905 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1906 mGridLines.append( newLine );
1907 currentLevel += gridIntervalY;
1914 QVector<QLineF> borderLines;
1915 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1916 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1917 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1918 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1920 QVector<QPointF> intersectionList;
1922 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount < MAX_GRID_OBJECTS )
1924 intersectionList.clear();
1925 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1927 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1928 for ( ; it != borderLines.constEnd(); ++it )
1930 QPointF intersectionPoint;
1931 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1933 intersectionList.push_back( intersectionPoint );
1934 if ( intersectionList.size() >= 2 )
1941 if ( intersectionList.size() >= 2 )
1944 newLine.coordinate = currentLevel;
1946 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1947 mGridLines.append( newLine );
1950 currentLevel += gridIntervalY;
1954void QgsLayoutItemMapGrid::calculateYGridLines()
const
1956 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1961 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1962 QRectF mapBoundingRect = mapPolygon.boundingRect();
1963 double gridIntervalX = mEvaluatedIntervalX;
1964 double gridOffsetX = mEvaluatedOffsetX;
1965 double annotationScale = 1.0;
1966 switch ( mGridUnit )
1971 mapBoundingRect =
mMap->rect();
1972 mapPolygon = QPolygonF(
mMap->rect() );
1975 annotationScale = 0.1;
1976 gridIntervalX *= 10;
1987 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX ) * gridIntervalX + gridOffsetX;
1989 currentLevel += gridIntervalX;
1991 int gridLineCount = 0;
1995 double xCanvasCoord;
1996 while (
qgsDoubleLessThanOrNear( currentLevel, mapBoundingRect.right(), GRID_LINE_CLOSE_TO_EDGE_TOLERANCE_MAP_UNITS ) && gridLineCount < MAX_GRID_OBJECTS )
1998 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
2001 newLine.coordinate = currentLevel * annotationScale;
2003 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
2004 mGridLines.append( newLine );
2005 currentLevel += gridIntervalX;
2012 QVector<QLineF> borderLines;
2013 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
2014 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
2015 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
2016 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
2018 QVector<QPointF> intersectionList;
2020 while ( currentLevel <= mapBoundingRect.right() && gridLineCount < MAX_GRID_OBJECTS )
2022 intersectionList.clear();
2023 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
2025 QVector<QLineF>::const_iterator it = borderLines.constBegin();
2026 for ( ; it != borderLines.constEnd(); ++it )
2028 QPointF intersectionPoint;
2029 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
2031 intersectionList.push_back( intersectionPoint );
2032 if ( intersectionList.size() >= 2 )
2039 if ( intersectionList.size() >= 2 )
2042 newLine.coordinate = currentLevel;
2044 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
2045 mGridLines.append( newLine );
2048 currentLevel += gridIntervalX;
2054 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
2059 const double roundCorrection = bbox.
yMaximum() > mEvaluatedOffsetY ? 1.0 : 0.0;
2060 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
2062 const double minX = bbox.
xMinimum();
2063 const double maxX = bbox.
xMaximum();
2064 double step = ( maxX - minX ) / 20;
2066 bool crosses180 =
false;
2067 bool crossed180 =
false;
2068 if ( mCRS.isGeographic() && ( minX > maxX ) )
2072 step = ( maxX + 360.0 - minX ) / 20;
2078 int gridLineCount = 0;
2079 while ( currentLevel >= bbox.
yMinimum() && gridLineCount < MAX_GRID_OBJECTS )
2082 double currentX = minX;
2086 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
2093 const QgsPointXY mapPoint = t.
transform( currentX, currentLevel );
2094 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2096 catch ( QgsCsException &cse )
2103 if ( crosses180 && currentX > 180.0 )
2111 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2112 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2113 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2115 if ( !( *lineIt ).isEmpty() )
2118 newLine.coordinate = currentLevel;
2120 newLine.line = QPolygonF( *lineIt );
2121 mGridLines.append( newLine );
2125 currentLevel -= mEvaluatedIntervalY;
2133 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
2138 const double roundCorrection = bbox.
xMinimum() > mEvaluatedOffsetX ? 1.0 : 0.0;
2139 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
2141 const double minY = bbox.
yMinimum();
2142 const double maxY = bbox.
yMaximum();
2143 const double step = ( maxY - minY ) / 20;
2148 bool crosses180 =
false;
2149 bool crossed180 =
false;
2156 int gridLineCount = 0;
2157 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount < MAX_GRID_OBJECTS )
2160 double currentY = minY;
2164 if ( currentY > maxY )
2171 const QgsPointXY mapPoint = t.
transform( currentLevel, currentY );
2173 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2175 catch ( QgsCsException &cse )
2184 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2185 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2186 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2188 if ( !( *lineIt ).isEmpty() )
2191 newLine.coordinate = currentLevel;
2193 newLine.line = QPolygonF( *lineIt );
2194 mGridLines.append( newLine );
2198 currentLevel += mEvaluatedIntervalX;
2199 if ( crosses180 && currentLevel > 180.0 )
2201 currentLevel -= 360.0;
2230 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
2232 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
2234 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
2236 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
2250 if ( ddValue.compare(
"x_only"_L1, Qt::CaseInsensitive ) == 0 )
2252 else if ( ddValue.compare(
"y_only"_L1, Qt::CaseInsensitive ) == 0 )
2254 else if ( ddValue.compare(
"disabled"_L1, Qt::CaseInsensitive ) == 0 )
2256 else if ( ddValue.compare(
"all"_L1, Qt::CaseInsensitive ) == 0 )
2262void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
2267 mTransformDirty = mTransformDirty
2278 mDrawAnnotationProperty->prepare( context );
2282 mDrawAnnotationProperty.reset();
2285 switch ( mGridUnit )
2298 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
2300 mEvaluatedEnabled =
false;
2305 const double mapWidthMapUnits = mapWidth();
2306 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2307 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2309 mEvaluatedIntervalX = interval;
2310 mEvaluatedIntervalY = interval;
2311 mTransformDirty =
true;
2323 mEvaluatedLeftGridAnnotationDisplay
2325 mEvaluatedRightGridAnnotationDisplay
2327 mEvaluatedTopGridAnnotationDisplay
2329 mEvaluatedBottomGridAnnotationDisplay
2334 mEvaluatedBottomFrameDivisions
2338double QgsLayoutItemMapGrid::mapWidth()
const
2345 const QgsRectangle mapExtent =
mMap->extent();
2349 return mapExtent.
width();
2365 catch ( QgsCsException & )
2368 QgsDebugError( u
"An error occurred while calculating length"_s );
2374bool sortByDistance( QPair<qreal, Qgis::MapGridBorderSide> a, QPair<qreal, Qgis::MapGridBorderSide> b )
2376 return a.first < b.first;
2386 const double tolerance = std::max(
mMap->frameEnabled() ?
mMap->pen().widthF() : 0.0, 1.0 );
2390 ( p.y() <= tolerance && p.x() <= tolerance )
2391 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2392 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2393 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2399 if ( p.x() <= tolerance )
2410 if ( p.y() <= tolerance )
2422 QList< QPair<qreal, Qgis::MapGridBorderSide > > distanceToSide;
2428 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2429 return distanceToSide.at( 0 ).second;
2434 mGridLineSymbol.reset( symbol );
2439 return mGridLineSymbol.get();
2444 return mGridLineSymbol.get();
2449 mGridMarkerSymbol.reset( symbol );
2454 return mGridMarkerSymbol.get();
2459 return mGridMarkerSymbol.get();
2464 mAnnotationFormat.setFont( font );
2465 if ( font.pointSizeF() > 0 )
2467 mAnnotationFormat.setSize( font.pointSizeF() );
2470 else if ( font.pixelSize() > 0 )
2472 mAnnotationFormat.setSize( font.pixelSize() );
2479 return mAnnotationFormat.toQFont();
2484 mAnnotationFormat.
setColor( color );
2489 return mAnnotationFormat.color();
2497 mLeftGridAnnotationDisplay = display;
2500 mRightGridAnnotationDisplay = display;
2503 mTopGridAnnotationDisplay = display;
2506 mBottomGridAnnotationDisplay = display;
2510 refreshDataDefinedProperties();
2514 mMap->updateBoundingRect();
2524 return mLeftGridAnnotationDisplay;
2526 return mRightGridAnnotationDisplay;
2528 return mTopGridAnnotationDisplay;
2530 return mBottomGridAnnotationDisplay;
2532 return mBottomGridAnnotationDisplay;
2539 double bottom = 0.0;
2542 return std::max( std::max( std::max( top, right ), bottom ), left );
2552 if ( !
mMap || !mEvaluatedEnabled )
2562 GridExtension extension;
2565 switch ( mGridUnit )
2570 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
2572 drawGridCrsTransform( context, 0,
true );
2579 drawGridNoTransform( context, 0,
true );
2584 updateGridLinesAnnotationsPositions();
2588 drawGridFrame(
nullptr, &extension );
2591 if ( mShowGridAnnotation )
2596 top = extension.top;
2597 right = extension.right;
2598 bottom = extension.bottom;
2599 left = extension.left;
2605 refreshDataDefinedProperties();
2610 if ( unit == mGridUnit )
2615 mTransformDirty =
true;
2624 mGridIntervalX = interval;
2625 mTransformDirty =
true;
2626 refreshDataDefinedProperties();
2635 mGridIntervalY = interval;
2636 mTransformDirty =
true;
2637 refreshDataDefinedProperties();
2646 mGridOffsetX = offset;
2647 mTransformDirty =
true;
2648 refreshDataDefinedProperties();
2657 mGridOffsetY = offset;
2658 mTransformDirty =
true;
2659 refreshDataDefinedProperties();
2668 mMinimumIntervalWidth = minWidth;
2669 mTransformDirty =
true;
2670 refreshDataDefinedProperties();
2679 mMaximumIntervalWidth = maxWidth;
2680 mTransformDirty =
true;
2681 refreshDataDefinedProperties();
2686 if (
style == mGridStyle )
2691 mTransformDirty =
true;
2696 mCrossLength = length;
2697 refreshDataDefinedProperties();
2705 mLeftGridAnnotationDirection = direction;
2708 mRightGridAnnotationDirection = direction;
2711 mTopGridAnnotationDirection = direction;
2714 mBottomGridAnnotationDirection = direction;
2720 mMap->updateBoundingRect();
2727 mGridFrameSides = flags;
2732 mGridFrameSides.setFlag( flag, on );
2737 return mGridFrameSides;
2752 if ( mGridLineSymbol )
2758 if ( mGridMarkerSymbol )
2770 mTransformDirty =
true;
2771 refreshDataDefinedProperties();
2772 mMap->updateBoundingRect();
2778 return mGridFrameSides.testFlag( flag );
2783 mGridFrameWidth = width;
2784 refreshDataDefinedProperties();
2789 mGridFrameMargin = margin;
2790 refreshDataDefinedProperties();
2795 mGridFramePenThickness = width;
2796 refreshDataDefinedProperties();
2806 mHAlign = alignment;
2811 mLeftGridAnnotationDirection = direction;
2812 mRightGridAnnotationDirection = direction;
2813 mTopGridAnnotationDirection = direction;
2814 mBottomGridAnnotationDirection = direction;
2822 mLeftGridAnnotationPosition = position;
2825 mRightGridAnnotationPosition = position;
2828 mTopGridAnnotationPosition = position;
2831 mBottomGridAnnotationPosition = position;
2837 mMap->updateBoundingRect();
2847 return mLeftGridAnnotationPosition;
2849 return mRightGridAnnotationPosition;
2851 return mTopGridAnnotationPosition;
2853 return mBottomGridAnnotationPosition;
2855 return mLeftGridAnnotationPosition;
2860 mAnnotationFrameDistance = distance;
2861 refreshDataDefinedProperties();
2868 return mLeftGridAnnotationDirection;
2874 return mLeftGridAnnotationDirection;
2876 return mRightGridAnnotationDirection;
2878 return mTopGridAnnotationDirection;
2880 return mBottomGridAnnotationDirection;
2882 return mLeftGridAnnotationDirection;
2887 mGridAnnotationExpressionString = expression;
2888 mGridAnnotationExpression.reset();
2896 mLeftFrameDivisions = divisions;
2899 mRightFrameDivisions = divisions;
2902 mTopFrameDivisions = divisions;
2905 mBottomFrameDivisions = divisions;
2909 refreshDataDefinedProperties();
2922 return mLeftFrameDivisions;
2924 return mRightFrameDivisions;
2926 return mTopFrameDivisions;
2928 return mBottomFrameDivisions;
2930 return mLeftFrameDivisions;
2942 const QgsCoordinateTransform tr(
mMap->crs(), mCRS,
mLayout->project() );
2943 QgsCoordinateTransform extentTransform = tr;
2945 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
2946 const QRectF mbr = mapPolygon.boundingRect();
2947 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2950 if ( mCRS.isGeographic() )
2953 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2954 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2956 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2957 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2959 if ( lowerLeft.x() > upperRight.x() )
2975 inverseTransform = QgsCoordinateTransform( mCRS,
mMap->crs(),
mLayout->project() );
2977 catch ( QgsCsException &cse )
2986QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2991 const QgsGeometry intersected = lineGeom.
intersection( rectGeom );
2994 QList<QPolygonF> trimmedLines;
2995 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2996 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2998 trimmedLines << ( *geomIt ).asQPolygonF();
3000 return trimmedLines;
3075 refreshDataDefinedProperties();
Provides global constants and enumerations for use throughout the application.
MapGridTickLengthMode
Map grid tick length mode (useful for rotated grids).
@ OrthogonalTicks
Align ticks orthogonaly.
QFlags< MapGridFrameSideFlag > MapGridFrameSideFlags
Flags for controlling which side of the map a frame is drawn on.
@ Default
Allow raster-based rendering in situations where it is required for correct rendering or where it wil...
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
@ Millimeters
Millimeters.
MapGridAnnotationPosition
Position for map grid annotations.
@ InsideMapFrame
Draw annotations inside the map frame.
@ OutsideMapFrame
Draw annotations outside the map frame.
MapGridUnit
Units for map grid values.
@ Centimeters
Grid units in centimeters.
@ Millimeters
Grid units in millimeters.
@ DynamicPageSizeBased
Dynamically sized, based on a on-page size range.
@ MapUnits
Grid units follow map units.
DistanceUnit
Units of distance.
@ Unknown
Unknown distance unit.
MapGridBorderSide
Border sides for map grid annotations.
MapGridFrameSideFlag
Flags for controlling which side of the map a frame is drawn on.
@ Bottom
Bottom side of map.
@ Right
Right side of map.
@ Point
Text at point of origin layout mode.
MapGridComponentVisibility
Visibility display settings for map grid annotations and frames.
@ ShowAll
Show both latitude and longitude annotations/divisions.
@ LongitudeOnly
Show longitude/x annotations/divisions only.
@ LatitudeOnly
Show latitude/y annotations/divisions only.
@ Horizontal
Horizontally oriented text.
MapGridStyle
Map grid drawing styles.
@ LineCrosses
Draw line crosses at intersections of grid lines.
@ Markers
Draw markers at intersections of grid lines.
@ Lines
Draw lines for grid.
@ FrameAndAnnotationsOnly
No grid lines over the map, only draw frame and annotations.
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
MapGridAnnotationType
Annotation coordinate type.
@ Latitude
Coordinate is a latitude value.
@ Longitude
Coordinate is a longitude value.
MapGridFrameStyle
Style for map grid frames.
@ LineBorderNautical
Simple solid line frame, with nautical style diagonals on corners.
@ ZebraNautical
Black/white pattern, with nautical style diagonals on corners.
@ InteriorExteriorTicks
Tick markers drawn both inside and outside the map frame.
@ NoFrame
Disable grid frame.
@ ExteriorTicks
Tick markers drawn outside map frame.
@ Zebra
Black/white pattern.
@ LineBorder
Simple solid line frame.
@ InteriorTicks
Tick markers drawn inside map frame.
MapGridAnnotationDirection
Direction of grid annotations.
@ Vertical
Draw annotations vertically, ascending.
@ UnderTick
Draw annotations parallel to tick (under the line).
@ VerticalDescending
Draw annotations vertically, descending.
@ BoundaryDirection
Annotations follow the boundary direction.
@ AboveTick
Draw annotations parallel to tick (above the line).
@ OnTick
Draw annotations parallel to tick (on the line).
@ Horizontal
Draw annotations horizontally.
TextHorizontalAlignment
Text horizontal alignment.
MapGridAnnotationFormat
Format for displaying map grid annotations.
@ DegreeMinute
Degree/minutes, use NSEW suffix.
@ DegreeMinuteSecond
Degree/minutes/seconds, use NSEW suffix.
@ DegreeMinuteNoSuffix
Degree/minutes, use - for S/W coordinates.
@ CustomFormat
Custom expression-based format.
@ Decimal
Decimal degrees, use - for S/W coordinates.
@ DegreeMinuteSecondNoSuffix
Degree/minutes/seconds, use - for S/W coordinates.
@ DegreeMinutePadded
Degree/minutes, with minutes using leading zeros where required.
@ DegreeMinuteSecondPadded
Degree/minutes/seconds, with minutes using leading zeros where required.
@ DecimalWithSuffix
Decimal degrees, use NSEW suffix.
@ Forward
Forward transform (from source to destination).
@ Antialiasing
Use antialiasing when drawing items.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Represents a coordinate reference system (CRS).
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.
Qgis::DistanceUnit lengthUnits() const
Returns the units of distance for length calculations made by this object.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
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.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
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.
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.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters(), QgsFeedback *feedback=nullptr) const
Returns a geometry representing the points shared by this geometry and other.
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.
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(Qgis::MapGridFrameSideFlags flags)
Sets flags for grid frame sides.
void setRotatedTicksLengthMode(const Qgis::MapGridTickLengthMode mode)
Sets the tick length calculation mode.
bool rotatedAnnotationsEnabled() const
Gets whether annotations rotation for rotated or reprojected grids is enabled.
QString annotationExpression() const
Returns the expression used for drawing grid annotations.
double rotatedTicksMarginToCorner() const
Gets the margin to corners (in canvas units) below which outwards facing ticks are not drawn.
void calculateMaxExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect.
void setFrameFillColor2(const QColor &color)
Sets the second fill color used for the grid frame.
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.
void setAnnotationDisplay(Qgis::MapGridComponentVisibility display, Qgis::MapGridBorderSide border)
Sets what types of grid annotations should be drawn for a specified side of the map frame,...
void setFrameStyle(const Qgis::MapGridFrameStyle style)
Sets the grid frame style.
void setUnits(Qgis::MapGridUnit unit)
Sets the unit to use for grid measurements such as the interval and offset for grid lines.
Q_DECL_DEPRECATED void setAnnotationFontColor(const QColor &color)
Sets the font color used for drawing grid annotations.
double frameWidth() const
Gets the grid frame width in layout units.
void draw(QPainter *painter) override
Draws the item on to a destination painter.
double crossLength() const
Retrieves the length (in layout units) of the cross segments drawn for the grid.
void setIntervalY(double interval)
Sets the interval between grid lines in the y-direction.
void setRotatedTicksMinimumAngle(const double angle)
Sets the minimum angle (in degrees) below which ticks are not drawn.
Q_DECL_DEPRECATED QColor annotationFontColor() const
Returns the font color used for drawing grid annotations.
QPainter::CompositionMode blendMode() const
Retrieves the blending mode used for drawing the grid.
void setAnnotationEnabled(const bool enabled)
Sets whether annotations should be shown for the grid.
QgsTextFormat annotationTextFormat() const
Returns the text format used when rendering grid annotations.
void setStyle(Qgis::MapGridStyle style)
Sets the grid style, which controls how the grid is drawn over the map's contents.
double framePenSize() const
Retrieves the width of the stroke drawn in the grid frame.
void setFramePenColor(const QColor &color)
Sets the color of the stroke drawn in the grid frame.
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 setRotatedTicksEnabled(const bool state)
Enable/disable ticks rotation for rotated or reprojected grids.
Qgis::MapGridUnit units() const
Returns the units used for grid measurements such as the interval and offset for grid lines.
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...
void setFrameDivisions(Qgis::MapGridComponentVisibility divisions, Qgis::MapGridBorderSide side)
Sets what type of grid divisions should be used for frames on a specified side of the map.
Qgis::MapGridStyle style() const
Returns the grid's style, which controls how the grid is drawn over the map's contents.
double rotatedTicksMinimumAngle() const
Gets the minimum angle (in degrees) below which ticks are not drawn.
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...
Qgis::MapGridTickLengthMode rotatedAnnotationsLengthMode() const
Returns the annotation length calculation mode.
Qgis::MapGridFrameStyle frameStyle() const
Returns the grid frame style.
void setMinimumIntervalWidth(double width)
Sets the minimum width (in millimeters) for grid segments.
friend class QgsLayoutItemMap
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 setAnnotationDirection(Qgis::MapGridAnnotationDirection direction, Qgis::MapGridBorderSide side)
Sets the direction for drawing frame annotations for the specified map side.
void setEnabled(bool enabled) override
Controls whether the item will be drawn.
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 setRotatedAnnotationsMinimumAngle(const double angle)
Sets the minimum angle (in degrees) below which annotations are not drawn.
void setFrameMargin(const double margin)
Sets the grid frame margin (in layout units).
double rotatedAnnotationsMinimumAngle() const
Gets the minimum angle (in degrees) below which annotations are not drawn.
void setAnnotationTextFormat(const QgsTextFormat &format)
Sets the text format to use when rendering grid annotations.
QgsLayoutItemMapGrid(const QString &name, QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGrid.
Qgis::MapGridTickLengthMode rotatedTicksLengthMode() const
Returns the grid frame style.
~QgsLayoutItemMapGrid() override
void copyProperties(const QgsLayoutItemMapGrid *other)
Copies properties from specified map grid.
void setBlendMode(const QPainter::CompositionMode mode)
Sets the blending mode used for drawing the grid.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used for drawing grid points.
bool annotationEnabled() const
Returns whether annotations are shown for the grid.
void setMaximumIntervalWidth(double width)
Sets the maximum width (in millimeters) for grid segments.
Qgis::MapGridComponentVisibility frameDivisions(Qgis::MapGridBorderSide side) const
Returns the type of grid divisions which are used for frames on a specified side of the map.
Qgis::MapGridFrameSideFlags frameSideFlags() const
Returns the flags which control which sides of the map item the grid frame is drawn on.
void setAnnotationPosition(Qgis::MapGridAnnotationPosition position, Qgis::MapGridBorderSide side)
Sets the position for the grid annotations on a specified side of the map frame.
QColor framePenColor() const
Retrieves the color of the stroke drawn in the grid frame.
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 setRotatedTicksMarginToCorner(const double margin)
Sets the margin to corners (in canvas units) below which outwards facing ticks are not drawn.
void setAnnotationPrecision(const int precision)
Sets the coordinate precision for grid annotations.
QColor frameFillColor2() const
Retrieves the second fill color for the grid frame.
void setRotatedAnnotationsLengthMode(const Qgis::MapGridTickLengthMode mode)
Sets the annotation length calculation mode.
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used for drawing grid lines.
QgsCoordinateReferenceSystem crs() const
Retrieves the CRS for the grid.
void setRotatedAnnotationsMarginToCorner(const double margin)
Sets the margin to corners (in canvas units) below which outwards facing annotations are not drawn.
double rotatedAnnotationsMarginToCorner() const
Gets the margin to corners (in canvas units) below which outwards facing annotations are not drawn.
double offsetX() const
Returns the offset for grid lines in the x-direction.
bool rotatedTicksEnabled() const
Gets whether ticks rotation for rotated or reprojected grids is enabled.
double annotationFrameDistance() const
Returns the distance between the map frame and annotations.
double intervalY() const
Returns the interval between grid lines in the y-direction.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs for the grid.
bool testFrameSideFlag(Qgis::MapGridFrameSideFlag flag) const
Tests whether the grid frame should be drawn on a specified side of the map item.
double minimumIntervalWidth() const
Returns the minimum width (in millimeters) for grid segments.
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...
QColor frameFillColor1() const
Retrieves the first fill color for the grid frame.
void setRotatedAnnotationsEnabled(const bool state)
Enable/disable annotations rotation for rotated or reprojected grids.
void setAnnotationFormat(const Qgis::MapGridAnnotationFormat format)
Sets the format for drawing grid annotations.
void setFrameWidth(const double width)
Sets the grid frame width (in layout units).
Qgis::MapGridComponentVisibility annotationDisplay(Qgis::MapGridBorderSide border) const
Returns the display mode for the grid annotations on a specified side of the map frame.
void setFrameFillColor1(const QColor &color)
Sets the first fill color used for the grid frame.
double frameMargin() const
Sets the grid frame Margin (in layout units).
void setOffsetX(double offset)
Sets the offset for grid lines in the x-direction.
Qgis::MapGridAnnotationFormat annotationFormat() const
Returns the format for drawing grid annotations.
void setFrameSideFlag(Qgis::MapGridFrameSideFlag flag, bool on=true)
Sets whether the grid frame is drawn for a certain side of the map item.
Qgis::MapGridAnnotationDirection annotationDirection(Qgis::MapGridBorderSide border) const
Returns the direction for drawing frame annotations, on the specified side of the map.
Qgis::MapGridAnnotationPosition annotationPosition(Qgis::MapGridBorderSide side) const
Returns the position for the grid annotations on a specified side of the map frame.
void setGridLineColor(const QColor &color)
Sets the color of grid lines.
void setGridLineWidth(double width)
Sets the width of grid lines (in layout units).
int annotationPrecision() const
Returns the coordinate precision for grid annotations, which is the number of decimal places shown wh...
double maximumIntervalWidth() const
Returns the maximum width (in millimeters) for grid segments.
Qgis::TextHorizontalAlignment horizontalAlignment() const
Returns the horizontal alignment for annotation text.
void setHorizontalAlignment(Qgis::TextHorizontalAlignment alignment)
Sets the horizontal alignment for annotation text.
void setAnnotationExpression(const QString &expression)
Sets the expression used for drawing grid annotations.
double intervalX() const
Returns the interval between grid lines in the x-direction.
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.
QgsLayoutItemMapItemStack(QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapItemStack, attached to the specified map.
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.
QString name() const
Returns the friendly display name for the item.
QgsLayoutItemMapItem(const QString &name, QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapItem, attached to the specified map.
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...
const QgsLayoutItemMap * map() const
Returns the layout item map for the item.
Layout graphical items for displaying a map.
void extentChanged()
Emitted when the map's extent changes.
void mapRotationChanged(double newRotation)
Emitted when the map's rotation changes.
void crsChanged()
Emitted when the map's coordinate reference system is changed.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the object's property collection, used for data defined overrides.
QPointer< QgsLayout > mLayout
@ MapGridOffsetY
Map grid offset Y.
@ MapGridFrameDivisionsBottom
Map frame division display bottom.
@ MapGridEnabled
Map grid enabled.
@ MapGridIntervalX
Map grid interval X.
@ MapGridFrameDivisionsTop
Map frame division display top.
@ MapGridAnnotationDisplayLeft
Map annotation display left.
@ MapGridFrameMargin
Map grid frame margin.
@ MapGridDrawAnnotation
Map annotation visibility (for individual annotations).
@ MapGridCrossSize
Map grid cross size.
@ MapGridAnnotationDisplayRight
Map annotation display right.
@ MapGridOffsetX
Map grid offset X.
@ MapGridAnnotationDisplayTop
Map annotation display top.
@ MapGridAnnotationDisplayBottom
Map annotation display bottom.
@ MapGridFrameDivisionsRight
Map frame division display right.
@ MapGridLabelDistance
Map grid label distance.
@ MapGridIntervalY
Map grid interval Y.
@ MapGridFrameSize
Map grid frame size.
@ MapGridFrameLineThickness
Map grid frame line thickness.
@ MapGridFrameDivisionsLeft
Map frame division display left.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the objects's property collection, used for data defined overrides.
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].
static const QgsSettingsEntryString * settingsLayoutDefaultFont
Settings entry for the default font family used for new layout items.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
static std::unique_ptr< 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 std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
bool isEmpty() const
Returns true if the geometry is empty.
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
Qgis::RasterizedRenderingPolicy rasterizedRenderingPolicy() const
Returns the policy controlling when rasterisation of content during renders is permitted.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Scoped object for saving and restoring a QPainter object's state.
@ NoSave
Do not save the current painter state.
void restore()
Performs a manual restore on the painter state, popping the latest state from the painter.
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 std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
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 QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
void setColor(const QColor &color) const
Sets the color for the symbol.
QSizeF documentSize(Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation) const
Returns the overall size of the document.
static QgsTextDocumentMetrics calculateMetrics(const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor=1.0, const QgsTextDocumentRenderContext &documentContext=QgsTextDocumentRenderContext())
Returns precalculated text metrics for a text document, when rendered using the given base format and...
int size() const
Returns the number of blocks in the document.
static QgsTextDocument fromTextAndFormat(const QStringList &lines, const QgsTextFormat &format)
Constructor for QgsTextDocument consisting of a set of lines, respecting settings from a text format.
static void drawDocument(const QRectF &rect, const QgsTextFormat &format, const QgsTextDocument &document, const QgsTextDocumentMetrics &metrics, QgsRenderContext &context, Qgis::TextHorizontalAlignment horizontalAlignment=Qgis::TextHorizontalAlignment::Left, Qgis::TextVerticalAlignment verticalAlignment=Qgis::TextVerticalAlignment::Top, double rotation=0, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags())
Draws a text document within a rectangle using the specified settings.
static double calculateScaleFactorForFormat(const QgsRenderContext &context, const QgsTextFormat &format)
Returns the scale factor used for upscaling font sizes and downscaling destination painter devices.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Point, QFontMetricsF *fontMetrics=nullptr, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), double maxLineWidth=0)
Returns the height of a text based on a given format.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
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
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
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).
bool qgsDoubleGreaterThanOrNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles to see if one is greater than the other or very near to the other.
bool qgsDoubleLessThanOrNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles to see if one is less than the other or very near to the other.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector2D borderToVector2D(Qgis::MapGridBorderSide border)
bool sortByDistance(QPair< qreal, Qgis::MapGridBorderSide > a, QPair< qreal, Qgis::MapGridBorderSide > b)
Qgis::MapGridComponentVisibility gridAnnotationDisplayModeFromDD(QString ddValue, Qgis::MapGridComponentVisibility defValue)
QVector2D borderToNormal2D(Qgis::MapGridBorderSide border)
#define QgsDebugError(str)
Single variable definition for use within a QgsExpressionContextScope.
Contains information relating to the style entity currently being visited.