53#include "moc_qgslayoutitemmapgrid.cpp"
55using namespace Qt::StringLiterals;
57#define MAX_GRID_LINES 1000
86 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
92 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
97 QList< QgsLayoutItemMapGrid * > list;
120 const QDomNodeList mapGridNodeList = elem.elementsByTagName( u
"ComposerMapGrid"_s );
121 for (
int i = 0; i < mapGridNodeList.size(); ++i )
123 const QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
125 mapGrid->
readXml( mapGridElem, doc, context );
139 return std::max( std::max( std::max( top, right ), bottom ), left );
153 double gridTop = 0.0;
154 double gridRight = 0.0;
155 double gridBottom = 0.0;
156 double gridLeft = 0.0;
157 grid->calculateMaxExtension( gridTop, gridRight, gridBottom, gridLeft );
158 top = std::max( top, gridTop );
159 right = std::max( right, gridRight );
160 bottom = std::max( bottom, gridBottom );
161 left = std::max( left, gridLeft );
177 return QVector2D( 0, 1 );
179 return QVector2D( -1, 0 );
181 return QVector2D( 0, -1 );
183 return QVector2D( 1, 0 );
191 return QVector2D( borderVector.y(), -borderVector.x() );
196 , mGridFrameSides(
Qgis::MapGridFrameSideFlag::
Left |
Qgis::MapGridFrameSideFlag::
Right |
Qgis::MapGridFrameSideFlag::Top |
Qgis::MapGridFrameSideFlag::Bottom )
200 if ( !defaultFontString.isEmpty() )
203 QgsFontUtils::setFontFamily( font, defaultFontString );
204 mAnnotationFormat.setFont( font );
207 createDefaultGridLineSymbol();
208 createDefaultGridMarkerSymbol();
213 if ( !mCRS.isValid() )
220void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
222 QVariantMap properties;
223 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
224 properties.insert( u
"width"_s, u
"0.3"_s );
225 properties.insert( u
"capstyle"_s, u
"flat"_s );
229void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
231 QVariantMap properties;
232 properties.insert( u
"name"_s, u
"circle"_s );
233 properties.insert( u
"size"_s, u
"2.0"_s );
234 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
240 if ( mGridLineSymbol )
242 mGridLineSymbol->setWidth( width );
248 if ( mGridLineSymbol )
250 mGridLineSymbol->setColor(
c );
261 QDomElement mapGridElem = doc.createElement( u
"ComposerMapGrid"_s );
262 mapGridElem.setAttribute( u
"gridStyle"_s,
static_cast< int >( mGridStyle ) );
269 QDomElement lineStyleElem = doc.createElement( u
"lineStyle"_s );
271 lineStyleElem.appendChild( gridLineStyleElem );
272 mapGridElem.appendChild( lineStyleElem );
274 QDomElement markerStyleElem = doc.createElement( u
"markerStyle"_s );
276 markerStyleElem.appendChild( gridMarkerStyleElem );
277 mapGridElem.appendChild( markerStyleElem );
279 mapGridElem.setAttribute( u
"gridFrameStyle"_s,
static_cast< int >( mGridFrameStyle ) );
280 mapGridElem.setAttribute( u
"gridFrameSideFlags"_s, mGridFrameSides );
281 mapGridElem.setAttribute( u
"gridFrameWidth"_s,
qgsDoubleToString( mGridFrameWidth ) );
282 mapGridElem.setAttribute( u
"gridFrameMargin"_s,
qgsDoubleToString( mGridFrameMargin ) );
283 mapGridElem.setAttribute( u
"gridFramePenThickness"_s,
qgsDoubleToString( mGridFramePenThickness ) );
287 mapGridElem.setAttribute( u
"leftFrameDivisions"_s,
static_cast< int >( mLeftFrameDivisions ) );
288 mapGridElem.setAttribute( u
"rightFrameDivisions"_s,
static_cast< int >( mRightFrameDivisions ) );
289 mapGridElem.setAttribute( u
"topFrameDivisions"_s,
static_cast< int >( mTopFrameDivisions ) );
290 mapGridElem.setAttribute( u
"bottomFrameDivisions"_s,
static_cast< int >( mBottomFrameDivisions ) );
291 mapGridElem.setAttribute( u
"rotatedTicksLengthMode"_s,
static_cast< int >( mRotatedTicksLengthMode ) );
292 mapGridElem.setAttribute( u
"rotatedTicksEnabled"_s, mRotatedTicksEnabled );
293 mapGridElem.setAttribute( u
"rotatedTicksMinimumAngle"_s, QString::number( mRotatedTicksMinimumAngle ) );
294 mapGridElem.setAttribute( u
"rotatedTicksMarginToCorner"_s, QString::number( mRotatedTicksMarginToCorner ) );
295 mapGridElem.setAttribute( u
"rotatedAnnotationsLengthMode"_s,
static_cast< int >( mRotatedAnnotationsLengthMode ) );
296 mapGridElem.setAttribute( u
"rotatedAnnotationsEnabled"_s, mRotatedAnnotationsEnabled );
297 mapGridElem.setAttribute( u
"rotatedAnnotationsMinimumAngle"_s, QString::number( mRotatedAnnotationsMinimumAngle ) );
298 mapGridElem.setAttribute( u
"rotatedAnnotationsMarginToCorner"_s, QString::number( mRotatedAnnotationsMarginToCorner ) );
299 if ( mCRS.isValid() )
301 mCRS.writeXml( mapGridElem, doc );
304 mapGridElem.setAttribute( u
"annotationFormat"_s,
static_cast< int >( mGridAnnotationFormat ) );
305 mapGridElem.setAttribute( u
"showAnnotation"_s, mShowGridAnnotation );
306 mapGridElem.setAttribute( u
"annotationExpression"_s, mGridAnnotationExpressionString );
307 mapGridElem.setAttribute( u
"leftAnnotationDisplay"_s,
static_cast< int >( mLeftGridAnnotationDisplay ) );
308 mapGridElem.setAttribute( u
"rightAnnotationDisplay"_s,
static_cast< int >( mRightGridAnnotationDisplay ) );
309 mapGridElem.setAttribute( u
"topAnnotationDisplay"_s,
static_cast< int >( mTopGridAnnotationDisplay ) );
310 mapGridElem.setAttribute( u
"bottomAnnotationDisplay"_s,
static_cast< int >( mBottomGridAnnotationDisplay ) );
311 mapGridElem.setAttribute( u
"leftAnnotationPosition"_s,
static_cast< int >( mLeftGridAnnotationPosition ) );
312 mapGridElem.setAttribute( u
"rightAnnotationPosition"_s,
static_cast< int >( mRightGridAnnotationPosition ) );
313 mapGridElem.setAttribute( u
"topAnnotationPosition"_s,
static_cast< int >( mTopGridAnnotationPosition ) );
314 mapGridElem.setAttribute( u
"bottomAnnotationPosition"_s,
static_cast< int >( mBottomGridAnnotationPosition ) );
315 mapGridElem.setAttribute( u
"leftAnnotationDirection"_s,
static_cast< int >( mLeftGridAnnotationDirection ) );
316 mapGridElem.setAttribute( u
"rightAnnotationDirection"_s,
static_cast< int >( mRightGridAnnotationDirection ) );
317 mapGridElem.setAttribute( u
"topAnnotationDirection"_s,
static_cast< int >( mTopGridAnnotationDirection ) );
318 mapGridElem.setAttribute( u
"bottomAnnotationDirection"_s,
static_cast< int >( mBottomGridAnnotationDirection ) );
319 mapGridElem.setAttribute( u
"frameAnnotationDistance"_s, QString::number( mAnnotationFrameDistance ) );
320 mapGridElem.appendChild( mAnnotationFormat.writeXml( doc, context ) );
321 mapGridElem.setAttribute( u
"annotationPrecision"_s, mGridAnnotationPrecision );
322 mapGridElem.setAttribute( u
"unit"_s,
static_cast< int >( mGridUnit ) );
323 mapGridElem.setAttribute( u
"blendMode"_s, mBlendMode );
324 mapGridElem.setAttribute( u
"minimumIntervalWidth"_s, QString::number( mMinimumIntervalWidth ) );
325 mapGridElem.setAttribute( u
"maximumIntervalWidth"_s, QString::number( mMaximumIntervalWidth ) );
333 elem.appendChild( mapGridElem );
340 if ( itemElem.isNull() )
348 mGridStyle =
static_cast< Qgis::MapGridStyle >( itemElem.attribute( u
"gridStyle"_s, u
"0"_s ).toInt() );
349 mGridIntervalX = itemElem.attribute( u
"intervalX"_s, u
"0"_s ).toDouble();
350 mGridIntervalY = itemElem.attribute( u
"intervalY"_s, u
"0"_s ).toDouble();
351 mGridOffsetX = itemElem.attribute( u
"offsetX"_s, u
"0"_s ).toDouble();
352 mGridOffsetY = itemElem.attribute( u
"offsetY"_s, u
"0"_s ).toDouble();
353 mCrossLength = itemElem.attribute( u
"crossLength"_s, u
"3"_s ).toDouble();
354 mGridFrameStyle =
static_cast< Qgis::MapGridFrameStyle >( itemElem.attribute( u
"gridFrameStyle"_s, u
"0"_s ).toInt() );
356 mGridFrameWidth = itemElem.attribute( u
"gridFrameWidth"_s, u
"2.0"_s ).toDouble();
357 mGridFrameMargin = itemElem.attribute( u
"gridFrameMargin"_s, u
"0.0"_s ).toDouble();
358 mGridFramePenThickness = itemElem.attribute( u
"gridFramePenThickness"_s, u
"0.3"_s ).toDouble();
366 mRotatedTicksLengthMode =
static_cast< Qgis::MapGridTickLengthMode >( itemElem.attribute( u
"rotatedTicksLengthMode"_s, u
"0"_s ).toInt() );
367 mRotatedTicksEnabled = itemElem.attribute( u
"rotatedTicksEnabled"_s, u
"0"_s ) !=
"0"_L1;
368 mRotatedTicksMinimumAngle = itemElem.attribute( u
"rotatedTicksMinimumAngle"_s, u
"0"_s ).toDouble();
369 mRotatedTicksMarginToCorner = itemElem.attribute( u
"rotatedTicksMarginToCorner"_s, u
"0"_s ).toDouble();
370 mRotatedAnnotationsLengthMode =
static_cast< Qgis::MapGridTickLengthMode >( itemElem.attribute( u
"rotatedAnnotationsLengthMode"_s, u
"0"_s ).toInt() );
371 mRotatedAnnotationsEnabled = itemElem.attribute( u
"rotatedAnnotationsEnabled"_s, u
"0"_s ) !=
"0"_L1;
372 mRotatedAnnotationsMinimumAngle = itemElem.attribute( u
"rotatedAnnotationsMinimumAngle"_s, u
"0"_s ).toDouble();
373 mRotatedAnnotationsMarginToCorner = itemElem.attribute( u
"rotatedAnnotationsMarginToCorner"_s, u
"0"_s ).toDouble();
375 const QDomElement lineStyleElem = itemElem.firstChildElement( u
"lineStyle"_s );
376 if ( !lineStyleElem.isNull() )
378 const QDomElement symbolElem = lineStyleElem.firstChildElement( u
"symbol"_s );
379 if ( !symbolElem.isNull() )
388 mGridLineSymbol->setWidth( itemElem.attribute( u
"penWidth"_s, u
"0"_s ).toDouble() );
389 mGridLineSymbol->setColor(
390 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() )
394 const QDomElement markerStyleElem = itemElem.firstChildElement( u
"markerStyle"_s );
395 if ( !markerStyleElem.isNull() )
397 const QDomElement symbolElem = markerStyleElem.firstChildElement( u
"symbol"_s );
398 if ( !symbolElem.isNull() )
404 if ( !mCRS.readXml( itemElem ) )
407 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( u
"blendMode"_s, u
"0"_s ).toUInt() );
410 mShowGridAnnotation = ( itemElem.attribute( u
"showAnnotation"_s, u
"0"_s ) !=
"0"_L1 );
412 mGridAnnotationExpressionString = itemElem.attribute( u
"annotationExpression"_s );
413 mGridAnnotationExpression.reset();
427 mAnnotationFrameDistance = itemElem.attribute( u
"frameAnnotationDistance"_s, u
"0"_s ).toDouble();
429 if ( !itemElem.firstChildElement(
"text-style" ).isNull() )
431 mAnnotationFormat.readXml( itemElem, context );
438 font.fromString( itemElem.attribute(
"annotationFont", QString() ) );
440 mAnnotationFormat.setFont( font );
441 mAnnotationFormat.setSize( font.pointSizeF() );
446 mGridAnnotationPrecision = itemElem.attribute( u
"annotationPrecision"_s, u
"3"_s ).toInt();
447 const int gridUnitInt = itemElem.attribute( u
"unit"_s, QString::number(
static_cast< int >(
Qgis::MapGridUnit::MapUnits ) ) ).toInt();
449 mMinimumIntervalWidth = itemElem.attribute( u
"minimumIntervalWidth"_s, u
"50"_s ).toDouble();
450 mMaximumIntervalWidth = itemElem.attribute( u
"maximumIntervalWidth"_s, u
"100"_s ).toDouble();
454 refreshDataDefinedProperties();
464 mTransformDirty =
true;
470 return mBlendMode != QPainter::CompositionMode_SourceOver;
473QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
475 const QTransform t = QTransform::fromScale( scale, scale );
476 return t.map( polygon );
479void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
481 if ( !
mMap || !mEvaluatedEnabled )
487 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
488 if ( mapPolygon != mPrevMapPolygon )
490 mTransformDirty =
true;
491 mPrevMapPolygon = mapPolygon;
494 if ( mTransformDirty )
496 calculateCrsTransformLines();
500 if ( !calculateLinesOnly )
502 int countLongitudeLines = 0;
503 int countLatitudeLines = 0;
504 for (
const GridLine &line : mGridLines )
506 switch ( line.coordinateType )
509 countLongitudeLines++;
512 countLatitudeLines++;
517 int latitudeLineIndex = 0;
518 int longitudeLineIndex = 0;
521 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
523 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
525 switch ( gridIt->coordinateType )
528 longitudeLineIndex++;
542 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
545 if ( drawnCount >= MAX_GRID_LINES )
551 const double maxX =
mMap->rect().width();
552 const double maxY =
mMap->rect().height();
554 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
556 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
558 const double x = intersectionIt->x();
559 const double y = intersectionIt->y();
563 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
564 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
565 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
566 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
567 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
568 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
571 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
572 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
576 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
580 if ( drawnCount >= MAX_GRID_LINES )
587void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
589 QgsRectangle crsBoundingRect;
590 QgsCoordinateTransform inverseTr;
591 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
598 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
599 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
606 QList< QgsGeometry > xLines;
607 QList< QgsGeometry > yLines;
608 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
609 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
612 for (
int i = 0; i < gridIt->line.size(); ++i )
614 line.append( QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
623 mTransformedIntersections.clear();
624 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
625 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
627 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
628 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
631 const QgsGeometry intersects = ( *yLineIt ).intersection( ( *xLineIt ) );
632 if ( intersects.
isNull() )
637 QgsPointXY vertex = intersects.
vertexAt( i );
640 mTransformedIntersections << vertex;
648 mTransformDirty =
false;
653 if ( !
mMap || !mEvaluatedEnabled )
657 QPaintDevice *paintDevice = p->device();
664 p->setCompositionMode( mBlendMode );
667 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
668 p->setClipRect( thisPaintRect );
669 if ( thisPaintRect != mPrevPaintRect )
672 mTransformDirty =
true;
673 mPrevPaintRect = thisPaintRect;
677 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
678 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
693 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
695 drawGridCrsTransform( context, dotsPerMM );
702 drawGridNoTransform( context, dotsPerMM );
707 p->setClipping(
false );
711 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
716 updateGridLinesAnnotationsPositions();
723 if ( mShowGridAnnotation )
729void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
731 QList< GridLine >::iterator it = mGridLines.begin();
732 int annotationCount = 0;
733 for ( ; it != mGridLines.end(); ++it )
735 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
736 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
737 it->startAnnotation.position = QVector2D( it->line.first() );
738 it->endAnnotation.position = QVector2D( it->line.last() );
739 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
740 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
742 it->startAnnotation.angle
743 = 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() );
745 it->endAnnotation.angle
746 = 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() );
748 if ( annotationCount >= MAX_GRID_FRAME_OBJECTS )
753void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
757 calculateYGridLines();
758 calculateXGridLines();
760 if ( calculateLinesOnly || mGridLines.empty() )
763 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
764 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
766 int countLongitudeLines = 0;
767 int countLatitudeLines = 0;
768 for (
const GridLine &line : mGridLines )
770 switch ( line.coordinateType )
773 countLongitudeLines++;
776 countLatitudeLines++;
781 int latitudeLineIndex = 0;
782 int longitudeLineIndex = 0;
791 for ( ; vIt != mGridLines.constEnd(); ++vIt )
795 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
797 longitudeLineIndex++;
803 drawGridLine( line, context );
805 if ( drawnCount >= MAX_GRID_LINES )
809 for ( ; hIt != mGridLines.constEnd(); ++hIt )
813 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
821 drawGridLine( line, context );
823 if ( drawnCount >= MAX_GRID_LINES )
830 QPointF intersectionPoint, crossEnd1, crossEnd2;
832 for ( ; vIt != mGridLines.constEnd(); ++vIt )
837 l1 = QLineF( vIt->line.first(), vIt->line.last() );
840 hIt = mGridLines.constBegin();
841 for ( ; hIt != mGridLines.constEnd(); ++hIt )
846 l2 = QLineF( hIt->line.first(), hIt->line.last() );
848 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
858 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
862 drawGridMarker( intersectionPoint * dotsPerMM, context );
867 if ( drawnCount >= MAX_GRID_LINES )
877 hIt = mGridLines.constBegin();
878 for ( ; hIt != mGridLines.constEnd(); ++hIt )
883 l1 = QLineF( hIt->line.first(), hIt->line.last() );
885 vIt = mGridLines.constBegin();
886 for ( ; vIt != mGridLines.constEnd(); ++vIt )
891 l2 = QLineF( vIt->line.first(), vIt->line.last() );
893 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
901 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
905 if ( drawnCount >= MAX_GRID_LINES )
911void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
919 mCurrentComponentDrawCount = 0;
921 switch ( mGridFrameStyle )
925 drawGridFrameZebra( p, extension );
930 drawGridFrameTicks( p, extension );
935 drawGridFrameLine( p, extension );
946void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
949 poly << line.p1() << line.p2();
950 drawGridLine( poly, context );
953void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
955 if ( !
mMap || !
mMap->layout() || !mGridLineSymbol )
960 mGridLineSymbol->startRender( context );
961 mGridLineSymbol->renderPolyline( line,
nullptr, context );
962 mGridLineSymbol->stopRender( context );
965void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
967 if ( !
mMap || !
mMap->layout() || !mGridMarkerSymbol )
972 mGridMarkerSymbol->startRender( context );
973 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
974 mGridMarkerSymbol->stopRender( context );
977void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
997void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
Qgis::MapGridBorderSide border,
double *extension )
const
1004 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1009 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
1013 double currentCoord = 0.0;
1014 bool color1 =
false;
1020 bool drawTLBox =
false;
1021 bool drawTRBox =
false;
1022 bool drawBLBox =
false;
1023 bool drawBRBox =
false;
1025 QMap< double, double > pos = QMap< double, double >();
1026 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1027 for ( ; it != mGridLines.constEnd(); ++it )
1030 for (
int i = 0; i < 2; ++i )
1032 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1035 if ( annot.border != border )
1038 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1042 pos.insert( annot.position.y(), it->coordinate );
1044 pos.insert( annot.position.x(), it->coordinate );
1051 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
1067 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
1071 QPen framePen = QPen( mGridFramePenColor );
1072 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1073 framePen.setJoinStyle( Qt::MiterJoin );
1074 p->setPen( framePen );
1076 QMap< double, double >::const_iterator posIt = pos.constBegin();
1077 for ( ; posIt != pos.constEnd(); ++posIt )
1079 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1082 height = posIt.key() - currentCoord;
1083 width = mEvaluatedGridFrameWidth;
1089 height = mEvaluatedGridFrameWidth;
1090 width = posIt.key() - currentCoord;
1092 y = ( border ==
Qgis::MapGridBorderSide::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
1094 p->drawRect( QRectF( x, y, width, height ) );
1095 currentCoord = posIt.key();
1098 mCurrentComponentDrawCount++;
1099 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1106 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin );
1107 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1109 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1111 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1113 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1115 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1119void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1129 QPen framePen = QPen( mGridFramePenColor );
1130 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1131 framePen.setCapStyle( Qt::FlatCap );
1132 p->setBrush( Qt::NoBrush );
1133 p->setPen( framePen );
1136 QList< GridLine >::iterator it = mGridLines.begin();
1137 for ( ; it != mGridLines.end(); ++it )
1140 for (
int i = 0; i < 2; ++i )
1142 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1144 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1148 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1156 facingLeft = ( annot.angle != 0 );
1157 facingRight = ( annot.angle != 0 );
1161 facingLeft = ( annot.angle > 0 );
1162 facingRight = ( annot.angle < 0 );
1166 facingLeft = ( annot.angle < 0 );
1167 facingRight = ( annot.angle > 0 );
1171 && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1174 && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1177 && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1180 && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1184 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1186 double fA = mEvaluatedGridFrameMargin;
1187 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1191 fA /= QVector2D::dotProduct( vector, normalVector );
1192 fB /= QVector2D::dotProduct( vector, normalVector );
1199 extension->UpdateBorder( annot.border, fB );
1207 pA = annot.position +
static_cast< float >( fA ) * vector;
1208 pB = annot.position +
static_cast< float >( fB ) * vector;
1212 pA = annot.position -
static_cast< float >( fA ) * vector;
1213 pB = annot.position -
static_cast< float >( fB ) * vector;
1217 pA = annot.position -
static_cast< float >( fB ) * vector;
1218 pB = annot.position +
static_cast< float >( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1220 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1222 mCurrentComponentDrawCount++;
1223 if ( mCurrentComponentDrawCount >= MAX_GRID_TICKS )
1228void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1238 QPen framePen = QPen( mGridFramePenColor );
1239 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1240 framePen.setCapStyle( Qt::SquareCap );
1241 p->setBrush( Qt::NoBrush );
1242 p->setPen( framePen );
1252 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1261 QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1270 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1279 QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1283 if ( !extension && drawDiagonals )
1288 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1289 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1290 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1295 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1296 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1297 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1302 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1303 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1304 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1309 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1310 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1311 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1318 if ( mGridLines.empty() )
1321 mCurrentComponentDrawCount = 0;
1323 QString currentAnnotationString;
1324 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1326 QgsExpressionContextScope *gridScope =
new QgsExpressionContextScope();
1327 QgsExpressionContextScopePopper scopePopper( expressionContext, gridScope );
1329 bool geographic =
false;
1330 if ( mCRS.isValid() )
1332 geographic = mCRS.isGeographic();
1336 geographic =
mMap->crs().isGeographic();
1339 const bool forceWrap
1342 int countLongitudeLines = 0;
1343 int countLatitudeLines = 0;
1344 for (
const GridLine &line : mGridLines )
1346 switch ( line.coordinateType )
1349 countLongitudeLines++;
1352 countLatitudeLines++;
1357 int latitudeLineIndex = 0;
1358 int longitudeLineIndex = 0;
1359 for ( ; it != mGridLines.constEnd(); ++it )
1361 double value = it->coordinate;
1362 switch ( it->coordinateType )
1365 longitudeLineIndex++;
1366 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLongitudeLines,
true ) );
1367 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, longitudeLineIndex,
true ) );
1368 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"x"_s,
true ) );
1372 latitudeLineIndex++;
1373 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLatitudeLines,
true ) );
1374 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, latitudeLineIndex,
true ) );
1375 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"y"_s,
true ) );
1382 const double wrappedX = std::fmod( value, 360.0 );
1383 if ( wrappedX > 180.0 )
1385 value = wrappedX - 360.0;
1387 else if ( wrappedX < -180.0 )
1389 value = wrappedX + 360.0;
1393 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_number"_s, value,
true ) );
1395 if ( mDrawAnnotationProperty )
1398 const bool display = mDrawAnnotationProperty->valueAsBool( expressionContext,
true, &ok );
1399 if ( ok && !display )
1402 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext, geographic );
1403 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1404 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1405 mCurrentComponentDrawCount++;
1406 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1411void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
1420 if ( !shouldShowAnnotationForSide( coordinateType, annot.border ) )
1424 std::unique_ptr< QgsScopedQPainterState > painterState;
1425 double dotsPerMM = 1;
1429 painterState = std::make_unique< QgsScopedQPainterState >( context.
painter() );
1430 dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
1431 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1442 double textWidthPainterUnits = sizePainterUnits.width();
1444 textWidthPainterUnits *= 1.1;
1446 const double textWidthMM = textWidthPainterUnits * painterUnitsToMM;
1448 double textHeightPainterUnits = 0;
1449 if ( extension || doc.
size() > 1 )
1451 textHeightPainterUnits = sizePainterUnits.height();
1460 const double textHeightMM = textHeightPainterUnits * painterUnitsToMM;
1466 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1470 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1473 double distanceToFrameMM = mEvaluatedAnnotationFrameDistance;
1478 const bool hasExteriorMargin
1481 const bool hasBorderWidth
1484 distanceToFrameMM += mEvaluatedGridFrameWidth;
1485 if ( hasBorderWidth )
1486 distanceToFrameMM += mEvaluatedGridFrameLineThickness / 2.0;
1489 distanceToFrameMM *= -1;
1493 distanceToFrameMM /= QVector2D::dotProduct( vector, normalVector );
1496 QPointF annotationPositionMM = ( annot.position +
static_cast< float >( distanceToFrameMM ) * vector ).toPointF();
1501 double rotation = 0;
1505 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1507 if ( rotation <= -90 || rotation > 90 )
1510 anchorMM.setX( outside ? 0 : textWidthMM );
1514 anchorMM.setX( outside ? textWidthMM : 0 );
1518 anchorMM.setY( 0.5 * textHeightMM );
1520 anchorMM.setY( -1.5 * textHeightMM );
1522 anchorMM.setY( -0.5 * textHeightMM );
1527 anchorMM.setX( 0.5 * textWidthMM );
1528 anchorMM.setY( -0.5 * textHeightMM );
1530 anchorMM.setY( outside ? 0 : -textHeightMM );
1532 anchorMM.setX( outside ? 0 : textWidthMM );
1534 anchorMM.setY( outside ? -textHeightMM : 0 );
1536 anchorMM.setX( outside ? textWidthMM : 0 );
1541 anchorMM.setX( 0.5 * textWidthMM );
1542 anchorMM.setY( -0.5 * textHeightMM );
1544 anchorMM.setX( outside ? 0 : textWidthMM );
1546 anchorMM.setY( outside ? -textHeightMM : 0 );
1548 anchorMM.setX( outside ? textWidthMM : 0 );
1550 anchorMM.setY( outside ? 0 : -textHeightMM );
1555 anchorMM.setX( 0.5 * textWidthMM );
1556 anchorMM.setY( -0.5 * textHeightMM );
1558 anchorMM.setX( outside ? textWidthMM : 0 );
1560 anchorMM.setY( outside ? 0 : -textHeightMM );
1562 anchorMM.setX( outside ? 0 : textWidthMM );
1564 anchorMM.setY( outside ? -textHeightMM : 0 );
1569 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1570 anchorMM.setX( 0.5 * textWidthMM );
1572 anchorMM.setY( -textHeightMM );
1580 extension->UpdateBorder( frameBorder, -distanceToFrameMM + std::max( textHeightMM, textWidthMM ) );
1582 extension->UpdateAll( std::max( textHeightMM, textWidthMM ) / 2.0 );
1585 if ( extension || !context.
painter() )
1589 bool facingLeft = ( annot.angle < 0 );
1590 bool facingRight = ( annot.angle > 0 );
1593 facingLeft = !facingLeft;
1594 facingRight = !facingRight;
1596 const QRectF mapRect =
mMap->rect();
1598 && ( ( facingLeft && !
qgsDoubleGreaterThanOrNear( annot.position.x(),mRotatedAnnotationsMarginToCorner,ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM) )
1599 || ( facingRight && !
qgsDoubleLessThanOrNear( annot.position.x(), mapRect.width() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1602 && ( ( facingLeft && !
qgsDoubleLessThanOrNear( annot.position.x(), mapRect.width() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1603 || ( facingRight && !
qgsDoubleGreaterThanOrNear( annot.position.x(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1606 && ( ( facingLeft && !
qgsDoubleLessThanOrNear( annot.position.y(), mapRect.height() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1607 || ( facingRight && !
qgsDoubleGreaterThanOrNear( annot.position.y(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1610 && ( ( facingLeft && !
qgsDoubleGreaterThanOrNear( annot.position.y(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1611 || ( facingRight && !
qgsDoubleLessThanOrNear( annot.position.y(), mapRect.height() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1618 QPointF textPos( 0, 0 );
1619 switch ( annot.border )
1636 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1639 textPos.setX( textWidthMM / painterUnitsToMM );
1645 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1667 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1670 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1674 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1689 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1714 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1717 textPos.setX( textWidthMM / painterUnitsToMM );
1729 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1750 context.
painter()->translate( QPointF( annotationPositionMM.x(), annotationPositionMM.y() ) / painterUnitsToMM );
1751 context.
painter()->rotate( rotation );
1752 context.
painter()->translate( -anchorMM / painterUnitsToMM );
1763 return QString::number( value,
'f', mGridAnnotationPrecision );
1769 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1773 if ( !isGeographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1775 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1781 if ( !isGeographic || coordRounded != 0.0 )
1783 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1789 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1793 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1798 if ( !mGridAnnotationExpression )
1800 mGridAnnotationExpression = std::make_unique<QgsExpression>( mGridAnnotationExpressionString );
1801 mGridAnnotationExpression->prepare( &expressionContext );
1803 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1808 switch ( mGridAnnotationFormat )
1858void QgsLayoutItemMapGrid::calculateXGridLines()
const
1860 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1865 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1866 QRectF mapBoundingRect = mapPolygon.boundingRect();
1867 double gridIntervalY = mEvaluatedIntervalY;
1868 double gridOffsetY = mEvaluatedOffsetY;
1869 double annotationScale = 1.0;
1870 switch ( mGridUnit )
1875 mapBoundingRect =
mMap->rect();
1876 mapPolygon = QPolygonF(
mMap->rect() );
1879 annotationScale = 0.1;
1880 gridIntervalY *= 10;
1891 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY ) * gridIntervalY + gridOffsetY;
1893 currentLevel += gridIntervalY;
1895 int gridLineCount = 0;
1900 double yCanvasCoord;
1901 while (
qgsDoubleLessThanOrNear( currentLevel, mapBoundingRect.bottom(), GRID_LINE_CLOSE_TO_EDGE_TOLERANCE_MAP_UNITS ) && gridLineCount < MAX_GRID_OBJECTS )
1903 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1905 newLine.coordinate = currentLevel * annotationScale;
1907 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1908 mGridLines.append( newLine );
1909 currentLevel += gridIntervalY;
1916 QVector<QLineF> borderLines;
1917 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1918 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1919 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1920 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1922 QVector<QPointF> intersectionList;
1924 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount < MAX_GRID_OBJECTS )
1926 intersectionList.clear();
1927 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1929 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1930 for ( ; it != borderLines.constEnd(); ++it )
1932 QPointF intersectionPoint;
1933 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1935 intersectionList.push_back( intersectionPoint );
1936 if ( intersectionList.size() >= 2 )
1943 if ( intersectionList.size() >= 2 )
1946 newLine.coordinate = currentLevel;
1948 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1949 mGridLines.append( newLine );
1952 currentLevel += gridIntervalY;
1956void QgsLayoutItemMapGrid::calculateYGridLines()
const
1958 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1963 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1964 QRectF mapBoundingRect = mapPolygon.boundingRect();
1965 double gridIntervalX = mEvaluatedIntervalX;
1966 double gridOffsetX = mEvaluatedOffsetX;
1967 double annotationScale = 1.0;
1968 switch ( mGridUnit )
1973 mapBoundingRect =
mMap->rect();
1974 mapPolygon = QPolygonF(
mMap->rect() );
1977 annotationScale = 0.1;
1978 gridIntervalX *= 10;
1989 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX ) * gridIntervalX + gridOffsetX;
1991 currentLevel += gridIntervalX;
1993 int gridLineCount = 0;
1997 double xCanvasCoord;
1998 while (
qgsDoubleLessThanOrNear( currentLevel, mapBoundingRect.right(), GRID_LINE_CLOSE_TO_EDGE_TOLERANCE_MAP_UNITS ) && gridLineCount < MAX_GRID_OBJECTS )
2000 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
2003 newLine.coordinate = currentLevel * annotationScale;
2005 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
2006 mGridLines.append( newLine );
2007 currentLevel += gridIntervalX;
2014 QVector<QLineF> borderLines;
2015 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
2016 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
2017 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
2018 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
2020 QVector<QPointF> intersectionList;
2022 while ( currentLevel <= mapBoundingRect.right() && gridLineCount < MAX_GRID_OBJECTS )
2024 intersectionList.clear();
2025 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
2027 QVector<QLineF>::const_iterator it = borderLines.constBegin();
2028 for ( ; it != borderLines.constEnd(); ++it )
2030 QPointF intersectionPoint;
2031 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
2033 intersectionList.push_back( intersectionPoint );
2034 if ( intersectionList.size() >= 2 )
2041 if ( intersectionList.size() >= 2 )
2044 newLine.coordinate = currentLevel;
2046 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
2047 mGridLines.append( newLine );
2050 currentLevel += gridIntervalX;
2056 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
2061 const double roundCorrection = bbox.
yMaximum() > mEvaluatedOffsetY ? 1.0 : 0.0;
2062 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
2064 const double minX = bbox.
xMinimum();
2065 const double maxX = bbox.
xMaximum();
2066 double step = ( maxX - minX ) / 20;
2068 bool crosses180 =
false;
2069 bool crossed180 =
false;
2070 if ( mCRS.isGeographic() && ( minX > maxX ) )
2074 step = ( maxX + 360.0 - minX ) / 20;
2080 int gridLineCount = 0;
2081 while ( currentLevel >= bbox.
yMinimum() && gridLineCount < MAX_GRID_OBJECTS )
2084 double currentX = minX;
2088 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
2095 const QgsPointXY mapPoint = t.
transform( currentX, currentLevel );
2096 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2098 catch ( QgsCsException &cse )
2105 if ( crosses180 && currentX > 180.0 )
2113 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2114 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2115 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2117 if ( !( *lineIt ).isEmpty() )
2120 newLine.coordinate = currentLevel;
2122 newLine.line = QPolygonF( *lineIt );
2123 mGridLines.append( newLine );
2127 currentLevel -= mEvaluatedIntervalY;
2135 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
2140 const double roundCorrection = bbox.
xMinimum() > mEvaluatedOffsetX ? 1.0 : 0.0;
2141 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
2143 const double minY = bbox.
yMinimum();
2144 const double maxY = bbox.
yMaximum();
2145 const double step = ( maxY - minY ) / 20;
2150 bool crosses180 =
false;
2151 bool crossed180 =
false;
2158 int gridLineCount = 0;
2159 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount < MAX_GRID_OBJECTS )
2162 double currentY = minY;
2166 if ( currentY > maxY )
2173 const QgsPointXY mapPoint = t.
transform( currentLevel, currentY );
2175 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2177 catch ( QgsCsException &cse )
2186 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2187 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2188 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2190 if ( !( *lineIt ).isEmpty() )
2193 newLine.coordinate = currentLevel;
2195 newLine.line = QPolygonF( *lineIt );
2196 mGridLines.append( newLine );
2200 currentLevel += mEvaluatedIntervalX;
2201 if ( crosses180 && currentLevel > 180.0 )
2203 currentLevel -= 360.0;
2232 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
2234 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
2236 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
2238 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
2252 if ( ddValue.compare(
"x_only"_L1, Qt::CaseInsensitive ) == 0 )
2254 else if ( ddValue.compare(
"y_only"_L1, Qt::CaseInsensitive ) == 0 )
2256 else if ( ddValue.compare(
"disabled"_L1, Qt::CaseInsensitive ) == 0 )
2258 else if ( ddValue.compare(
"all"_L1, Qt::CaseInsensitive ) == 0 )
2264void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
2269 mTransformDirty = mTransformDirty
2280 mDrawAnnotationProperty->prepare( context );
2284 mDrawAnnotationProperty.reset();
2287 switch ( mGridUnit )
2300 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
2302 mEvaluatedEnabled =
false;
2307 const double mapWidthMapUnits = mapWidth();
2308 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2309 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2311 mEvaluatedIntervalX = interval;
2312 mEvaluatedIntervalY = interval;
2313 mTransformDirty =
true;
2325 mEvaluatedLeftGridAnnotationDisplay
2327 mEvaluatedRightGridAnnotationDisplay
2329 mEvaluatedTopGridAnnotationDisplay
2331 mEvaluatedBottomGridAnnotationDisplay
2336 mEvaluatedBottomFrameDivisions
2340double QgsLayoutItemMapGrid::mapWidth()
const
2347 const QgsRectangle mapExtent =
mMap->extent();
2351 return mapExtent.
width();
2367 catch ( QgsCsException & )
2370 QgsDebugError( u
"An error occurred while calculating length"_s );
2376bool sortByDistance( QPair<qreal, Qgis::MapGridBorderSide> a, QPair<qreal, Qgis::MapGridBorderSide> b )
2378 return a.first < b.first;
2388 const double tolerance = std::max(
mMap->frameEnabled() ?
mMap->pen().widthF() : 0.0, 1.0 );
2392 ( p.y() <= tolerance && p.x() <= tolerance )
2393 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2394 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2395 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2401 if ( p.x() <= tolerance )
2412 if ( p.y() <= tolerance )
2424 QList< QPair<qreal, Qgis::MapGridBorderSide > > distanceToSide;
2430 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2431 return distanceToSide.at( 0 ).second;
2436 mGridLineSymbol.reset( symbol );
2441 return mGridLineSymbol.get();
2446 return mGridLineSymbol.get();
2451 mGridMarkerSymbol.reset( symbol );
2456 return mGridMarkerSymbol.get();
2461 return mGridMarkerSymbol.get();
2466 mAnnotationFormat.setFont( font );
2467 if ( font.pointSizeF() > 0 )
2469 mAnnotationFormat.setSize( font.pointSizeF() );
2472 else if ( font.pixelSize() > 0 )
2474 mAnnotationFormat.setSize( font.pixelSize() );
2481 return mAnnotationFormat.toQFont();
2486 mAnnotationFormat.
setColor( color );
2491 return mAnnotationFormat.color();
2499 mLeftGridAnnotationDisplay = display;
2502 mRightGridAnnotationDisplay = display;
2505 mTopGridAnnotationDisplay = display;
2508 mBottomGridAnnotationDisplay = display;
2512 refreshDataDefinedProperties();
2516 mMap->updateBoundingRect();
2526 return mLeftGridAnnotationDisplay;
2528 return mRightGridAnnotationDisplay;
2530 return mTopGridAnnotationDisplay;
2532 return mBottomGridAnnotationDisplay;
2534 return mBottomGridAnnotationDisplay;
2541 double bottom = 0.0;
2544 return std::max( std::max( std::max( top, right ), bottom ), left );
2554 if ( !
mMap || !mEvaluatedEnabled )
2564 GridExtension extension;
2567 switch ( mGridUnit )
2572 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
2574 drawGridCrsTransform( context, 0,
true );
2581 drawGridNoTransform( context, 0,
true );
2586 updateGridLinesAnnotationsPositions();
2590 drawGridFrame(
nullptr, &extension );
2593 if ( mShowGridAnnotation )
2598 top = extension.top;
2599 right = extension.right;
2600 bottom = extension.bottom;
2601 left = extension.left;
2607 refreshDataDefinedProperties();
2612 if ( unit == mGridUnit )
2617 mTransformDirty =
true;
2626 mGridIntervalX = interval;
2627 mTransformDirty =
true;
2628 refreshDataDefinedProperties();
2637 mGridIntervalY = interval;
2638 mTransformDirty =
true;
2639 refreshDataDefinedProperties();
2648 mGridOffsetX = offset;
2649 mTransformDirty =
true;
2650 refreshDataDefinedProperties();
2659 mGridOffsetY = offset;
2660 mTransformDirty =
true;
2661 refreshDataDefinedProperties();
2670 mMinimumIntervalWidth = minWidth;
2671 mTransformDirty =
true;
2672 refreshDataDefinedProperties();
2681 mMaximumIntervalWidth = maxWidth;
2682 mTransformDirty =
true;
2683 refreshDataDefinedProperties();
2688 if (
style == mGridStyle )
2693 mTransformDirty =
true;
2698 mCrossLength = length;
2699 refreshDataDefinedProperties();
2707 mLeftGridAnnotationDirection = direction;
2710 mRightGridAnnotationDirection = direction;
2713 mTopGridAnnotationDirection = direction;
2716 mBottomGridAnnotationDirection = direction;
2722 mMap->updateBoundingRect();
2729 mGridFrameSides = flags;
2734 mGridFrameSides.setFlag( flag, on );
2739 return mGridFrameSides;
2754 if ( mGridLineSymbol )
2760 if ( mGridMarkerSymbol )
2772 mTransformDirty =
true;
2773 refreshDataDefinedProperties();
2774 mMap->updateBoundingRect();
2780 return mGridFrameSides.testFlag( flag );
2785 mGridFrameWidth = width;
2786 refreshDataDefinedProperties();
2791 mGridFrameMargin = margin;
2792 refreshDataDefinedProperties();
2797 mGridFramePenThickness = width;
2798 refreshDataDefinedProperties();
2808 mHAlign = alignment;
2813 mLeftGridAnnotationDirection = direction;
2814 mRightGridAnnotationDirection = direction;
2815 mTopGridAnnotationDirection = direction;
2816 mBottomGridAnnotationDirection = direction;
2824 mLeftGridAnnotationPosition = position;
2827 mRightGridAnnotationPosition = position;
2830 mTopGridAnnotationPosition = position;
2833 mBottomGridAnnotationPosition = position;
2839 mMap->updateBoundingRect();
2849 return mLeftGridAnnotationPosition;
2851 return mRightGridAnnotationPosition;
2853 return mTopGridAnnotationPosition;
2855 return mBottomGridAnnotationPosition;
2857 return mLeftGridAnnotationPosition;
2862 mAnnotationFrameDistance = distance;
2863 refreshDataDefinedProperties();
2870 return mLeftGridAnnotationDirection;
2876 return mLeftGridAnnotationDirection;
2878 return mRightGridAnnotationDirection;
2880 return mTopGridAnnotationDirection;
2882 return mBottomGridAnnotationDirection;
2884 return mLeftGridAnnotationDirection;
2889 mGridAnnotationExpressionString = expression;
2890 mGridAnnotationExpression.reset();
2898 mLeftFrameDivisions = divisions;
2901 mRightFrameDivisions = divisions;
2904 mTopFrameDivisions = divisions;
2907 mBottomFrameDivisions = divisions;
2911 refreshDataDefinedProperties();
2924 return mLeftFrameDivisions;
2926 return mRightFrameDivisions;
2928 return mTopFrameDivisions;
2930 return mBottomFrameDivisions;
2932 return mLeftFrameDivisions;
2944 const QgsCoordinateTransform tr(
mMap->crs(), mCRS,
mLayout->project() );
2945 QgsCoordinateTransform extentTransform = tr;
2947 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
2948 const QRectF mbr = mapPolygon.boundingRect();
2949 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2952 if ( mCRS.isGeographic() )
2955 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2956 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2958 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2959 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2961 if ( lowerLeft.x() > upperRight.x() )
2977 inverseTransform = QgsCoordinateTransform( mCRS,
mMap->crs(),
mLayout->project() );
2979 catch ( QgsCsException &cse )
2988QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2993 const QgsGeometry intersected = lineGeom.
intersection( rectGeom );
2996 QList<QPolygonF> trimmedLines;
2997 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2998 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
3000 trimmedLines << ( *geomIt ).asQPolygonF();
3002 return trimmedLines;
3077 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.
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.