55#include "moc_qgslayoutitemmapgrid.cpp"
57using namespace Qt::StringLiterals;
59#define MAX_GRID_LINES 1000
88 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
94 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
99 QList< QgsLayoutItemMapGrid * > list;
122 const QDomNodeList mapGridNodeList = elem.elementsByTagName( u
"ComposerMapGrid"_s );
123 for (
int i = 0; i < mapGridNodeList.size(); ++i )
125 const QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
127 mapGrid->
readXml( mapGridElem, doc, context );
141 return std::max( std::max( std::max( top, right ), bottom ), left );
155 double gridTop = 0.0;
156 double gridRight = 0.0;
157 double gridBottom = 0.0;
158 double gridLeft = 0.0;
159 grid->calculateMaxExtension( gridTop, gridRight, gridBottom, gridLeft );
160 top = std::max( top, gridTop );
161 right = std::max( right, gridRight );
162 bottom = std::max( bottom, gridBottom );
163 left = std::max( left, gridLeft );
179 return QVector2D( 0, 1 );
181 return QVector2D( -1, 0 );
183 return QVector2D( 0, -1 );
185 return QVector2D( 1, 0 );
193 return QVector2D( borderVector.y(), -borderVector.x() );
198 , mGridFrameSides(
Qgis::MapGridFrameSideFlag::
Left |
Qgis::MapGridFrameSideFlag::
Right |
Qgis::MapGridFrameSideFlag::Top |
Qgis::MapGridFrameSideFlag::Bottom )
202 if ( !defaultFontString.isEmpty() )
205 QgsFontUtils::setFontFamily( font, defaultFontString );
206 mAnnotationFormat.setFont( font );
209 createDefaultGridLineSymbol();
210 createDefaultGridMarkerSymbol();
215 if ( !mCRS.isValid() )
222void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
224 QVariantMap properties;
225 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
226 properties.insert( u
"width"_s, u
"0.3"_s );
227 properties.insert( u
"capstyle"_s, u
"flat"_s );
231void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
233 QVariantMap properties;
234 properties.insert( u
"name"_s, u
"circle"_s );
235 properties.insert( u
"size"_s, u
"2.0"_s );
236 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
242 if ( mGridLineSymbol )
244 mGridLineSymbol->setWidth( width );
250 if ( mGridLineSymbol )
252 mGridLineSymbol->setColor(
c );
263 QDomElement mapGridElem = doc.createElement( u
"ComposerMapGrid"_s );
264 mapGridElem.setAttribute( u
"gridStyle"_s,
static_cast< int >( mGridStyle ) );
271 QDomElement lineStyleElem = doc.createElement( u
"lineStyle"_s );
273 lineStyleElem.appendChild( gridLineStyleElem );
274 mapGridElem.appendChild( lineStyleElem );
276 QDomElement markerStyleElem = doc.createElement( u
"markerStyle"_s );
278 markerStyleElem.appendChild( gridMarkerStyleElem );
279 mapGridElem.appendChild( markerStyleElem );
281 mapGridElem.setAttribute( u
"gridFrameStyle"_s,
static_cast< int >( mGridFrameStyle ) );
282 mapGridElem.setAttribute( u
"gridFrameSideFlags"_s, mGridFrameSides );
283 mapGridElem.setAttribute( u
"gridFrameWidth"_s,
qgsDoubleToString( mGridFrameWidth ) );
284 mapGridElem.setAttribute( u
"gridFrameMargin"_s,
qgsDoubleToString( mGridFrameMargin ) );
285 mapGridElem.setAttribute( u
"gridFramePenThickness"_s,
qgsDoubleToString( mGridFramePenThickness ) );
289 mapGridElem.setAttribute( u
"leftFrameDivisions"_s,
static_cast< int >( mLeftFrameDivisions ) );
290 mapGridElem.setAttribute( u
"rightFrameDivisions"_s,
static_cast< int >( mRightFrameDivisions ) );
291 mapGridElem.setAttribute( u
"topFrameDivisions"_s,
static_cast< int >( mTopFrameDivisions ) );
292 mapGridElem.setAttribute( u
"bottomFrameDivisions"_s,
static_cast< int >( mBottomFrameDivisions ) );
293 mapGridElem.setAttribute( u
"rotatedTicksLengthMode"_s,
static_cast< int >( mRotatedTicksLengthMode ) );
294 mapGridElem.setAttribute( u
"rotatedTicksEnabled"_s, mRotatedTicksEnabled );
295 mapGridElem.setAttribute( u
"rotatedTicksMinimumAngle"_s, QString::number( mRotatedTicksMinimumAngle ) );
296 mapGridElem.setAttribute( u
"rotatedTicksMarginToCorner"_s, QString::number( mRotatedTicksMarginToCorner ) );
297 mapGridElem.setAttribute( u
"rotatedAnnotationsLengthMode"_s,
static_cast< int >( mRotatedAnnotationsLengthMode ) );
298 mapGridElem.setAttribute( u
"rotatedAnnotationsEnabled"_s, mRotatedAnnotationsEnabled );
299 mapGridElem.setAttribute( u
"rotatedAnnotationsMinimumAngle"_s, QString::number( mRotatedAnnotationsMinimumAngle ) );
300 mapGridElem.setAttribute( u
"rotatedAnnotationsMarginToCorner"_s, QString::number( mRotatedAnnotationsMarginToCorner ) );
301 if ( mCRS.isValid() )
303 mCRS.writeXml( mapGridElem, doc );
306 mapGridElem.setAttribute( u
"annotationFormat"_s,
static_cast< int >( mGridAnnotationFormat ) );
307 mapGridElem.setAttribute( u
"showAnnotation"_s, mShowGridAnnotation );
308 mapGridElem.setAttribute( u
"annotationExpression"_s, mGridAnnotationExpressionString );
309 mapGridElem.setAttribute( u
"leftAnnotationDisplay"_s,
static_cast< int >( mLeftGridAnnotationDisplay ) );
310 mapGridElem.setAttribute( u
"rightAnnotationDisplay"_s,
static_cast< int >( mRightGridAnnotationDisplay ) );
311 mapGridElem.setAttribute( u
"topAnnotationDisplay"_s,
static_cast< int >( mTopGridAnnotationDisplay ) );
312 mapGridElem.setAttribute( u
"bottomAnnotationDisplay"_s,
static_cast< int >( mBottomGridAnnotationDisplay ) );
313 mapGridElem.setAttribute( u
"leftAnnotationPosition"_s,
static_cast< int >( mLeftGridAnnotationPosition ) );
314 mapGridElem.setAttribute( u
"rightAnnotationPosition"_s,
static_cast< int >( mRightGridAnnotationPosition ) );
315 mapGridElem.setAttribute( u
"topAnnotationPosition"_s,
static_cast< int >( mTopGridAnnotationPosition ) );
316 mapGridElem.setAttribute( u
"bottomAnnotationPosition"_s,
static_cast< int >( mBottomGridAnnotationPosition ) );
317 mapGridElem.setAttribute( u
"leftAnnotationDirection"_s,
static_cast< int >( mLeftGridAnnotationDirection ) );
318 mapGridElem.setAttribute( u
"rightAnnotationDirection"_s,
static_cast< int >( mRightGridAnnotationDirection ) );
319 mapGridElem.setAttribute( u
"topAnnotationDirection"_s,
static_cast< int >( mTopGridAnnotationDirection ) );
320 mapGridElem.setAttribute( u
"bottomAnnotationDirection"_s,
static_cast< int >( mBottomGridAnnotationDirection ) );
321 mapGridElem.setAttribute( u
"frameAnnotationDistance"_s, QString::number( mAnnotationFrameDistance ) );
322 mapGridElem.appendChild( mAnnotationFormat.writeXml( doc, context ) );
323 mapGridElem.setAttribute( u
"annotationPrecision"_s, mGridAnnotationPrecision );
324 mapGridElem.setAttribute( u
"unit"_s,
static_cast< int >( mGridUnit ) );
325 mapGridElem.setAttribute( u
"blendMode"_s, mBlendMode );
326 mapGridElem.setAttribute( u
"minimumIntervalWidth"_s, QString::number( mMinimumIntervalWidth ) );
327 mapGridElem.setAttribute( u
"maximumIntervalWidth"_s, QString::number( mMaximumIntervalWidth ) );
335 elem.appendChild( mapGridElem );
342 if ( itemElem.isNull() )
350 mGridStyle =
static_cast< Qgis::MapGridStyle >( itemElem.attribute( u
"gridStyle"_s, u
"0"_s ).toInt() );
351 mGridIntervalX = itemElem.attribute( u
"intervalX"_s, u
"0"_s ).toDouble();
352 mGridIntervalY = itemElem.attribute( u
"intervalY"_s, u
"0"_s ).toDouble();
353 mGridOffsetX = itemElem.attribute( u
"offsetX"_s, u
"0"_s ).toDouble();
354 mGridOffsetY = itemElem.attribute( u
"offsetY"_s, u
"0"_s ).toDouble();
355 mCrossLength = itemElem.attribute( u
"crossLength"_s, u
"3"_s ).toDouble();
356 mGridFrameStyle =
static_cast< Qgis::MapGridFrameStyle >( itemElem.attribute( u
"gridFrameStyle"_s, u
"0"_s ).toInt() );
358 mGridFrameWidth = itemElem.attribute( u
"gridFrameWidth"_s, u
"2.0"_s ).toDouble();
359 mGridFrameMargin = itemElem.attribute( u
"gridFrameMargin"_s, u
"0.0"_s ).toDouble();
360 mGridFramePenThickness = itemElem.attribute( u
"gridFramePenThickness"_s, u
"0.3"_s ).toDouble();
368 mRotatedTicksLengthMode =
static_cast< Qgis::MapGridTickLengthMode >( itemElem.attribute( u
"rotatedTicksLengthMode"_s, u
"0"_s ).toInt() );
369 mRotatedTicksEnabled = itemElem.attribute( u
"rotatedTicksEnabled"_s, u
"0"_s ) !=
"0"_L1;
370 mRotatedTicksMinimumAngle = itemElem.attribute( u
"rotatedTicksMinimumAngle"_s, u
"0"_s ).toDouble();
371 mRotatedTicksMarginToCorner = itemElem.attribute( u
"rotatedTicksMarginToCorner"_s, u
"0"_s ).toDouble();
372 mRotatedAnnotationsLengthMode =
static_cast< Qgis::MapGridTickLengthMode >( itemElem.attribute( u
"rotatedAnnotationsLengthMode"_s, u
"0"_s ).toInt() );
373 mRotatedAnnotationsEnabled = itemElem.attribute( u
"rotatedAnnotationsEnabled"_s, u
"0"_s ) !=
"0"_L1;
374 mRotatedAnnotationsMinimumAngle = itemElem.attribute( u
"rotatedAnnotationsMinimumAngle"_s, u
"0"_s ).toDouble();
375 mRotatedAnnotationsMarginToCorner = itemElem.attribute( u
"rotatedAnnotationsMarginToCorner"_s, u
"0"_s ).toDouble();
377 const QDomElement lineStyleElem = itemElem.firstChildElement( u
"lineStyle"_s );
378 if ( !lineStyleElem.isNull() )
380 const QDomElement symbolElem = lineStyleElem.firstChildElement( u
"symbol"_s );
381 if ( !symbolElem.isNull() )
390 mGridLineSymbol->setWidth( itemElem.attribute( u
"penWidth"_s, u
"0"_s ).toDouble() );
391 mGridLineSymbol->setColor(
392 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() )
396 const QDomElement markerStyleElem = itemElem.firstChildElement( u
"markerStyle"_s );
397 if ( !markerStyleElem.isNull() )
399 const QDomElement symbolElem = markerStyleElem.firstChildElement( u
"symbol"_s );
400 if ( !symbolElem.isNull() )
406 if ( !mCRS.readXml( itemElem ) )
409 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( u
"blendMode"_s, u
"0"_s ).toUInt() );
412 mShowGridAnnotation = ( itemElem.attribute( u
"showAnnotation"_s, u
"0"_s ) !=
"0"_L1 );
414 mGridAnnotationExpressionString = itemElem.attribute( u
"annotationExpression"_s );
415 mGridAnnotationExpression.reset();
429 mAnnotationFrameDistance = itemElem.attribute( u
"frameAnnotationDistance"_s, u
"0"_s ).toDouble();
431 if ( !itemElem.firstChildElement(
"text-style" ).isNull() )
433 mAnnotationFormat.readXml( itemElem, context );
440 font.fromString( itemElem.attribute(
"annotationFont", QString() ) );
442 mAnnotationFormat.setFont( font );
443 mAnnotationFormat.setSize( font.pointSizeF() );
448 mGridAnnotationPrecision = itemElem.attribute( u
"annotationPrecision"_s, u
"3"_s ).toInt();
449 const int gridUnitInt = itemElem.attribute( u
"unit"_s, QString::number(
static_cast< int >(
Qgis::MapGridUnit::MapUnits ) ) ).toInt();
451 mMinimumIntervalWidth = itemElem.attribute( u
"minimumIntervalWidth"_s, u
"50"_s ).toDouble();
452 mMaximumIntervalWidth = itemElem.attribute( u
"maximumIntervalWidth"_s, u
"100"_s ).toDouble();
456 refreshDataDefinedProperties();
466 mTransformDirty =
true;
472 return mBlendMode != QPainter::CompositionMode_SourceOver;
475QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
477 const QTransform t = QTransform::fromScale( scale, scale );
478 return t.map( polygon );
481void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
483 if ( !
mMap || !mEvaluatedEnabled )
489 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
490 if ( mapPolygon != mPrevMapPolygon )
492 mTransformDirty =
true;
493 mPrevMapPolygon = mapPolygon;
496 if ( mTransformDirty )
498 calculateCrsTransformLines();
502 if ( !calculateLinesOnly )
504 int countLongitudeLines = 0;
505 int countLatitudeLines = 0;
506 for (
const GridLine &line : mGridLines )
508 switch ( line.coordinateType )
511 countLongitudeLines++;
514 countLatitudeLines++;
519 int latitudeLineIndex = 0;
520 int longitudeLineIndex = 0;
523 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
525 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
527 switch ( gridIt->coordinateType )
530 longitudeLineIndex++;
544 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
547 if ( drawnCount >= MAX_GRID_LINES )
553 const double maxX =
mMap->rect().width();
554 const double maxY =
mMap->rect().height();
556 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
558 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
560 const double x = intersectionIt->x();
561 const double y = intersectionIt->y();
565 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
566 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
567 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
568 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
569 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
570 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
573 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
574 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
578 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
582 if ( drawnCount >= MAX_GRID_LINES )
589void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
591 QgsRectangle crsBoundingRect;
592 QgsCoordinateTransform inverseTr;
593 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
600 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
601 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
608 QList< QgsGeometry > xLines;
609 QList< QgsGeometry > yLines;
610 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
611 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
614 for (
int i = 0; i < gridIt->line.size(); ++i )
616 line.append( QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
625 mTransformedIntersections.clear();
626 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
627 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
629 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
630 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
633 const QgsGeometry intersects = ( *yLineIt ).intersection( ( *xLineIt ) );
634 if ( intersects.
isNull() )
639 QgsPointXY vertex = intersects.
vertexAt( i );
642 mTransformedIntersections << vertex;
650 mTransformDirty =
false;
655 if ( !
mMap || !mEvaluatedEnabled )
659 QPaintDevice *paintDevice = p->device();
666 p->setCompositionMode( mBlendMode );
669 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
670 p->setClipRect( thisPaintRect );
671 if ( thisPaintRect != mPrevPaintRect )
674 mTransformDirty =
true;
675 mPrevPaintRect = thisPaintRect;
679 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
680 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
695 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
697 drawGridCrsTransform( context, dotsPerMM );
704 drawGridNoTransform( context, dotsPerMM );
709 p->setClipping(
false );
713 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
718 updateGridLinesAnnotationsPositions();
725 if ( mShowGridAnnotation )
731void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
733 QList< GridLine >::iterator it = mGridLines.begin();
734 int annotationCount = 0;
735 for ( ; it != mGridLines.end(); ++it )
737 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
738 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
739 it->startAnnotation.position = QVector2D( it->line.first() );
740 it->endAnnotation.position = QVector2D( it->line.last() );
741 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
742 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
744 it->startAnnotation.angle
745 = 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() );
747 it->endAnnotation.angle
748 = 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() );
750 if ( annotationCount >= MAX_GRID_FRAME_OBJECTS )
755void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
759 calculateYGridLines();
760 calculateXGridLines();
762 if ( calculateLinesOnly || mGridLines.empty() )
765 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
766 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
768 int countLongitudeLines = 0;
769 int countLatitudeLines = 0;
770 for (
const GridLine &line : mGridLines )
772 switch ( line.coordinateType )
775 countLongitudeLines++;
778 countLatitudeLines++;
783 int latitudeLineIndex = 0;
784 int longitudeLineIndex = 0;
793 for ( ; vIt != mGridLines.constEnd(); ++vIt )
797 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
799 longitudeLineIndex++;
805 drawGridLine( line, context );
807 if ( drawnCount >= MAX_GRID_LINES )
811 for ( ; hIt != mGridLines.constEnd(); ++hIt )
815 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
823 drawGridLine( line, context );
825 if ( drawnCount >= MAX_GRID_LINES )
832 QPointF intersectionPoint, crossEnd1, crossEnd2;
834 for ( ; vIt != mGridLines.constEnd(); ++vIt )
839 l1 = QLineF( vIt->line.first(), vIt->line.last() );
842 hIt = mGridLines.constBegin();
843 for ( ; hIt != mGridLines.constEnd(); ++hIt )
848 l2 = QLineF( hIt->line.first(), hIt->line.last() );
850 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
860 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
864 drawGridMarker( intersectionPoint * dotsPerMM, context );
869 if ( drawnCount >= MAX_GRID_LINES )
879 hIt = mGridLines.constBegin();
880 for ( ; hIt != mGridLines.constEnd(); ++hIt )
885 l1 = QLineF( hIt->line.first(), hIt->line.last() );
887 vIt = mGridLines.constBegin();
888 for ( ; vIt != mGridLines.constEnd(); ++vIt )
893 l2 = QLineF( vIt->line.first(), vIt->line.last() );
895 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
903 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
907 if ( drawnCount >= MAX_GRID_LINES )
913void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
915 QgsScopedQPainterState painterState( p );
921 mCurrentComponentDrawCount = 0;
923 switch ( mGridFrameStyle )
927 drawGridFrameZebra( p, extension );
932 drawGridFrameTicks( p, extension );
937 drawGridFrameLine( p, extension );
945void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
948 poly << line.p1() << line.p2();
949 drawGridLine( poly, context );
952void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
954 if ( !
mMap || !
mMap->layout() || !mGridLineSymbol )
959 mGridLineSymbol->startRender( context );
960 mGridLineSymbol->renderPolyline( line,
nullptr, context );
961 mGridLineSymbol->stopRender( context );
964void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
966 if ( !
mMap || !
mMap->layout() || !mGridMarkerSymbol )
971 mGridMarkerSymbol->startRender( context );
972 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
973 mGridMarkerSymbol->stopRender( context );
976void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
996void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
Qgis::MapGridBorderSide border,
double *extension )
const
1003 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1008 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
1012 double currentCoord = 0.0;
1013 bool color1 =
false;
1019 bool drawTLBox =
false;
1020 bool drawTRBox =
false;
1021 bool drawBLBox =
false;
1022 bool drawBRBox =
false;
1024 QMap< double, double > pos = QMap< double, double >();
1025 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1026 for ( ; it != mGridLines.constEnd(); ++it )
1029 for (
int i = 0; i < 2; ++i )
1031 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1034 if ( annot.border != border )
1037 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1041 pos.insert( annot.position.y(), it->coordinate );
1043 pos.insert( annot.position.x(), it->coordinate );
1050 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
1066 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
1070 QPen framePen = QPen( mGridFramePenColor );
1071 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1072 framePen.setJoinStyle( Qt::MiterJoin );
1073 p->setPen( framePen );
1075 QMap< double, double >::const_iterator posIt = pos.constBegin();
1076 for ( ; posIt != pos.constEnd(); ++posIt )
1078 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1081 height = posIt.key() - currentCoord;
1082 width = mEvaluatedGridFrameWidth;
1088 height = mEvaluatedGridFrameWidth;
1089 width = posIt.key() - currentCoord;
1091 y = ( border ==
Qgis::MapGridBorderSide::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
1093 p->drawRect( QRectF( x, y, width, height ) );
1094 currentCoord = posIt.key();
1097 mCurrentComponentDrawCount++;
1098 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1105 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin );
1106 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1108 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1110 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1112 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1114 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1118void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1128 QPen framePen = QPen( mGridFramePenColor );
1129 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1130 framePen.setCapStyle( Qt::FlatCap );
1131 p->setBrush( Qt::NoBrush );
1132 p->setPen( framePen );
1135 QList< GridLine >::iterator it = mGridLines.begin();
1136 for ( ; it != mGridLines.end(); ++it )
1139 for (
int i = 0; i < 2; ++i )
1141 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1143 if ( !shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1147 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1155 facingLeft = ( annot.angle != 0 );
1156 facingRight = ( annot.angle != 0 );
1160 facingLeft = ( annot.angle > 0 );
1161 facingRight = ( annot.angle < 0 );
1165 facingLeft = ( annot.angle < 0 );
1166 facingRight = ( annot.angle > 0 );
1170 && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1173 && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1176 && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1179 && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) || ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1183 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1185 double fA = mEvaluatedGridFrameMargin;
1186 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1190 fA /= QVector2D::dotProduct( vector, normalVector );
1191 fB /= QVector2D::dotProduct( vector, normalVector );
1198 extension->UpdateBorder( annot.border, fB );
1206 pA = annot.position +
static_cast< float >( fA ) * vector;
1207 pB = annot.position +
static_cast< float >( fB ) * vector;
1211 pA = annot.position -
static_cast< float >( fA ) * vector;
1212 pB = annot.position -
static_cast< float >( fB ) * vector;
1216 pA = annot.position -
static_cast< float >( fB ) * vector;
1217 pB = annot.position +
static_cast< float >( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1219 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1221 mCurrentComponentDrawCount++;
1222 if ( mCurrentComponentDrawCount >= MAX_GRID_TICKS )
1227void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1237 QPen framePen = QPen( mGridFramePenColor );
1238 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1239 framePen.setCapStyle( Qt::SquareCap );
1240 p->setBrush( Qt::NoBrush );
1241 p->setPen( framePen );
1251 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1260 QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1269 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1278 QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin )
1282 if ( !extension && drawDiagonals )
1287 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1288 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1289 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1294 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1295 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1296 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1301 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1302 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1303 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1308 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1309 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0;
1310 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1317 if ( mGridLines.empty() )
1320 mCurrentComponentDrawCount = 0;
1322 QString currentAnnotationString;
1323 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1325 QgsExpressionContextScope *gridScope =
new QgsExpressionContextScope();
1326 QgsExpressionContextScopePopper scopePopper( expressionContext, gridScope );
1328 bool geographic =
false;
1329 if ( mCRS.isValid() )
1331 geographic = mCRS.isGeographic();
1335 geographic =
mMap->crs().isGeographic();
1338 const bool forceWrap
1341 int countLongitudeLines = 0;
1342 int countLatitudeLines = 0;
1343 for (
const GridLine &line : mGridLines )
1345 switch ( line.coordinateType )
1348 countLongitudeLines++;
1351 countLatitudeLines++;
1356 int latitudeLineIndex = 0;
1357 int longitudeLineIndex = 0;
1358 for ( ; it != mGridLines.constEnd(); ++it )
1360 double value = it->coordinate;
1361 switch ( it->coordinateType )
1364 longitudeLineIndex++;
1365 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLongitudeLines,
true ) );
1366 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, longitudeLineIndex,
true ) );
1367 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"x"_s,
true ) );
1371 latitudeLineIndex++;
1372 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLatitudeLines,
true ) );
1373 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, latitudeLineIndex,
true ) );
1374 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"y"_s,
true ) );
1381 const double wrappedX = std::fmod( value, 360.0 );
1382 if ( wrappedX > 180.0 )
1384 value = wrappedX - 360.0;
1386 else if ( wrappedX < -180.0 )
1388 value = wrappedX + 360.0;
1392 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_number"_s, value,
true ) );
1394 if ( mDrawAnnotationProperty )
1397 const bool display = mDrawAnnotationProperty->valueAsBool( expressionContext,
true, &ok );
1398 if ( ok && !display )
1401 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext, geographic );
1402 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1403 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1404 mCurrentComponentDrawCount++;
1405 if ( mCurrentComponentDrawCount >= MAX_GRID_ANNOTATIONS )
1410void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
1419 if ( !shouldShowAnnotationForSide( coordinateType, annot.border ) )
1424 double dotsPerMM = 1;
1428 painterState.save();
1429 dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
1430 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1441 double textWidthPainterUnits = sizePainterUnits.width();
1443 textWidthPainterUnits *= 1.1;
1445 const double textWidthMM = textWidthPainterUnits * painterUnitsToMM;
1447 double textHeightPainterUnits = 0;
1448 if ( extension || doc.
size() > 1 )
1450 textHeightPainterUnits = sizePainterUnits.height();
1459 const double textHeightMM = textHeightPainterUnits * painterUnitsToMM;
1465 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1469 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1472 double distanceToFrameMM = mEvaluatedAnnotationFrameDistance;
1477 const bool hasExteriorMargin
1480 const bool hasBorderWidth
1483 distanceToFrameMM += mEvaluatedGridFrameWidth;
1484 if ( hasBorderWidth )
1485 distanceToFrameMM += mEvaluatedGridFrameLineThickness / 2.0;
1488 distanceToFrameMM *= -1;
1492 distanceToFrameMM /= QVector2D::dotProduct( vector, normalVector );
1495 QPointF annotationPositionMM = ( annot.position +
static_cast< float >( distanceToFrameMM ) * vector ).toPointF();
1500 double rotation = 0;
1504 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1506 if ( rotation <= -90 || rotation > 90 )
1509 anchorMM.setX( outside ? 0 : textWidthMM );
1513 anchorMM.setX( outside ? textWidthMM : 0 );
1517 anchorMM.setY( 0.5 * textHeightMM );
1519 anchorMM.setY( -1.5 * textHeightMM );
1521 anchorMM.setY( -0.5 * textHeightMM );
1526 anchorMM.setX( 0.5 * textWidthMM );
1527 anchorMM.setY( -0.5 * textHeightMM );
1529 anchorMM.setY( outside ? 0 : -textHeightMM );
1531 anchorMM.setX( outside ? 0 : textWidthMM );
1533 anchorMM.setY( outside ? -textHeightMM : 0 );
1535 anchorMM.setX( outside ? textWidthMM : 0 );
1540 anchorMM.setX( 0.5 * textWidthMM );
1541 anchorMM.setY( -0.5 * textHeightMM );
1543 anchorMM.setX( outside ? 0 : textWidthMM );
1545 anchorMM.setY( outside ? -textHeightMM : 0 );
1547 anchorMM.setX( outside ? textWidthMM : 0 );
1549 anchorMM.setY( outside ? 0 : -textHeightMM );
1554 anchorMM.setX( 0.5 * textWidthMM );
1555 anchorMM.setY( -0.5 * textHeightMM );
1557 anchorMM.setX( outside ? textWidthMM : 0 );
1559 anchorMM.setY( outside ? 0 : -textHeightMM );
1561 anchorMM.setX( outside ? 0 : textWidthMM );
1563 anchorMM.setY( outside ? -textHeightMM : 0 );
1568 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1569 anchorMM.setX( 0.5 * textWidthMM );
1571 anchorMM.setY( -textHeightMM );
1579 extension->UpdateBorder( frameBorder, -distanceToFrameMM + std::max( textHeightMM, textWidthMM ) );
1581 extension->UpdateAll( std::max( textHeightMM, textWidthMM ) / 2.0 );
1584 if ( extension || !context.
painter() )
1588 bool facingLeft = ( annot.angle < 0 );
1589 bool facingRight = ( annot.angle > 0 );
1592 facingLeft = !facingLeft;
1593 facingRight = !facingRight;
1595 const QRectF mapRect =
mMap->rect();
1597 && ( ( facingLeft && !
qgsDoubleGreaterThanOrNear( annot.position.x(),mRotatedAnnotationsMarginToCorner,ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM) )
1598 || ( facingRight && !
qgsDoubleLessThanOrNear( annot.position.x(), mapRect.width() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1601 && ( ( facingLeft && !
qgsDoubleLessThanOrNear( annot.position.x(), mapRect.width() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1602 || ( facingRight && !
qgsDoubleGreaterThanOrNear( annot.position.x(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1605 && ( ( facingLeft && !
qgsDoubleLessThanOrNear( annot.position.y(), mapRect.height() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1606 || ( facingRight && !
qgsDoubleGreaterThanOrNear( annot.position.y(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1609 && ( ( facingLeft && !
qgsDoubleGreaterThanOrNear( annot.position.y(), mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) )
1610 || ( facingRight && !
qgsDoubleLessThanOrNear( annot.position.y(), mapRect.height() - mRotatedAnnotationsMarginToCorner, ANNOTATION_CLOSE_TO_EDGE_TOLERANCE_MM ) ) ) )
1617 QPointF textPos( 0, 0 );
1618 switch ( annot.border )
1635 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1638 textPos.setX( textWidthMM / painterUnitsToMM );
1644 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1666 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1669 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1673 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1688 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1713 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1716 textPos.setX( textWidthMM / painterUnitsToMM );
1728 textPos.setX( textWidthMM / ( 2 * painterUnitsToMM ) );
1749 context.
painter()->translate( QPointF( annotationPositionMM.x(), annotationPositionMM.y() ) / painterUnitsToMM );
1750 context.
painter()->rotate( rotation );
1751 context.
painter()->translate( -anchorMM / painterUnitsToMM );
1762 return QString::number( value,
'f', mGridAnnotationPrecision );
1768 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1772 if ( !isGeographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1774 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1780 if ( !isGeographic || coordRounded != 0.0 )
1782 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1788 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1792 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1797 if ( !mGridAnnotationExpression )
1799 mGridAnnotationExpression = std::make_unique<QgsExpression>( mGridAnnotationExpressionString );
1800 mGridAnnotationExpression->prepare( &expressionContext );
1802 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1807 switch ( mGridAnnotationFormat )
1857void QgsLayoutItemMapGrid::calculateXGridLines()
const
1859 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1864 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1865 QRectF mapBoundingRect = mapPolygon.boundingRect();
1866 double gridIntervalY = mEvaluatedIntervalY;
1867 double gridOffsetY = mEvaluatedOffsetY;
1868 double annotationScale = 1.0;
1869 switch ( mGridUnit )
1874 mapBoundingRect =
mMap->rect();
1875 mapPolygon = QPolygonF(
mMap->rect() );
1878 annotationScale = 0.1;
1879 gridIntervalY *= 10;
1890 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY ) * gridIntervalY + gridOffsetY;
1892 currentLevel += gridIntervalY;
1894 int gridLineCount = 0;
1899 double yCanvasCoord;
1900 while (
qgsDoubleLessThanOrNear( currentLevel, mapBoundingRect.bottom(), GRID_LINE_CLOSE_TO_EDGE_TOLERANCE_MAP_UNITS ) && gridLineCount < MAX_GRID_OBJECTS )
1902 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1904 newLine.coordinate = currentLevel * annotationScale;
1906 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1907 mGridLines.append( newLine );
1908 currentLevel += gridIntervalY;
1915 QVector<QLineF> borderLines;
1916 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1917 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1918 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1919 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1921 QVector<QPointF> intersectionList;
1923 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount < MAX_GRID_OBJECTS )
1925 intersectionList.clear();
1926 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1928 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1929 for ( ; it != borderLines.constEnd(); ++it )
1931 QPointF intersectionPoint;
1932 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1934 intersectionList.push_back( intersectionPoint );
1935 if ( intersectionList.size() >= 2 )
1942 if ( intersectionList.size() >= 2 )
1945 newLine.coordinate = currentLevel;
1947 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1948 mGridLines.append( newLine );
1951 currentLevel += gridIntervalY;
1955void QgsLayoutItemMapGrid::calculateYGridLines()
const
1957 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1962 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1963 QRectF mapBoundingRect = mapPolygon.boundingRect();
1964 double gridIntervalX = mEvaluatedIntervalX;
1965 double gridOffsetX = mEvaluatedOffsetX;
1966 double annotationScale = 1.0;
1967 switch ( mGridUnit )
1972 mapBoundingRect =
mMap->rect();
1973 mapPolygon = QPolygonF(
mMap->rect() );
1976 annotationScale = 0.1;
1977 gridIntervalX *= 10;
1988 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX ) * gridIntervalX + gridOffsetX;
1990 currentLevel += gridIntervalX;
1992 int gridLineCount = 0;
1996 double xCanvasCoord;
1997 while (
qgsDoubleLessThanOrNear( currentLevel, mapBoundingRect.right(), GRID_LINE_CLOSE_TO_EDGE_TOLERANCE_MAP_UNITS ) && gridLineCount < MAX_GRID_OBJECTS )
1999 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
2002 newLine.coordinate = currentLevel * annotationScale;
2004 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
2005 mGridLines.append( newLine );
2006 currentLevel += gridIntervalX;
2013 QVector<QLineF> borderLines;
2014 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
2015 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
2016 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
2017 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
2019 QVector<QPointF> intersectionList;
2021 while ( currentLevel <= mapBoundingRect.right() && gridLineCount < MAX_GRID_OBJECTS )
2023 intersectionList.clear();
2024 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
2026 QVector<QLineF>::const_iterator it = borderLines.constBegin();
2027 for ( ; it != borderLines.constEnd(); ++it )
2029 QPointF intersectionPoint;
2030 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
2032 intersectionList.push_back( intersectionPoint );
2033 if ( intersectionList.size() >= 2 )
2040 if ( intersectionList.size() >= 2 )
2043 newLine.coordinate = currentLevel;
2045 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
2046 mGridLines.append( newLine );
2049 currentLevel += gridIntervalX;
2055 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
2060 const double roundCorrection = bbox.
yMaximum() > mEvaluatedOffsetY ? 1.0 : 0.0;
2061 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
2063 const double minX = bbox.
xMinimum();
2064 const double maxX = bbox.
xMaximum();
2065 double step = ( maxX - minX ) / 20;
2067 bool crosses180 =
false;
2068 bool crossed180 =
false;
2069 if ( mCRS.isGeographic() && ( minX > maxX ) )
2073 step = ( maxX + 360.0 - minX ) / 20;
2079 int gridLineCount = 0;
2080 while ( currentLevel >= bbox.
yMinimum() && gridLineCount < MAX_GRID_OBJECTS )
2083 double currentX = minX;
2087 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
2094 const QgsPointXY mapPoint = t.
transform( currentX, currentLevel );
2095 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2097 catch ( QgsCsException &cse )
2104 if ( crosses180 && currentX > 180.0 )
2112 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2113 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2114 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2116 if ( !( *lineIt ).isEmpty() )
2119 newLine.coordinate = currentLevel;
2121 newLine.line = QPolygonF( *lineIt );
2122 mGridLines.append( newLine );
2126 currentLevel -= mEvaluatedIntervalY;
2134 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
2139 const double roundCorrection = bbox.
xMinimum() > mEvaluatedOffsetX ? 1.0 : 0.0;
2140 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
2142 const double minY = bbox.
yMinimum();
2143 const double maxY = bbox.
yMaximum();
2144 const double step = ( maxY - minY ) / 20;
2149 bool crosses180 =
false;
2150 bool crossed180 =
false;
2157 int gridLineCount = 0;
2158 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount < MAX_GRID_OBJECTS )
2161 double currentY = minY;
2165 if ( currentY > maxY )
2172 const QgsPointXY mapPoint = t.
transform( currentLevel, currentY );
2174 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
2176 catch ( QgsCsException &cse )
2185 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2186 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2187 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2189 if ( !( *lineIt ).isEmpty() )
2192 newLine.coordinate = currentLevel;
2194 newLine.line = QPolygonF( *lineIt );
2195 mGridLines.append( newLine );
2199 currentLevel += mEvaluatedIntervalX;
2200 if ( crosses180 && currentLevel > 180.0 )
2202 currentLevel -= 360.0;
2231 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
2233 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
2235 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
2237 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
2258 auto evaluatedVisibility = VISIBILITY_MAP.lookup( ddValue );
2259 if ( evaluatedVisibility )
2261 return *evaluatedVisibility;
2269void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
2274 mTransformDirty = mTransformDirty
2285 mDrawAnnotationProperty->prepare( context );
2289 mDrawAnnotationProperty.reset();
2292 switch ( mGridUnit )
2305 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
2307 mEvaluatedEnabled =
false;
2312 const double mapWidthMapUnits = mapWidth();
2313 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2314 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2316 mEvaluatedIntervalX = interval;
2317 mEvaluatedIntervalY = interval;
2318 mTransformDirty =
true;
2330 mEvaluatedLeftGridAnnotationDisplay
2332 mEvaluatedRightGridAnnotationDisplay
2334 mEvaluatedTopGridAnnotationDisplay
2336 mEvaluatedBottomGridAnnotationDisplay
2341 mEvaluatedBottomFrameDivisions
2345double QgsLayoutItemMapGrid::mapWidth()
const
2352 const QgsRectangle mapExtent =
mMap->extent();
2356 return mapExtent.
width();
2372 catch ( QgsCsException & )
2375 QgsDebugError( u
"An error occurred while calculating length"_s );
2381bool sortByDistance( QPair<qreal, Qgis::MapGridBorderSide> a, QPair<qreal, Qgis::MapGridBorderSide> b )
2383 return a.first < b.first;
2393 const double tolerance = std::max(
mMap->frameEnabled() ?
mMap->pen().widthF() : 0.0, 1.0 );
2397 ( p.y() <= tolerance && p.x() <= tolerance )
2398 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2399 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2400 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2406 if ( p.x() <= tolerance )
2417 if ( p.y() <= tolerance )
2429 QList< QPair<qreal, Qgis::MapGridBorderSide > > distanceToSide;
2435 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2436 return distanceToSide.at( 0 ).second;
2441 mGridLineSymbol.reset( symbol );
2446 return mGridLineSymbol.get();
2451 return mGridLineSymbol.get();
2456 mGridMarkerSymbol.reset( symbol );
2461 return mGridMarkerSymbol.get();
2466 return mGridMarkerSymbol.get();
2471 mAnnotationFormat.setFont( font );
2472 if ( font.pointSizeF() > 0 )
2474 mAnnotationFormat.setSize( font.pointSizeF() );
2477 else if ( font.pixelSize() > 0 )
2479 mAnnotationFormat.setSize( font.pixelSize() );
2486 return mAnnotationFormat.toQFont();
2491 mAnnotationFormat.
setColor( color );
2496 return mAnnotationFormat.color();
2504 mLeftGridAnnotationDisplay = display;
2507 mRightGridAnnotationDisplay = display;
2510 mTopGridAnnotationDisplay = display;
2513 mBottomGridAnnotationDisplay = display;
2517 refreshDataDefinedProperties();
2521 mMap->updateBoundingRect();
2531 return mLeftGridAnnotationDisplay;
2533 return mRightGridAnnotationDisplay;
2535 return mTopGridAnnotationDisplay;
2537 return mBottomGridAnnotationDisplay;
2539 return mBottomGridAnnotationDisplay;
2546 double bottom = 0.0;
2549 return std::max( std::max( std::max( top, right ), bottom ), left );
2559 if ( !
mMap || !mEvaluatedEnabled )
2569 GridExtension extension;
2572 switch ( mGridUnit )
2577 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
2579 drawGridCrsTransform( context, 0,
true );
2586 drawGridNoTransform( context, 0,
true );
2591 updateGridLinesAnnotationsPositions();
2595 drawGridFrame(
nullptr, &extension );
2598 if ( mShowGridAnnotation )
2603 top = extension.top;
2604 right = extension.right;
2605 bottom = extension.bottom;
2606 left = extension.left;
2612 refreshDataDefinedProperties();
2617 if ( unit == mGridUnit )
2622 mTransformDirty =
true;
2631 mGridIntervalX = interval;
2632 mTransformDirty =
true;
2633 refreshDataDefinedProperties();
2642 mGridIntervalY = interval;
2643 mTransformDirty =
true;
2644 refreshDataDefinedProperties();
2653 mGridOffsetX = offset;
2654 mTransformDirty =
true;
2655 refreshDataDefinedProperties();
2664 mGridOffsetY = offset;
2665 mTransformDirty =
true;
2666 refreshDataDefinedProperties();
2675 mMinimumIntervalWidth = minWidth;
2676 mTransformDirty =
true;
2677 refreshDataDefinedProperties();
2686 mMaximumIntervalWidth = maxWidth;
2687 mTransformDirty =
true;
2688 refreshDataDefinedProperties();
2693 if (
style == mGridStyle )
2698 mTransformDirty =
true;
2703 mCrossLength = length;
2704 refreshDataDefinedProperties();
2712 mLeftGridAnnotationDirection = direction;
2715 mRightGridAnnotationDirection = direction;
2718 mTopGridAnnotationDirection = direction;
2721 mBottomGridAnnotationDirection = direction;
2727 mMap->updateBoundingRect();
2734 mGridFrameSides = flags;
2739 mGridFrameSides.setFlag( flag, on );
2744 return mGridFrameSides;
2759 if ( mGridLineSymbol )
2765 if ( mGridMarkerSymbol )
2777 mTransformDirty =
true;
2778 refreshDataDefinedProperties();
2779 mMap->updateBoundingRect();
2785 return mGridFrameSides.testFlag( flag );
2790 mGridFrameWidth = width;
2791 refreshDataDefinedProperties();
2796 mGridFrameMargin = margin;
2797 refreshDataDefinedProperties();
2802 mGridFramePenThickness = width;
2803 refreshDataDefinedProperties();
2813 mHAlign = alignment;
2818 mLeftGridAnnotationDirection = direction;
2819 mRightGridAnnotationDirection = direction;
2820 mTopGridAnnotationDirection = direction;
2821 mBottomGridAnnotationDirection = direction;
2829 mLeftGridAnnotationPosition = position;
2832 mRightGridAnnotationPosition = position;
2835 mTopGridAnnotationPosition = position;
2838 mBottomGridAnnotationPosition = position;
2844 mMap->updateBoundingRect();
2854 return mLeftGridAnnotationPosition;
2856 return mRightGridAnnotationPosition;
2858 return mTopGridAnnotationPosition;
2860 return mBottomGridAnnotationPosition;
2862 return mLeftGridAnnotationPosition;
2867 mAnnotationFrameDistance = distance;
2868 refreshDataDefinedProperties();
2875 return mLeftGridAnnotationDirection;
2881 return mLeftGridAnnotationDirection;
2883 return mRightGridAnnotationDirection;
2885 return mTopGridAnnotationDirection;
2887 return mBottomGridAnnotationDirection;
2889 return mLeftGridAnnotationDirection;
2894 mGridAnnotationExpressionString = expression;
2895 mGridAnnotationExpression.reset();
2903 mLeftFrameDivisions = divisions;
2906 mRightFrameDivisions = divisions;
2909 mTopFrameDivisions = divisions;
2912 mBottomFrameDivisions = divisions;
2916 refreshDataDefinedProperties();
2929 return mLeftFrameDivisions;
2931 return mRightFrameDivisions;
2933 return mTopFrameDivisions;
2935 return mBottomFrameDivisions;
2937 return mLeftFrameDivisions;
2949 const QgsCoordinateTransform tr(
mMap->crs(), mCRS,
mLayout->project() );
2950 QgsCoordinateTransform extentTransform = tr;
2952 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
2953 const QRectF mbr = mapPolygon.boundingRect();
2954 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2957 if ( mCRS.isGeographic() )
2960 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2961 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2963 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2964 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2966 if ( lowerLeft.x() > upperRight.x() )
2982 inverseTransform = QgsCoordinateTransform( mCRS,
mMap->crs(),
mLayout->project() );
2984 catch ( QgsCsException &cse )
2993QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2998 const QgsGeometry intersected = lineGeom.
intersection( rectGeom );
3001 QList<QPolygonF> trimmedLines;
3002 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
3003 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
3005 trimmedLines << ( *geomIt ).asQPolygonF();
3007 return trimmedLines;
3082 refreshDataDefinedProperties();
Provides global constants and enumerations for use throughout the application.
MapGridTickLengthMode
Map grid tick length mode (useful for rotated grids).
@ OrthogonalTicks
Align ticks orthogonaly.
QFlags< MapGridFrameSideFlag > MapGridFrameSideFlags
Flags for controlling which side of the map a frame is drawn on.
@ Default
Allow raster-based rendering in situations where it is required for correct rendering or where it wil...
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
@ Millimeters
Millimeters.
MapGridAnnotationPosition
Position for map grid annotations.
@ InsideMapFrame
Draw annotations inside the map frame.
@ OutsideMapFrame
Draw annotations outside the map frame.
MapGridUnit
Units for map grid values.
@ Centimeters
Grid units in centimeters.
@ Millimeters
Grid units in millimeters.
@ DynamicPageSizeBased
Dynamically sized, based on a on-page size range.
@ MapUnits
Grid units follow map units.
DistanceUnit
Units of distance.
@ Unknown
Unknown distance unit.
MapGridBorderSide
Border sides for map grid annotations.
MapGridFrameSideFlag
Flags for controlling which side of the map a frame is drawn on.
@ Bottom
Bottom side of map.
@ Right
Right side of map.
@ Point
Text at point of origin layout mode.
MapGridComponentVisibility
Visibility display settings for map grid annotations and frames.
@ ShowAll
Show both latitude and longitude annotations/divisions.
@ LongitudeOnly
Show longitude/x annotations/divisions only.
@ LatitudeOnly
Show latitude/y annotations/divisions only.
@ Horizontal
Horizontally oriented text.
MapGridStyle
Map grid drawing styles.
@ LineCrosses
Draw line crosses at intersections of grid lines.
@ Markers
Draw markers at intersections of grid lines.
@ Lines
Draw lines for grid.
@ FrameAndAnnotationsOnly
No grid lines over the map, only draw frame and annotations.
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
MapGridAnnotationType
Annotation coordinate type.
@ Latitude
Coordinate is a latitude value.
@ Longitude
Coordinate is a longitude value.
MapGridFrameStyle
Style for map grid frames.
@ LineBorderNautical
Simple solid line frame, with nautical style diagonals on corners.
@ ZebraNautical
Black/white pattern, with nautical style diagonals on corners.
@ InteriorExteriorTicks
Tick markers drawn both inside and outside the map frame.
@ NoFrame
Disable grid frame.
@ ExteriorTicks
Tick markers drawn outside map frame.
@ Zebra
Black/white pattern.
@ LineBorder
Simple solid line frame.
@ InteriorTicks
Tick markers drawn inside map frame.
MapGridAnnotationDirection
Direction of grid annotations.
@ Vertical
Draw annotations vertically, ascending.
@ UnderTick
Draw annotations parallel to tick (under the line).
@ VerticalDescending
Draw annotations vertically, descending.
@ BoundaryDirection
Annotations follow the boundary direction.
@ AboveTick
Draw annotations parallel to tick (above the line).
@ OnTick
Draw annotations parallel to tick (on the line).
@ Horizontal
Draw annotations horizontally.
TextHorizontalAlignment
Text horizontal alignment.
MapGridAnnotationFormat
Format for displaying map grid annotations.
@ DegreeMinute
Degree/minutes, use NSEW suffix.
@ DegreeMinuteSecond
Degree/minutes/seconds, use NSEW suffix.
@ DegreeMinuteNoSuffix
Degree/minutes, use - for S/W coordinates.
@ CustomFormat
Custom expression-based format.
@ Decimal
Decimal degrees, use - for S/W coordinates.
@ DegreeMinuteSecondNoSuffix
Degree/minutes/seconds, use - for S/W coordinates.
@ DegreeMinutePadded
Degree/minutes, with minutes using leading zeros where required.
@ DegreeMinuteSecondPadded
Degree/minutes/seconds, with minutes using leading zeros where required.
@ DecimalWithSuffix
Decimal degrees, use NSEW suffix.
@ Forward
Forward transform (from source to destination).
@ Antialiasing
Use antialiasing when drawing items.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Represents a coordinate reference system (CRS).
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
Qgis::DistanceUnit lengthUnits() const
Returns the units of distance for length calculations made by this object.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters(), QgsFeedback *feedback=nullptr) const
Returns a geometry representing the points shared by this geometry and other.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
QList< QgsLayoutItemMapGrid * > asList() const
Returns a list of QgsLayoutItemMapGrids contained by the stack.
void calculateMaxGridExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void removeGrid(const QString &gridId)
Removes a grid with matching gridId from the stack and deletes the corresponding QgsLayoutItemMapGrid...
double maxGridExtension() const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void addGrid(QgsLayoutItemMapGrid *grid)
Adds a new map grid to the stack and takes ownership of the grid.
QgsLayoutItemMapGrid * grid(const QString &gridId) const
Returns a reference to a grid with matching gridId within the stack.
bool readXml(const QDomElement &elem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets the item stack's state from a DOM document, where element is a DOM node corresponding to a 'Layo...
QgsLayoutItemMapGrid & operator[](int index)
Returns a reference to a grid at the specified index within the stack.
void moveGridUp(const QString &gridId)
Moves a grid with matching gridId up the stack, causing it to be rendered above other grids.
void moveGridDown(const QString &gridId)
Moves a grid with matching gridId down the stack, causing it to be rendered below other grids.
QgsLayoutItemMapGridStack(QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGridStack, attached to the specified map.
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
void setFrameSideFlags(Qgis::MapGridFrameSideFlags flags)
Sets flags for grid frame sides.
void setRotatedTicksLengthMode(const Qgis::MapGridTickLengthMode mode)
Sets the tick length calculation mode.
bool rotatedAnnotationsEnabled() const
Gets whether annotations rotation for rotated or reprojected grids is enabled.
QString annotationExpression() const
Returns the expression used for drawing grid annotations.
double rotatedTicksMarginToCorner() const
Gets the margin to corners (in canvas units) below which outwards facing ticks are not drawn.
void calculateMaxExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect.
void setFrameFillColor2(const QColor &color)
Sets the second fill color used for the grid frame.
bool writeXml(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Stores map item state in a DOM element, where element is the DOM element corresponding to a 'LayoutMa...
void refresh() override
Refreshes the object, causing a recalculation of any property overrides.
void setAnnotationDisplay(Qgis::MapGridComponentVisibility display, Qgis::MapGridBorderSide border)
Sets what types of grid annotations should be drawn for a specified side of the map frame,...
void setFrameStyle(const Qgis::MapGridFrameStyle style)
Sets the grid frame style.
void setUnits(Qgis::MapGridUnit unit)
Sets the unit to use for grid measurements such as the interval and offset for grid lines.
Q_DECL_DEPRECATED void setAnnotationFontColor(const QColor &color)
Sets the font color used for drawing grid annotations.
double frameWidth() const
Gets the grid frame width in layout units.
void draw(QPainter *painter) override
Draws the item on to a destination painter.
double crossLength() const
Retrieves the length (in layout units) of the cross segments drawn for the grid.
void setIntervalY(double interval)
Sets the interval between grid lines in the y-direction.
void setRotatedTicksMinimumAngle(const double angle)
Sets the minimum angle (in degrees) below which ticks are not drawn.
Q_DECL_DEPRECATED QColor annotationFontColor() const
Returns the font color used for drawing grid annotations.
QPainter::CompositionMode blendMode() const
Retrieves the blending mode used for drawing the grid.
void setAnnotationEnabled(const bool enabled)
Sets whether annotations should be shown for the grid.
QgsTextFormat annotationTextFormat() const
Returns the text format used when rendering grid annotations.
void setStyle(Qgis::MapGridStyle style)
Sets the grid style, which controls how the grid is drawn over the map's contents.
double framePenSize() const
Retrieves the width of the stroke drawn in the grid frame.
void setFramePenColor(const QColor &color)
Sets the color of the stroke drawn in the grid frame.
void setFramePenSize(const double width)
Sets the width of the stroke drawn in the grid frame.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
void setRotatedTicksEnabled(const bool state)
Enable/disable ticks rotation for rotated or reprojected grids.
Qgis::MapGridUnit units() const
Returns the units used for grid measurements such as the interval and offset for grid lines.
Q_DECL_DEPRECATED QFont annotationFont() const
Returns the font used for drawing grid annotations.
double maxExtension() const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect (in layout u...
void setFrameDivisions(Qgis::MapGridComponentVisibility divisions, Qgis::MapGridBorderSide side)
Sets what type of grid divisions should be used for frames on a specified side of the map.
Qgis::MapGridStyle style() const
Returns the grid's style, which controls how the grid is drawn over the map's contents.
double rotatedTicksMinimumAngle() const
Gets the minimum angle (in degrees) below which ticks are not drawn.
bool readXml(const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets the map item state from a DOM document, where element is the DOM node corresponding to a 'Layout...
Qgis::MapGridTickLengthMode rotatedAnnotationsLengthMode() const
Returns the annotation length calculation mode.
Qgis::MapGridFrameStyle frameStyle() const
Returns the grid frame style.
void setMinimumIntervalWidth(double width)
Sets the minimum width (in millimeters) for grid segments.
friend class QgsLayoutItemMap
void setIntervalX(double interval)
Sets the interval between grid lines in the x-direction.
void setCrossLength(const double length)
Sets the length (in layout units) of the cross segments drawn for the grid.
void setAnnotationDirection(Qgis::MapGridAnnotationDirection direction, Qgis::MapGridBorderSide side)
Sets the direction for drawing frame annotations for the specified map side.
void setEnabled(bool enabled) override
Controls whether the item will be drawn.
void setAnnotationFrameDistance(const double distance)
Sets the distance between the map frame and annotations.
void crsChanged()
Emitted whenever the grid's CRS is changed.
void setRotatedAnnotationsMinimumAngle(const double angle)
Sets the minimum angle (in degrees) below which annotations are not drawn.
void setFrameMargin(const double margin)
Sets the grid frame margin (in layout units).
double rotatedAnnotationsMinimumAngle() const
Gets the minimum angle (in degrees) below which annotations are not drawn.
void setAnnotationTextFormat(const QgsTextFormat &format)
Sets the text format to use when rendering grid annotations.
QgsLayoutItemMapGrid(const QString &name, QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGrid.
Qgis::MapGridTickLengthMode rotatedTicksLengthMode() const
Returns the grid frame style.
~QgsLayoutItemMapGrid() override
void copyProperties(const QgsLayoutItemMapGrid *other)
Copies properties from specified map grid.
void setBlendMode(const QPainter::CompositionMode mode)
Sets the blending mode used for drawing the grid.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used for drawing grid points.
bool annotationEnabled() const
Returns whether annotations are shown for the grid.
void setMaximumIntervalWidth(double width)
Sets the maximum width (in millimeters) for grid segments.
Qgis::MapGridComponentVisibility frameDivisions(Qgis::MapGridBorderSide side) const
Returns the type of grid divisions which are used for frames on a specified side of the map.
Qgis::MapGridFrameSideFlags frameSideFlags() const
Returns the flags which control which sides of the map item the grid frame is drawn on.
void setAnnotationPosition(Qgis::MapGridAnnotationPosition position, Qgis::MapGridBorderSide side)
Sets the position for the grid annotations on a specified side of the map frame.
QColor framePenColor() const
Retrieves the color of the stroke drawn in the grid frame.
bool usesAdvancedEffects() const override
Returns true if the item is drawn using advanced effects, such as blend modes.
Q_DECL_DEPRECATED void setAnnotationFont(const QFont &font)
Sets the font used for drawing grid annotations.
void setRotatedTicksMarginToCorner(const double margin)
Sets the margin to corners (in canvas units) below which outwards facing ticks are not drawn.
void setAnnotationPrecision(const int precision)
Sets the coordinate precision for grid annotations.
QColor frameFillColor2() const
Retrieves the second fill color for the grid frame.
void setRotatedAnnotationsLengthMode(const Qgis::MapGridTickLengthMode mode)
Sets the annotation length calculation mode.
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used for drawing grid lines.
QgsCoordinateReferenceSystem crs() const
Retrieves the CRS for the grid.
void setRotatedAnnotationsMarginToCorner(const double margin)
Sets the margin to corners (in canvas units) below which outwards facing annotations are not drawn.
double rotatedAnnotationsMarginToCorner() const
Gets the margin to corners (in canvas units) below which outwards facing annotations are not drawn.
double offsetX() const
Returns the offset for grid lines in the x-direction.
bool rotatedTicksEnabled() const
Gets whether ticks rotation for rotated or reprojected grids is enabled.
double annotationFrameDistance() const
Returns the distance between the map frame and annotations.
double intervalY() const
Returns the interval between grid lines in the y-direction.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs for the grid.
bool testFrameSideFlag(Qgis::MapGridFrameSideFlag flag) const
Tests whether the grid frame should be drawn on a specified side of the map item.
double minimumIntervalWidth() const
Returns the minimum width (in millimeters) for grid segments.
void setOffsetY(double offset)
Sets the offset for grid lines in the y-direction.
const QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol used for drawing grid points.
const QgsLineSymbol * lineSymbol() const
Returns the line symbol used for drawing grid lines.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QColor frameFillColor1() const
Retrieves the first fill color for the grid frame.
void setRotatedAnnotationsEnabled(const bool state)
Enable/disable annotations rotation for rotated or reprojected grids.
void setAnnotationFormat(const Qgis::MapGridAnnotationFormat format)
Sets the format for drawing grid annotations.
void setFrameWidth(const double width)
Sets the grid frame width (in layout units).
Qgis::MapGridComponentVisibility annotationDisplay(Qgis::MapGridBorderSide border) const
Returns the display mode for the grid annotations on a specified side of the map frame.
void setFrameFillColor1(const QColor &color)
Sets the first fill color used for the grid frame.
double frameMargin() const
Sets the grid frame Margin (in layout units).
void setOffsetX(double offset)
Sets the offset for grid lines in the x-direction.
Qgis::MapGridAnnotationFormat annotationFormat() const
Returns the format for drawing grid annotations.
void setFrameSideFlag(Qgis::MapGridFrameSideFlag flag, bool on=true)
Sets whether the grid frame is drawn for a certain side of the map item.
Qgis::MapGridAnnotationDirection annotationDirection(Qgis::MapGridBorderSide border) const
Returns the direction for drawing frame annotations, on the specified side of the map.
Qgis::MapGridAnnotationPosition annotationPosition(Qgis::MapGridBorderSide side) const
Returns the position for the grid annotations on a specified side of the map frame.
void setGridLineColor(const QColor &color)
Sets the color of grid lines.
void setGridLineWidth(double width)
Sets the width of grid lines (in layout units).
int annotationPrecision() const
Returns the coordinate precision for grid annotations, which is the number of decimal places shown wh...
double maximumIntervalWidth() const
Returns the maximum width (in millimeters) for grid segments.
Qgis::TextHorizontalAlignment horizontalAlignment() const
Returns the horizontal alignment for annotation text.
void setHorizontalAlignment(Qgis::TextHorizontalAlignment alignment)
Sets the horizontal alignment for annotation text.
void setAnnotationExpression(const QString &expression)
Sets the expression used for drawing grid annotations.
double intervalX() const
Returns the interval between grid lines in the x-direction.
void addItem(QgsLayoutItemMapItem *item)
Adds a new map item to the stack and takes ownership of the item.
void removeItem(const QString &itemId)
Removes an item which matching itemId from the stack and deletes the corresponding QgsLayoutItemMapIt...
QgsLayoutItemMapItem * item(int index) const
Returns a reference to the item at the specified index within the stack.
void moveItemUp(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items.
void removeItems()
Clears the item stack and deletes all QgsLayoutItemMapItems contained by the stack.
QgsLayoutItemMapItemStack(QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapItemStack, attached to the specified map.
QList< QgsLayoutItemMapItem * > mItems
void moveItemDown(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items.
An item which is drawn inside a QgsLayoutItemMap, e.g., a grid or map overview.
QgsLayoutItemMap * mMap
Associated map.
virtual bool readXml(const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context)
Sets the map item state from a DOM document, where element is the DOM node corresponding to a 'Layout...
virtual bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Stores map item state in a DOM element, where element is the DOM element corresponding to a 'LayoutMa...
virtual void setEnabled(bool enabled)
Controls whether the item will be drawn.
QString name() const
Returns the friendly display name for the item.
QgsLayoutItemMapItem(const QString &name, QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapItem, attached to the specified map.
bool enabled() const
Returns whether the item will be drawn.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
const QgsLayoutItemMap * map() const
Returns the layout item map for the item.
Layout graphical items for displaying a map.
void extentChanged()
Emitted when the map's extent changes.
void mapRotationChanged(double newRotation)
Emitted when the map's rotation changes.
void crsChanged()
Emitted when the map's coordinate reference system is changed.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the object's property collection, used for data defined overrides.
QPointer< QgsLayout > mLayout
@ MapGridOffsetY
Map grid offset Y.
@ MapGridFrameDivisionsBottom
Map frame division display bottom.
@ MapGridEnabled
Map grid enabled.
@ MapGridIntervalX
Map grid interval X.
@ MapGridFrameDivisionsTop
Map frame division display top.
@ MapGridAnnotationDisplayLeft
Map annotation display left.
@ MapGridFrameMargin
Map grid frame margin.
@ MapGridDrawAnnotation
Map annotation visibility (for individual annotations).
@ MapGridCrossSize
Map grid cross size.
@ MapGridAnnotationDisplayRight
Map annotation display right.
@ MapGridOffsetX
Map grid offset X.
@ MapGridAnnotationDisplayTop
Map annotation display top.
@ MapGridAnnotationDisplayBottom
Map annotation display bottom.
@ MapGridFrameDivisionsRight
Map frame division display right.
@ MapGridLabelDistance
Map grid label distance.
@ MapGridIntervalY
Map grid interval Y.
@ MapGridFrameSize
Map grid frame size.
@ MapGridFrameLineThickness
Map grid frame line thickness.
@ MapGridFrameDivisionsLeft
Map frame division display left.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the objects's property collection, used for data defined overrides.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static double calculatePrettySize(double minimumSize, double maximumSize)
Calculates a "pretty" size which falls between the range [minimumSize, maximumSize].
static const QgsSettingsEntryString * settingsLayoutDefaultFont
Settings entry for the default font family used for new layout items.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
A marker symbol type, for rendering Point and MultiPoint geometries.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
bool isEmpty() const
Returns true if the geometry is empty.
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
Qgis::RasterizedRenderingPolicy rasterizedRenderingPolicy() const
Returns the policy controlling when rasterisation of content during renders is permitted.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Scoped object for saving and restoring a QPainter object's state.
@ NoSave
Do not save the current painter state.
void restore()
Performs a manual restore on the painter state, popping the latest state from the painter.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
void setColor(const QColor &color) const
Sets the color for the symbol.
QSizeF documentSize(Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation) const
Returns the overall size of the document.
static QgsTextDocumentMetrics calculateMetrics(const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor=1.0, const QgsTextDocumentRenderContext &documentContext=QgsTextDocumentRenderContext())
Returns precalculated text metrics for a text document, when rendered using the given base format and...
int size() const
Returns the number of blocks in the document.
static QgsTextDocument fromTextAndFormat(const QStringList &lines, const QgsTextFormat &format)
Constructor for QgsTextDocument consisting of a set of lines, respecting settings from a text format.
static void drawDocument(const QRectF &rect, const QgsTextFormat &format, const QgsTextDocument &document, const QgsTextDocumentMetrics &metrics, QgsRenderContext &context, Qgis::TextHorizontalAlignment horizontalAlignment=Qgis::TextHorizontalAlignment::Left, Qgis::TextVerticalAlignment verticalAlignment=Qgis::TextVerticalAlignment::Top, double rotation=0, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags())
Draws a text document within a rectangle using the specified settings.
static double calculateScaleFactorForFormat(const QgsRenderContext &context, const QgsTextFormat &format)
Returns the scale factor used for upscaling font sizes and downscaling destination painter devices.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Point, QFontMetricsF *fontMetrics=nullptr, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), double maxLineWidth=0)
Returns the height of a text based on a given format.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
bool qgsDoubleGreaterThanOrNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles to see if one is greater than the other or very near to the other.
bool qgsDoubleLessThanOrNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles to see if one is less than the other or very near to the other.
constexpr QgsDataDefinedStringDecoder< V, N > makeDataDefinedStringDecoder(const DataDefinedDecoderEntry< V >(&values)[N])
Creates a QgsDataDefinedStringDecoder from a hardcoded lookup table.
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.