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();
522 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
524 switch ( gridIt->coordinateType )
527 longitudeLineIndex++;
541 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
546 const double maxX =
mMap->rect().width();
547 const double maxY =
mMap->rect().height();
549 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
550 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
552 const double x = intersectionIt->x();
553 const double y = intersectionIt->y();
557 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
558 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
559 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
560 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
561 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
562 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
565 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
566 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
570 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
577void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
579 QgsRectangle crsBoundingRect;
580 QgsCoordinateTransform inverseTr;
581 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
588 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
589 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
596 QList< QgsGeometry > xLines;
597 QList< QgsGeometry > yLines;
598 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
599 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
602 for (
int i = 0; i < gridIt->line.size(); ++i )
604 line.append( QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
613 mTransformedIntersections.clear();
614 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
615 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
617 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
618 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
621 const QgsGeometry intersects = ( *yLineIt ).intersection( ( *xLineIt ) );
622 if ( intersects.
isNull() )
627 QgsPointXY vertex = intersects.
vertexAt( i );
630 mTransformedIntersections << vertex;
638 mTransformDirty =
false;
643 if ( !
mMap || !mEvaluatedEnabled )
647 QPaintDevice *paintDevice = p->device();
654 p->setCompositionMode( mBlendMode );
657 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
658 p->setClipRect( thisPaintRect );
659 if ( thisPaintRect != mPrevPaintRect )
662 mTransformDirty =
true;
663 mPrevPaintRect = thisPaintRect;
667 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
668 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
683 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
685 drawGridCrsTransform( context, dotsPerMM );
692 drawGridNoTransform( context, dotsPerMM );
697 p->setClipping(
false );
701 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
706 updateGridLinesAnnotationsPositions();
713 if ( mShowGridAnnotation )
719void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
721 QList< GridLine >::iterator it = mGridLines.begin();
722 for ( ; it != mGridLines.end(); ++it )
724 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
725 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
726 it->startAnnotation.position = QVector2D( it->line.first() );
727 it->endAnnotation.position = QVector2D( it->line.last() );
728 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
729 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
731 it->startAnnotation.angle
732 = 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() );
734 it->endAnnotation.angle
735 = 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() );
739void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
746 if ( calculateLinesOnly || mGridLines.empty() )
749 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
750 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
752 int countLongitudeLines = 0;
753 int countLatitudeLines = 0;
754 for (
const GridLine &line : mGridLines )
756 switch ( line.coordinateType )
759 countLongitudeLines++;
762 countLatitudeLines++;
767 int latitudeLineIndex = 0;
768 int longitudeLineIndex = 0;
776 for ( ; vIt != mGridLines.constEnd(); ++vIt )
780 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
782 longitudeLineIndex++;
788 drawGridLine( line, context );
791 for ( ; hIt != mGridLines.constEnd(); ++hIt )
795 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
803 drawGridLine( line, context );
809 QPointF intersectionPoint, crossEnd1, crossEnd2;
810 for ( ; vIt != mGridLines.constEnd(); ++vIt )
815 l1 = QLineF( vIt->line.first(), vIt->line.last() );
818 hIt = mGridLines.constBegin();
819 for ( ; hIt != mGridLines.constEnd(); ++hIt )
824 l2 = QLineF( hIt->line.first(), hIt->line.last() );
826 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
836 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
840 drawGridMarker( intersectionPoint * dotsPerMM, context );
852 hIt = mGridLines.constBegin();
853 for ( ; hIt != mGridLines.constEnd(); ++hIt )
858 l1 = QLineF( hIt->line.first(), hIt->line.last() );
860 vIt = mGridLines.constBegin();
861 for ( ; vIt != mGridLines.constEnd(); ++vIt )
866 l2 = QLineF( vIt->line.first(), vIt->line.last() );
868 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
876 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
883void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
892 switch ( mGridFrameStyle )
896 drawGridFrameZebra( p, extension );
901 drawGridFrameTicks( p, extension );
906 drawGridFrameLine( p, extension );
917void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
920 poly << line.p1() << line.p2();
921 drawGridLine( poly, context );
924void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
926 if ( !
mMap || !
mMap->layout() || !mGridLineSymbol )
931 mGridLineSymbol->startRender( context );
932 mGridLineSymbol->renderPolyline( line,
nullptr, context );
933 mGridLineSymbol->stopRender( context );
936void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
938 if ( !
mMap || !
mMap->layout() || !mGridMarkerSymbol )
943 mGridMarkerSymbol->startRender( context );
944 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
945 mGridMarkerSymbol->stopRender( context );
948void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
968void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
Qgis::MapGridBorderSide border,
double *extension )
const
977 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
981 double currentCoord = 0.0;
988 bool drawTLBox =
false;
989 bool drawTRBox =
false;
990 bool drawBLBox =
false;
991 bool drawBRBox =
false;
993 QMap< double, double > pos = QMap< double, double >();
994 QList< GridLine >::const_iterator it = mGridLines.constBegin();
995 for ( ; it != mGridLines.constEnd(); ++it )
998 for (
int i = 0; i < 2; ++i )
1000 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1003 if ( annot.border != border )
1006 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1010 pos.insert( annot.position.y(), it->coordinate );
1012 pos.insert( annot.position.x(), it->coordinate );
1019 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
1035 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
1039 QPen framePen = QPen( mGridFramePenColor );
1040 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1041 framePen.setJoinStyle( Qt::MiterJoin );
1042 p->setPen( framePen );
1044 QMap< double, double >::const_iterator posIt = pos.constBegin();
1045 for ( ; posIt != pos.constEnd(); ++posIt )
1047 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1050 height = posIt.key() - currentCoord;
1051 width = mEvaluatedGridFrameWidth;
1057 height = mEvaluatedGridFrameWidth;
1058 width = posIt.key() - currentCoord;
1060 y = ( border ==
Qgis::MapGridBorderSide::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
1062 p->drawRect( QRectF( x, y, width, height ) );
1063 currentCoord = posIt.key();
1070 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin );
1071 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1073 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1075 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1077 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1079 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1083void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1093 QPen framePen = QPen( mGridFramePenColor );
1094 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1095 framePen.setCapStyle( Qt::FlatCap );
1096 p->setBrush( Qt::NoBrush );
1097 p->setPen( framePen );
1100 QList< GridLine >::iterator it = mGridLines.begin();
1101 for ( ; it != mGridLines.end(); ++it )
1104 for (
int i = 0; i < 2; ++i )
1106 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1108 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1112 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1120 facingLeft = ( annot.angle != 0 );
1121 facingRight = ( annot.angle != 0 );
1125 facingLeft = ( annot.angle > 0 );
1126 facingRight = ( annot.angle < 0 );
1130 facingLeft = ( annot.angle < 0 );
1131 facingRight = ( annot.angle > 0 );
1135 && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1138 && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1141 && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1144 && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1148 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1150 double fA = mEvaluatedGridFrameMargin;
1151 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1155 fA /= QVector2D::dotProduct( vector, normalVector );
1156 fB /= QVector2D::dotProduct( vector, normalVector );
1163 extension->UpdateBorder( annot.border, fB );
1171 pA = annot.position +
static_cast< float >( fA ) * vector;
1172 pB = annot.position +
static_cast< float >( fB ) * vector;
1176 pA = annot.position -
static_cast< float >( fA ) * vector;
1177 pB = annot.position -
static_cast< float >( fB ) * vector;
1181 pA = annot.position -
static_cast< float >( fB ) * vector;
1182 pB = annot.position +
static_cast< float >( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1184 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1189void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1199 QPen framePen = QPen( mGridFramePenColor );
1200 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1201 framePen.setCapStyle( Qt::SquareCap );
1202 p->setBrush( Qt::NoBrush );
1203 p->setPen( framePen );
1213 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1222 QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1231 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1240 QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1244 if ( !extension && drawDiagonals )
1249 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1250 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1251 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1256 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1257 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1258 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1263 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1264 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1265 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1270 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1271 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1272 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1279 if ( mGridLines.empty() )
1282 QString currentAnnotationString;
1283 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1285 QgsExpressionContextScope *gridScope =
new QgsExpressionContextScope();
1286 QgsExpressionContextScopePopper scopePopper( expressionContext, gridScope );
1288 bool geographic =
false;
1289 if ( mCRS.isValid() )
1291 geographic = mCRS.isGeographic();
1295 geographic =
mMap->crs().isGeographic();
1298 const bool forceWrap
1301 int countLongitudeLines = 0;
1302 int countLatitudeLines = 0;
1303 for (
const GridLine &line : mGridLines )
1305 switch ( line.coordinateType )
1308 countLongitudeLines++;
1311 countLatitudeLines++;
1316 int latitudeLineIndex = 0;
1317 int longitudeLineIndex = 0;
1318 for ( ; it != mGridLines.constEnd(); ++it )
1320 double value = it->coordinate;
1321 switch ( it->coordinateType )
1324 longitudeLineIndex++;
1325 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLongitudeLines,
true ) );
1326 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, longitudeLineIndex,
true ) );
1327 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"x"_s,
true ) );
1331 latitudeLineIndex++;
1332 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLatitudeLines,
true ) );
1333 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, latitudeLineIndex,
true ) );
1334 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"y"_s,
true ) );
1341 const double wrappedX = std::fmod( value, 360.0 );
1342 if ( wrappedX > 180.0 )
1344 value = wrappedX - 360.0;
1346 else if ( wrappedX < -180.0 )
1348 value = wrappedX + 360.0;
1352 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_number"_s, value,
true ) );
1354 if ( mDrawAnnotationProperty )
1357 const bool display = mDrawAnnotationProperty->valueAsBool( expressionContext,
true, &ok );
1358 if ( ok && !display )
1361 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext, geographic );
1362 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1363 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1367void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
1376 if ( !shouldShowAnnotationForSide( coordinateType, annot.border ) )
1380 std::unique_ptr< QgsScopedQPainterState > painterState;
1381 double dotsPerMM = 1;
1385 painterState = std::make_unique< QgsScopedQPainterState >( context.
painter() );
1386 dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
1387 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1398 double textWidthPainterUnits = sizePainterUnits.width();
1400 textWidthPainterUnits *= 1.1;
1402 const double textWidthMM = textWidthPainterUnits * painterUnitsToMM;
1404 double textHeightPainterUnits = 0;
1405 if ( extension || doc.
size() > 1 )
1407 textHeightPainterUnits = sizePainterUnits.height();
1416 const double textHeightMM = textHeightPainterUnits * painterUnitsToMM;
1422 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1426 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1429 double distanceToFrameMM = mEvaluatedAnnotationFrameDistance;
1434 const bool hasExteriorMargin
1437 const bool hasBorderWidth
1440 distanceToFrameMM += mEvaluatedGridFrameWidth;
1441 if ( hasBorderWidth )
1442 distanceToFrameMM += mEvaluatedGridFrameLineThickness / 2.0;
1445 distanceToFrameMM *= -1;
1449 distanceToFrameMM /= QVector2D::dotProduct( vector, normalVector );
1452 QPointF annotationPositionMM = ( annot.position +
static_cast< float >( distanceToFrameMM ) * vector ).toPointF();
1457 double rotation = 0;
1461 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1463 if ( rotation <= -90 || rotation > 90 )
1466 anchorMM.setX( outside ? 0 : textWidthMM );
1470 anchorMM.setX( outside ? textWidthMM : 0 );
1474 anchorMM.setY( 0.5 * textHeightMM );
1476 anchorMM.setY( -1.5 * textHeightMM );
1478 anchorMM.setY( -0.5 * textHeightMM );
1483 anchorMM.setX( 0.5 * textWidthMM );
1484 anchorMM.setY( -0.5 * textHeightMM );
1486 anchorMM.setY( outside ? 0 : -textHeightMM );
1488 anchorMM.setX( outside ? 0 : textWidthMM );
1490 anchorMM.setY( outside ? -textHeightMM : 0 );
1492 anchorMM.setX( outside ? textWidthMM : 0 );
1497 anchorMM.setX( 0.5 * textWidthMM );
1498 anchorMM.setY( -0.5 * textHeightMM );
1500 anchorMM.setX( outside ? 0 : textWidthMM );
1502 anchorMM.setY( outside ? -textHeightMM : 0 );
1504 anchorMM.setX( outside ? textWidthMM : 0 );
1506 anchorMM.setY( outside ? 0 : -textHeightMM );
1511 anchorMM.setX( 0.5 * textWidthMM );
1512 anchorMM.setY( -0.5 * textHeightMM );
1514 anchorMM.setX( outside ? textWidthMM : 0 );
1516 anchorMM.setY( outside ? 0 : -textHeightMM );
1518 anchorMM.setX( outside ? 0 : textWidthMM );
1520 anchorMM.setY( outside ? -textHeightMM : 0 );
1525 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1526 anchorMM.setX( 0.5 * textWidthMM );
1528 anchorMM.setY( -textHeightMM );
1536 extension->UpdateBorder( frameBorder, -distanceToFrameMM + std::max( textHeightMM, textWidthMM ) );
1538 extension->UpdateAll( std::max( textHeightMM, textWidthMM ) / 2.0 );
1541 if ( extension || !context.
painter() )
1545 bool facingLeft = ( annot.angle < 0 );
1546 bool facingRight = ( annot.angle > 0 );
1549 facingLeft = !facingLeft;
1550 facingRight = !facingRight;
1553 && ( ( facingLeft && annot.position.x() < mRotatedAnnotationsMarginToCorner ) || ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
1556 && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) || ( facingRight && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ) )
1559 && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) || ( facingRight && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ) )
1562 && ( ( facingLeft && annot.position.y() < mRotatedAnnotationsMarginToCorner ) || ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
1569 QPointF textPos( 0, 0 );
1570 switch ( annot.border )
1587 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1590 textPos.setX( textWidthMM / painterUnitsToMM );
1596 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1618 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1621 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1625 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1640 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1665 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1668 textPos.setX( textWidthMM / painterUnitsToMM );
1680 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1701 context.
painter()->translate( QPointF( annotationPositionMM.x(), annotationPositionMM.y() ) / painterUnitsToMM );
1702 context.
painter()->rotate( rotation );
1703 context.
painter()->translate( -anchorMM / painterUnitsToMM );
1714 return QString::number( value,
'f', mGridAnnotationPrecision );
1720 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1724 if ( !isGeographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1726 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1732 if ( !isGeographic || coordRounded != 0.0 )
1734 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1740 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1744 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1749 if ( !mGridAnnotationExpression )
1751 mGridAnnotationExpression = std::make_unique<QgsExpression>( mGridAnnotationExpressionString );
1752 mGridAnnotationExpression->prepare( &expressionContext );
1754 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1759 switch ( mGridAnnotationFormat )
1809int QgsLayoutItemMapGrid::xGridLines()
const
1811 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1817 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1818 QRectF mapBoundingRect = mapPolygon.boundingRect();
1819 double gridIntervalY = mEvaluatedIntervalY;
1820 double gridOffsetY = mEvaluatedOffsetY;
1821 double annotationScale = 1.0;
1822 switch ( mGridUnit )
1827 mapBoundingRect =
mMap->rect();
1828 mapPolygon = QPolygonF(
mMap->rect() );
1831 annotationScale = 0.1;
1832 gridIntervalY *= 10;
1844 const double roundCorrection = mapBoundingRect.top() > gridOffsetY ? 1.0 : 0.0;
1845 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1847 int gridLineCount = 0;
1852 double yCanvasCoord;
1853 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1855 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1857 newLine.coordinate = currentLevel * annotationScale;
1859 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1860 mGridLines.append( newLine );
1861 currentLevel += gridIntervalY;
1868 QVector<QLineF> borderLines;
1869 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1870 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1871 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1872 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1874 QVector<QPointF> intersectionList;
1876 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1878 intersectionList.clear();
1879 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1881 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1882 for ( ; it != borderLines.constEnd(); ++it )
1884 QPointF intersectionPoint;
1885 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1887 intersectionList.push_back( intersectionPoint );
1888 if ( intersectionList.size() >= 2 )
1895 if ( intersectionList.size() >= 2 )
1898 newLine.coordinate = currentLevel;
1900 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1901 mGridLines.append( newLine );
1904 currentLevel += gridIntervalY;
1911int QgsLayoutItemMapGrid::yGridLines()
const
1913 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1918 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1919 QRectF mapBoundingRect = mapPolygon.boundingRect();
1920 double gridIntervalX = mEvaluatedIntervalX;
1921 double gridOffsetX = mEvaluatedOffsetX;
1922 double annotationScale = 1.0;
1923 switch ( mGridUnit )
1928 mapBoundingRect =
mMap->rect();
1929 mapPolygon = QPolygonF(
mMap->rect() );
1932 annotationScale = 0.1;
1933 gridIntervalX *= 10;
1945 const double roundCorrection = mapBoundingRect.left() > gridOffsetX ? 1.0 : 0.0;
1946 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1948 int gridLineCount = 0;
1952 double xCanvasCoord;
1953 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1955 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1958 newLine.coordinate = currentLevel * annotationScale;
1960 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
1961 mGridLines.append( newLine );
1962 currentLevel += gridIntervalX;
1969 QVector<QLineF> borderLines;
1970 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1971 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1972 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1973 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1975 QVector<QPointF> intersectionList;
1977 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1979 intersectionList.clear();
1980 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1982 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1983 for ( ; it != borderLines.constEnd(); ++it )
1985 QPointF intersectionPoint;
1986 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1988 intersectionList.push_back( intersectionPoint );
1989 if ( intersectionList.size() >= 2 )
1996 if ( intersectionList.size() >= 2 )
1999 newLine.coordinate = currentLevel;
2001 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
2002 mGridLines.append( newLine );
2005 currentLevel += gridIntervalX;
2013 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
2018 const double roundCorrection = bbox.
yMaximum() > mEvaluatedOffsetY ? 1.0 : 0.0;
2019 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
2021 const double minX = bbox.
xMinimum();
2022 const double maxX = bbox.
xMaximum();
2023 double step = ( maxX - minX ) / 20;
2025 bool crosses180 =
false;
2026 bool crossed180 =
false;
2027 if ( mCRS.isGeographic() && ( minX > maxX ) )
2031 step = ( maxX + 360.0 - minX ) / 20;
2037 int gridLineCount = 0;
2041 double currentX = minX;
2045 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
2052 const QgsPointXY mapPoint = t.
transform( currentX, currentLevel );
2053 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2055 catch ( QgsCsException &cse )
2062 if ( crosses180 && currentX > 180.0 )
2070 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2071 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2072 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2074 if ( !( *lineIt ).isEmpty() )
2077 newLine.coordinate = currentLevel;
2079 newLine.line = QPolygonF( *lineIt );
2080 mGridLines.append( newLine );
2084 currentLevel -= mEvaluatedIntervalY;
2092 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
2097 const double roundCorrection = bbox.
xMinimum() > mEvaluatedOffsetX ? 1.0 : 0.0;
2098 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
2100 const double minY = bbox.
yMinimum();
2101 const double maxY = bbox.
yMaximum();
2102 const double step = ( maxY - minY ) / 20;
2107 bool crosses180 =
false;
2108 bool crossed180 =
false;
2115 int gridLineCount = 0;
2116 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
2119 double currentY = minY;
2123 if ( currentY > maxY )
2130 const QgsPointXY mapPoint = t.
transform( currentLevel, currentY );
2132 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2134 catch ( QgsCsException &cse )
2143 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2144 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2145 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2147 if ( !( *lineIt ).isEmpty() )
2150 newLine.coordinate = currentLevel;
2152 newLine.line = QPolygonF( *lineIt );
2153 mGridLines.append( newLine );
2157 currentLevel += mEvaluatedIntervalX;
2158 if ( crosses180 && currentLevel > 180.0 )
2160 currentLevel -= 360.0;
2189 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
2191 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
2193 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
2195 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
2209 if ( ddValue.compare(
"x_only"_L1, Qt::CaseInsensitive ) == 0 )
2211 else if ( ddValue.compare(
"y_only"_L1, Qt::CaseInsensitive ) == 0 )
2213 else if ( ddValue.compare(
"disabled"_L1, Qt::CaseInsensitive ) == 0 )
2215 else if ( ddValue.compare(
"all"_L1, Qt::CaseInsensitive ) == 0 )
2221void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
2226 mTransformDirty = mTransformDirty
2237 mDrawAnnotationProperty->prepare( context );
2241 mDrawAnnotationProperty.reset();
2244 switch ( mGridUnit )
2257 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
2259 mEvaluatedEnabled =
false;
2264 const double mapWidthMapUnits = mapWidth();
2265 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2266 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2268 mEvaluatedIntervalX = interval;
2269 mEvaluatedIntervalY = interval;
2270 mTransformDirty =
true;
2282 mEvaluatedLeftGridAnnotationDisplay
2284 mEvaluatedRightGridAnnotationDisplay
2286 mEvaluatedTopGridAnnotationDisplay
2288 mEvaluatedBottomGridAnnotationDisplay
2293 mEvaluatedBottomFrameDivisions
2297double QgsLayoutItemMapGrid::mapWidth()
const
2304 const QgsRectangle mapExtent =
mMap->extent();
2308 return mapExtent.
width();
2324 catch ( QgsCsException & )
2327 QgsDebugError( u
"An error occurred while calculating length"_s );
2333bool sortByDistance( QPair<qreal, Qgis::MapGridBorderSide> a, QPair<qreal, Qgis::MapGridBorderSide> b )
2335 return a.first < b.first;
2345 const double tolerance = std::max(
mMap->frameEnabled() ?
mMap->pen().widthF() : 0.0, 1.0 );
2349 ( p.y() <= tolerance && p.x() <= tolerance )
2350 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2351 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2352 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2358 if ( p.x() <= tolerance )
2369 if ( p.y() <= tolerance )
2381 QList< QPair<qreal, Qgis::MapGridBorderSide > > distanceToSide;
2387 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2388 return distanceToSide.at( 0 ).second;
2393 mGridLineSymbol.reset( symbol );
2398 return mGridLineSymbol.get();
2403 return mGridLineSymbol.get();
2408 mGridMarkerSymbol.reset( symbol );
2413 return mGridMarkerSymbol.get();
2418 return mGridMarkerSymbol.get();
2423 mAnnotationFormat.setFont( font );
2424 if ( font.pointSizeF() > 0 )
2426 mAnnotationFormat.setSize( font.pointSizeF() );
2429 else if ( font.pixelSize() > 0 )
2431 mAnnotationFormat.setSize( font.pixelSize() );
2438 return mAnnotationFormat.toQFont();
2443 mAnnotationFormat.
setColor( color );
2448 return mAnnotationFormat.color();
2456 mLeftGridAnnotationDisplay = display;
2459 mRightGridAnnotationDisplay = display;
2462 mTopGridAnnotationDisplay = display;
2465 mBottomGridAnnotationDisplay = display;
2469 refreshDataDefinedProperties();
2473 mMap->updateBoundingRect();
2483 return mLeftGridAnnotationDisplay;
2485 return mRightGridAnnotationDisplay;
2487 return mTopGridAnnotationDisplay;
2489 return mBottomGridAnnotationDisplay;
2491 return mBottomGridAnnotationDisplay;
2498 double bottom = 0.0;
2501 return std::max( std::max( std::max( top, right ), bottom ), left );
2511 if ( !
mMap || !mEvaluatedEnabled )
2521 GridExtension extension;
2524 switch ( mGridUnit )
2529 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
2531 drawGridCrsTransform( context, 0,
true );
2538 drawGridNoTransform( context, 0,
true );
2543 updateGridLinesAnnotationsPositions();
2547 drawGridFrame(
nullptr, &extension );
2550 if ( mShowGridAnnotation )
2555 top = extension.top;
2556 right = extension.right;
2557 bottom = extension.bottom;
2558 left = extension.left;
2564 refreshDataDefinedProperties();
2569 if ( unit == mGridUnit )
2574 mTransformDirty =
true;
2583 mGridIntervalX = interval;
2584 mTransformDirty =
true;
2585 refreshDataDefinedProperties();
2594 mGridIntervalY = interval;
2595 mTransformDirty =
true;
2596 refreshDataDefinedProperties();
2605 mGridOffsetX = offset;
2606 mTransformDirty =
true;
2607 refreshDataDefinedProperties();
2616 mGridOffsetY = offset;
2617 mTransformDirty =
true;
2618 refreshDataDefinedProperties();
2627 mMinimumIntervalWidth = minWidth;
2628 mTransformDirty =
true;
2629 refreshDataDefinedProperties();
2638 mMaximumIntervalWidth = maxWidth;
2639 mTransformDirty =
true;
2640 refreshDataDefinedProperties();
2645 if (
style == mGridStyle )
2650 mTransformDirty =
true;
2655 mCrossLength = length;
2656 refreshDataDefinedProperties();
2664 mLeftGridAnnotationDirection = direction;
2667 mRightGridAnnotationDirection = direction;
2670 mTopGridAnnotationDirection = direction;
2673 mBottomGridAnnotationDirection = direction;
2679 mMap->updateBoundingRect();
2686 mGridFrameSides = flags;
2691 mGridFrameSides.setFlag( flag, on );
2696 return mGridFrameSides;
2711 if ( mGridLineSymbol )
2717 if ( mGridMarkerSymbol )
2729 mTransformDirty =
true;
2730 refreshDataDefinedProperties();
2731 mMap->updateBoundingRect();
2737 return mGridFrameSides.testFlag( flag );
2742 mGridFrameWidth = width;
2743 refreshDataDefinedProperties();
2748 mGridFrameMargin = margin;
2749 refreshDataDefinedProperties();
2754 mGridFramePenThickness = width;
2755 refreshDataDefinedProperties();
2765 mHAlign = alignment;
2770 mLeftGridAnnotationDirection = direction;
2771 mRightGridAnnotationDirection = direction;
2772 mTopGridAnnotationDirection = direction;
2773 mBottomGridAnnotationDirection = direction;
2781 mLeftGridAnnotationPosition = position;
2784 mRightGridAnnotationPosition = position;
2787 mTopGridAnnotationPosition = position;
2790 mBottomGridAnnotationPosition = position;
2796 mMap->updateBoundingRect();
2806 return mLeftGridAnnotationPosition;
2808 return mRightGridAnnotationPosition;
2810 return mTopGridAnnotationPosition;
2812 return mBottomGridAnnotationPosition;
2814 return mLeftGridAnnotationPosition;
2819 mAnnotationFrameDistance = distance;
2820 refreshDataDefinedProperties();
2827 return mLeftGridAnnotationDirection;
2833 return mLeftGridAnnotationDirection;
2835 return mRightGridAnnotationDirection;
2837 return mTopGridAnnotationDirection;
2839 return mBottomGridAnnotationDirection;
2841 return mLeftGridAnnotationDirection;
2846 mGridAnnotationExpressionString = expression;
2847 mGridAnnotationExpression.reset();
2855 mLeftFrameDivisions = divisions;
2858 mRightFrameDivisions = divisions;
2861 mTopFrameDivisions = divisions;
2864 mBottomFrameDivisions = divisions;
2868 refreshDataDefinedProperties();
2881 return mLeftFrameDivisions;
2883 return mRightFrameDivisions;
2885 return mTopFrameDivisions;
2887 return mBottomFrameDivisions;
2889 return mLeftFrameDivisions;
2901 const QgsCoordinateTransform tr(
mMap->crs(), mCRS,
mLayout->project() );
2902 QgsCoordinateTransform extentTransform = tr;
2904 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
2905 const QRectF mbr = mapPolygon.boundingRect();
2906 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2909 if ( mCRS.isGeographic() )
2912 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2913 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2915 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2916 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2918 if ( lowerLeft.x() > upperRight.x() )
2934 inverseTransform = QgsCoordinateTransform( mCRS,
mMap->crs(),
mLayout->project() );
2936 catch ( QgsCsException &cse )
2945QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2950 const QgsGeometry intersected = lineGeom.
intersection( rectGeom );
2953 QList<QPolygonF> trimmedLines;
2954 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2955 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2957 trimmedLines << ( *geomIt ).asQPolygonF();
2959 return trimmedLines;
3034 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).
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.