53#include "moc_qgslayoutitemmapgrid.cpp"
55using namespace Qt::StringLiterals;
57#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 |
199 Qgis::MapGridFrameSideFlag::Top |
Qgis::MapGridFrameSideFlag::Bottom )
203 const QString defaultFontString = settings.
value( u
"LayoutDesigner/defaultFont"_s, QVariant(),
QgsSettings::Gui ).toString();
204 if ( !defaultFontString.isEmpty() )
207 QgsFontUtils::setFontFamily( font, defaultFontString );
208 mAnnotationFormat.setFont( font );
211 createDefaultGridLineSymbol();
212 createDefaultGridMarkerSymbol();
218 if ( !mCRS.isValid() )
225void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
227 QVariantMap properties;
228 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
229 properties.insert( u
"width"_s, u
"0.3"_s );
230 properties.insert( u
"capstyle"_s, u
"flat"_s );
234void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
236 QVariantMap properties;
237 properties.insert( u
"name"_s, u
"circle"_s );
238 properties.insert( u
"size"_s, u
"2.0"_s );
239 properties.insert( u
"color"_s, u
"0,0,0,255"_s );
245 if ( mGridLineSymbol )
247 mGridLineSymbol->setWidth( width );
253 if ( mGridLineSymbol )
255 mGridLineSymbol->setColor(
c );
266 QDomElement mapGridElem = doc.createElement( u
"ComposerMapGrid"_s );
267 mapGridElem.setAttribute( u
"gridStyle"_s,
static_cast< int >( mGridStyle ) );
274 QDomElement lineStyleElem = doc.createElement( u
"lineStyle"_s );
276 lineStyleElem.appendChild( gridLineStyleElem );
277 mapGridElem.appendChild( lineStyleElem );
279 QDomElement markerStyleElem = doc.createElement( u
"markerStyle"_s );
281 markerStyleElem.appendChild( gridMarkerStyleElem );
282 mapGridElem.appendChild( markerStyleElem );
284 mapGridElem.setAttribute( u
"gridFrameStyle"_s,
static_cast< int >( mGridFrameStyle ) );
285 mapGridElem.setAttribute( u
"gridFrameSideFlags"_s, mGridFrameSides );
286 mapGridElem.setAttribute( u
"gridFrameWidth"_s,
qgsDoubleToString( mGridFrameWidth ) );
287 mapGridElem.setAttribute( u
"gridFrameMargin"_s,
qgsDoubleToString( mGridFrameMargin ) );
288 mapGridElem.setAttribute( u
"gridFramePenThickness"_s,
qgsDoubleToString( mGridFramePenThickness ) );
292 mapGridElem.setAttribute( u
"leftFrameDivisions"_s,
static_cast< int >( mLeftFrameDivisions ) );
293 mapGridElem.setAttribute( u
"rightFrameDivisions"_s,
static_cast< int >( mRightFrameDivisions ) );
294 mapGridElem.setAttribute( u
"topFrameDivisions"_s,
static_cast< int >( mTopFrameDivisions ) );
295 mapGridElem.setAttribute( u
"bottomFrameDivisions"_s,
static_cast< int >( mBottomFrameDivisions ) );
296 mapGridElem.setAttribute( u
"rotatedTicksLengthMode"_s,
static_cast< int >( mRotatedTicksLengthMode ) );
297 mapGridElem.setAttribute( u
"rotatedTicksEnabled"_s, mRotatedTicksEnabled );
298 mapGridElem.setAttribute( u
"rotatedTicksMinimumAngle"_s, QString::number( mRotatedTicksMinimumAngle ) );
299 mapGridElem.setAttribute( u
"rotatedTicksMarginToCorner"_s, QString::number( mRotatedTicksMarginToCorner ) );
300 mapGridElem.setAttribute( u
"rotatedAnnotationsLengthMode"_s,
static_cast< int >( mRotatedAnnotationsLengthMode ) );
301 mapGridElem.setAttribute( u
"rotatedAnnotationsEnabled"_s, mRotatedAnnotationsEnabled );
302 mapGridElem.setAttribute( u
"rotatedAnnotationsMinimumAngle"_s, QString::number( mRotatedAnnotationsMinimumAngle ) );
303 mapGridElem.setAttribute( u
"rotatedAnnotationsMarginToCorner"_s, QString::number( mRotatedAnnotationsMarginToCorner ) );
304 if ( mCRS.isValid() )
306 mCRS.writeXml( mapGridElem, doc );
309 mapGridElem.setAttribute( u
"annotationFormat"_s,
static_cast< int >( mGridAnnotationFormat ) );
310 mapGridElem.setAttribute( u
"showAnnotation"_s, mShowGridAnnotation );
311 mapGridElem.setAttribute( u
"annotationExpression"_s, mGridAnnotationExpressionString );
312 mapGridElem.setAttribute( u
"leftAnnotationDisplay"_s,
static_cast< int >( mLeftGridAnnotationDisplay ) );
313 mapGridElem.setAttribute( u
"rightAnnotationDisplay"_s,
static_cast< int >( mRightGridAnnotationDisplay ) );
314 mapGridElem.setAttribute( u
"topAnnotationDisplay"_s,
static_cast< int >( mTopGridAnnotationDisplay ) );
315 mapGridElem.setAttribute( u
"bottomAnnotationDisplay"_s,
static_cast< int >( mBottomGridAnnotationDisplay ) );
316 mapGridElem.setAttribute( u
"leftAnnotationPosition"_s,
static_cast< int >( mLeftGridAnnotationPosition ) );
317 mapGridElem.setAttribute( u
"rightAnnotationPosition"_s,
static_cast< int >( mRightGridAnnotationPosition ) );
318 mapGridElem.setAttribute( u
"topAnnotationPosition"_s,
static_cast< int >( mTopGridAnnotationPosition ) );
319 mapGridElem.setAttribute( u
"bottomAnnotationPosition"_s,
static_cast< int >( mBottomGridAnnotationPosition ) );
320 mapGridElem.setAttribute( u
"leftAnnotationDirection"_s,
static_cast< int >( mLeftGridAnnotationDirection ) );
321 mapGridElem.setAttribute( u
"rightAnnotationDirection"_s,
static_cast< int >( mRightGridAnnotationDirection ) );
322 mapGridElem.setAttribute( u
"topAnnotationDirection"_s,
static_cast< int >( mTopGridAnnotationDirection ) );
323 mapGridElem.setAttribute( u
"bottomAnnotationDirection"_s,
static_cast< int >( mBottomGridAnnotationDirection ) );
324 mapGridElem.setAttribute( u
"frameAnnotationDistance"_s, QString::number( mAnnotationFrameDistance ) );
325 mapGridElem.appendChild( mAnnotationFormat.writeXml( doc, context ) );
326 mapGridElem.setAttribute( u
"annotationPrecision"_s, mGridAnnotationPrecision );
327 mapGridElem.setAttribute( u
"unit"_s,
static_cast< int >( mGridUnit ) );
328 mapGridElem.setAttribute( u
"blendMode"_s, mBlendMode );
329 mapGridElem.setAttribute( u
"minimumIntervalWidth"_s, QString::number( mMinimumIntervalWidth ) );
330 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( QColor( itemElem.attribute( u
"penColorRed"_s, u
"0"_s ).toInt(),
390 itemElem.attribute( u
"penColorGreen"_s, u
"0"_s ).toInt(),
391 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();
452 refreshDataDefinedProperties();
462 mTransformDirty =
true;
468 return mBlendMode != QPainter::CompositionMode_SourceOver;
471QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
473 const QTransform t = QTransform::fromScale( scale, scale );
474 return t.map( polygon );
477void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
479 if ( !
mMap || !mEvaluatedEnabled )
485 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
486 if ( mapPolygon != mPrevMapPolygon )
488 mTransformDirty =
true;
489 mPrevMapPolygon = mapPolygon;
492 if ( mTransformDirty )
494 calculateCrsTransformLines();
498 if ( !calculateLinesOnly )
500 int countLongitudeLines = 0;
501 int countLatitudeLines = 0;
502 for (
const GridLine &line : mGridLines )
504 switch ( line.coordinateType )
507 countLongitudeLines++;
510 countLatitudeLines++;
515 int latitudeLineIndex = 0;
516 int longitudeLineIndex = 0;
519 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
520 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
522 switch ( gridIt->coordinateType )
525 longitudeLineIndex++;
539 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
544 const double maxX =
mMap->rect().width();
545 const double maxY =
mMap->rect().height();
547 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
548 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
550 const double x = intersectionIt->x();
551 const double y = intersectionIt->y();
555 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
556 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
557 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
558 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
559 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
560 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
563 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
564 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
568 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
575void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
577 QgsRectangle crsBoundingRect;
578 QgsCoordinateTransform inverseTr;
579 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
586 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
587 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
594 QList< QgsGeometry > xLines;
595 QList< QgsGeometry > yLines;
596 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
597 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
601 for (
int i = 0; i < gridIt->line.size(); ++i )
603 line.append( QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
612 mTransformedIntersections.clear();
613 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
614 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
616 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
617 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
620 const QgsGeometry intersects = ( *yLineIt ).intersection( ( *xLineIt ) );
621 if ( intersects.
isNull() )
626 QgsPointXY vertex = intersects.
vertexAt( i );
629 mTransformedIntersections << vertex;
637 mTransformDirty =
false;
642 if ( !
mMap || !mEvaluatedEnabled )
646 QPaintDevice *paintDevice = p->device();
653 p->setCompositionMode( mBlendMode );
656 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
657 p->setClipRect( thisPaintRect );
658 if ( thisPaintRect != mPrevPaintRect )
661 mTransformDirty =
true;
662 mPrevPaintRect = thisPaintRect;
666 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
667 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
682 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
684 drawGridCrsTransform( context, dotsPerMM );
691 drawGridNoTransform( context, dotsPerMM );
696 p->setClipping(
false );
700 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
705 updateGridLinesAnnotationsPositions();
712 if ( mShowGridAnnotation )
718void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
720 QList< GridLine >::iterator it = mGridLines.begin();
721 for ( ; it != mGridLines.end(); ++it )
723 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
724 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
725 it->startAnnotation.position = QVector2D( it->line.first() );
726 it->endAnnotation.position = QVector2D( it->line.last() );
727 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
728 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
730 it->startAnnotation.angle = atan2( it->startAnnotation.vector.x() * normS.y() - it->startAnnotation.vector.y() * normS.x(), it->startAnnotation.vector.x() * normS.x() + it->startAnnotation.vector.y() * normS.y() );
732 it->endAnnotation.angle = atan2( it->endAnnotation.vector.x() * normE.y() - it->endAnnotation.vector.y() * normE.x(), it->endAnnotation.vector.x() * normE.x() + it->endAnnotation.vector.y() * normE.y() );
736void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
743 if ( calculateLinesOnly || mGridLines.empty() )
746 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
747 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
749 int countLongitudeLines = 0;
750 int countLatitudeLines = 0;
751 for (
const GridLine &line : mGridLines )
753 switch ( line.coordinateType )
756 countLongitudeLines++;
759 countLatitudeLines++;
764 int latitudeLineIndex = 0;
765 int longitudeLineIndex = 0;
773 for ( ; vIt != mGridLines.constEnd(); ++vIt )
777 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
779 longitudeLineIndex++;
785 drawGridLine( line, context );
788 for ( ; hIt != mGridLines.constEnd(); ++hIt )
792 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
800 drawGridLine( line, context );
806 QPointF intersectionPoint, crossEnd1, crossEnd2;
807 for ( ; vIt != mGridLines.constEnd(); ++vIt )
812 l1 = QLineF( vIt->line.first(), vIt->line.last() );
815 hIt = mGridLines.constBegin();
816 for ( ; hIt != mGridLines.constEnd(); ++hIt )
821 l2 = QLineF( hIt->line.first(), hIt->line.last() );
823 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
828 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
830 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
833 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
837 drawGridMarker( intersectionPoint * dotsPerMM, context );
849 hIt = mGridLines.constBegin();
850 for ( ; hIt != mGridLines.constEnd(); ++hIt )
855 l1 = QLineF( hIt->line.first(), hIt->line.last() );
857 vIt = mGridLines.constBegin();
858 for ( ; vIt != mGridLines.constEnd(); ++vIt )
863 l2 = QLineF( vIt->line.first(), vIt->line.last() );
865 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
868 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
870 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
873 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
880void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
889 switch ( mGridFrameStyle )
893 drawGridFrameZebra( p, extension );
898 drawGridFrameTicks( p, extension );
903 drawGridFrameLine( p, extension );
914void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
917 poly << line.p1() << line.p2();
918 drawGridLine( poly, context );
921void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
923 if ( !
mMap || !
mMap->layout() || !mGridLineSymbol )
928 mGridLineSymbol->startRender( context );
929 mGridLineSymbol->renderPolyline( line,
nullptr, context );
930 mGridLineSymbol->stopRender( context );
933void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
935 if ( !
mMap || !
mMap->layout() || !mGridMarkerSymbol )
940 mGridMarkerSymbol->startRender( context );
941 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
942 mGridMarkerSymbol->stopRender( context );
945void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
965void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
Qgis::MapGridBorderSide border,
double *extension )
const
974 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
978 double currentCoord = 0.0;
985 bool drawTLBox =
false;
986 bool drawTRBox =
false;
987 bool drawBLBox =
false;
988 bool drawBRBox =
false;
990 QMap< double, double > pos = QMap< double, double >();
991 QList< GridLine >::const_iterator it = mGridLines.constBegin();
992 for ( ; it != mGridLines.constEnd(); ++it )
995 for (
int i = 0 ; i < 2 ; ++i )
997 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1000 if ( annot.border != border )
1003 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1007 pos.insert( annot.position.y(), it->coordinate );
1009 pos.insert( annot.position.x(), it->coordinate );
1016 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
1032 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
1036 QPen framePen = QPen( mGridFramePenColor );
1037 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1038 framePen.setJoinStyle( Qt::MiterJoin );
1039 p->setPen( framePen );
1041 QMap< double, double >::const_iterator posIt = pos.constBegin();
1042 for ( ; posIt != pos.constEnd(); ++posIt )
1044 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1047 height = posIt.key() - currentCoord;
1048 width = mEvaluatedGridFrameWidth;
1054 height = mEvaluatedGridFrameWidth;
1055 width = posIt.key() - currentCoord;
1057 y = ( border ==
Qgis::MapGridBorderSide::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
1059 p->drawRect( QRectF( x, y, width, height ) );
1060 currentCoord = posIt.key();
1067 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) ;
1068 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1070 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1072 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1074 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1076 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1080void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1090 QPen framePen = QPen( mGridFramePenColor );
1091 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1092 framePen.setCapStyle( Qt::FlatCap );
1093 p->setBrush( Qt::NoBrush );
1094 p->setPen( framePen );
1097 QList< GridLine >::iterator it = mGridLines.begin();
1098 for ( ; it != mGridLines.end(); ++it )
1101 for (
int i = 0 ; i < 2 ; ++i )
1103 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1105 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1109 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1117 facingLeft = ( annot.angle != 0 );
1118 facingRight = ( annot.angle != 0 );
1122 facingLeft = ( annot.angle > 0 );
1123 facingRight = ( annot.angle < 0 );
1127 facingLeft = ( annot.angle < 0 );
1128 facingRight = ( annot.angle > 0 );
1132 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1135 ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1138 ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1141 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1145 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1147 double fA = mEvaluatedGridFrameMargin;
1148 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1152 fA /= QVector2D::dotProduct( vector, normalVector );
1153 fB /= QVector2D::dotProduct( vector, normalVector );
1160 extension->UpdateBorder( annot.border, fB );
1168 pA = annot.position + fA * vector;
1169 pB = annot.position + fB * vector;
1173 pA = annot.position - fA * vector;
1174 pB = annot.position - fB * vector;
1178 pA = annot.position - fB * vector;
1179 pB = annot.position + ( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1181 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1187void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1197 QPen framePen = QPen( mGridFramePenColor );
1198 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1199 framePen.setCapStyle( Qt::SquareCap );
1200 p->setBrush( Qt::NoBrush );
1201 p->setPen( framePen );
1211 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1219 p->drawLine( QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1227 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1235 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1238 if ( ! extension && drawDiagonals )
1243 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1244 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1245 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1250 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1251 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1252 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1257 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1258 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1259 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1264 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1265 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1266 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1272 GridExtension *extension )
const
1274 if ( mGridLines.empty() )
1277 QString currentAnnotationString;
1278 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1280 QgsExpressionContextScope *gridScope =
new QgsExpressionContextScope();
1281 QgsExpressionContextScopePopper scopePopper( expressionContext, gridScope );
1283 bool geographic =
false;
1284 if ( mCRS.isValid() )
1286 geographic = mCRS.isGeographic();
1290 geographic =
mMap->crs().isGeographic();
1296 int countLongitudeLines = 0;
1297 int countLatitudeLines = 0;
1298 for (
const GridLine &line : mGridLines )
1300 switch ( line.coordinateType )
1303 countLongitudeLines++;
1306 countLatitudeLines++;
1311 int latitudeLineIndex = 0;
1312 int longitudeLineIndex = 0;
1313 for ( ; it != mGridLines.constEnd(); ++it )
1315 double value = it->coordinate;
1316 switch ( it->coordinateType )
1319 longitudeLineIndex++;
1320 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLongitudeLines,
true ) );
1321 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, longitudeLineIndex,
true ) );
1322 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"x"_s,
true ) );
1326 latitudeLineIndex++;
1327 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_count"_s, countLatitudeLines,
true ) );
1328 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_index"_s, latitudeLineIndex,
true ) );
1329 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_axis"_s, u
"y"_s,
true ) );
1336 const double wrappedX = std::fmod( value, 360.0 );
1337 if ( wrappedX > 180.0 )
1339 value = wrappedX - 360.0;
1341 else if ( wrappedX < -180.0 )
1343 value = wrappedX + 360.0;
1347 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"grid_number"_s, value,
true ) );
1349 if ( mDrawAnnotationProperty )
1352 const bool display = mDrawAnnotationProperty->valueAsBool( expressionContext,
true, &ok );
1353 if ( ok && !display )
1356 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext, geographic );
1357 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1358 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1362void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
QgsRenderContext &context, GridLineAnnotation annot,
const QString &annotationString,
const Qgis::MapGridAnnotationType coordinateType, GridExtension *extension )
const
1369 if ( ! shouldShowAnnotationForSide( coordinateType, annot.border ) )
1373 std::unique_ptr< QgsScopedQPainterState > painterState;
1374 double dotsPerMM = 1;
1378 painterState = std::make_unique< QgsScopedQPainterState >( context.
painter() );
1379 dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
1380 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1391 double textWidthPainterUnits = sizePainterUnits.width();
1393 textWidthPainterUnits *= 1.1;
1395 const double textWidthMM = textWidthPainterUnits * painterUnitsToMM ;
1397 double textHeightPainterUnits = 0;
1398 if ( extension || doc.
size() > 1 )
1400 textHeightPainterUnits = sizePainterUnits.height();
1409 const double textHeightMM = textHeightPainterUnits * painterUnitsToMM;
1416 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1420 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1423 double distanceToFrameMM = mEvaluatedAnnotationFrameDistance;
1431 distanceToFrameMM += mEvaluatedGridFrameWidth;
1432 if ( hasBorderWidth )
1433 distanceToFrameMM += mEvaluatedGridFrameLineThickness / 2.0;
1436 distanceToFrameMM *= -1;
1440 distanceToFrameMM /= QVector2D::dotProduct( vector, normalVector );
1443 const QVector2D annotationPositionMM = annot.position +
static_cast< float >( distanceToFrameMM ) * vector;
1456 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1458 if ( rotation <= -90 || rotation > 90 )
1461 anchorMM.setX( outside ? 0 : textWidthMM );
1465 anchorMM.setX( outside ? textWidthMM : 0 );
1469 anchorMM.setY( 0.5 * textHeightMM );
1471 anchorMM.setY( -1.5 * textHeightMM );
1473 anchorMM.setY( -0.5 * textHeightMM );
1479 anchorMM.setX( 0.5 * textWidthMM );
1480 anchorMM.setY( -0.5 * textHeightMM );
1482 anchorMM.setY( outside ? 0 : -textHeightMM );
1484 anchorMM.setX( outside ? 0 : textWidthMM );
1486 anchorMM.setY( outside ? -textHeightMM : 0 );
1488 anchorMM.setX( outside ? textWidthMM : 0 );
1493 anchorMM.setX( 0.5 * textWidthMM );
1494 anchorMM.setY( -0.5 * textHeightMM );
1496 anchorMM.setX( outside ? 0 : textWidthMM );
1498 anchorMM.setY( outside ? -textHeightMM : 0 );
1500 anchorMM.setX( outside ? textWidthMM : 0 );
1502 anchorMM.setY( outside ? 0 : -textHeightMM );
1507 anchorMM.setX( 0.5 * textWidthMM );
1508 anchorMM.setY( -0.5 * textHeightMM );
1510 anchorMM.setX( outside ? textWidthMM : 0 );
1512 anchorMM.setY( outside ? 0 : -textHeightMM );
1514 anchorMM.setX( outside ? 0 : textWidthMM );
1516 anchorMM.setY( outside ? -textHeightMM : 0 );
1521 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1522 anchorMM.setX( 0.5 * textWidthMM );
1524 anchorMM.setY( -textHeightMM );
1532 extension->UpdateBorder( frameBorder, -distanceToFrameMM + textWidthMM );
1534 extension->UpdateAll( textWidthMM / 2.0 );
1537 if ( extension || !context.
painter() )
1541 bool facingLeft = ( annot.angle < 0 );
1542 bool facingRight = ( annot.angle > 0 );
1545 facingLeft = !facingLeft;
1546 facingRight = !facingRight;
1549 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
1552 ( facingRight && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ) )
1555 ( facingRight && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ) )
1558 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
1561 context.
painter()->translate( QPointF( annotationPositionMM .x(), annotationPositionMM .y() ) / painterUnitsToMM );
1562 context.
painter()->rotate( rotation );
1563 context.
painter()->translate( -anchorMM / painterUnitsToMM );
1573 return QString::number( value,
'f', mGridAnnotationPrecision );
1579 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1583 if ( !isGeographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1585 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1591 if ( !isGeographic || coordRounded != 0.0 )
1593 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1599 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1603 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1608 if ( !mGridAnnotationExpression )
1610 mGridAnnotationExpression = std::make_unique<QgsExpression>( mGridAnnotationExpressionString );
1611 mGridAnnotationExpression->prepare( &expressionContext );
1613 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1618 switch ( mGridAnnotationFormat )
1668int QgsLayoutItemMapGrid::xGridLines()
const
1670 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1676 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1677 QRectF mapBoundingRect = mapPolygon.boundingRect();
1678 double gridIntervalY = mEvaluatedIntervalY;
1679 double gridOffsetY = mEvaluatedOffsetY;
1680 double annotationScale = 1.0;
1681 switch ( mGridUnit )
1686 mapBoundingRect =
mMap->rect();
1687 mapPolygon = QPolygonF(
mMap->rect() );
1690 annotationScale = 0.1;
1691 gridIntervalY *= 10;
1703 const double roundCorrection = mapBoundingRect.top() > gridOffsetY ? 1.0 : 0.0;
1704 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1706 int gridLineCount = 0;
1711 double yCanvasCoord;
1712 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1714 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1716 newLine.coordinate = currentLevel * annotationScale;
1718 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1719 mGridLines.append( newLine );
1720 currentLevel += gridIntervalY;
1727 QVector<QLineF> borderLines;
1728 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1729 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1730 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1731 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1733 QVector<QPointF> intersectionList;
1735 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1737 intersectionList.clear();
1738 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1740 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1741 for ( ; it != borderLines.constEnd(); ++it )
1743 QPointF intersectionPoint;
1744 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1746 intersectionList.push_back( intersectionPoint );
1747 if ( intersectionList.size() >= 2 )
1754 if ( intersectionList.size() >= 2 )
1757 newLine.coordinate = currentLevel;
1759 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1760 mGridLines.append( newLine );
1763 currentLevel += gridIntervalY;
1770int QgsLayoutItemMapGrid::yGridLines()
const
1772 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1777 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1778 QRectF mapBoundingRect = mapPolygon.boundingRect();
1779 double gridIntervalX = mEvaluatedIntervalX;
1780 double gridOffsetX = mEvaluatedOffsetX;
1781 double annotationScale = 1.0;
1782 switch ( mGridUnit )
1787 mapBoundingRect =
mMap->rect();
1788 mapPolygon = QPolygonF(
mMap->rect() );
1791 annotationScale = 0.1;
1792 gridIntervalX *= 10;
1804 const double roundCorrection = mapBoundingRect.left() > gridOffsetX ? 1.0 : 0.0;
1805 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1807 int gridLineCount = 0;
1811 double xCanvasCoord;
1812 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1814 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1817 newLine.coordinate = currentLevel * annotationScale;
1819 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
1820 mGridLines.append( newLine );
1821 currentLevel += gridIntervalX;
1828 QVector<QLineF> borderLines;
1829 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1830 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1831 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1832 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1834 QVector<QPointF> intersectionList;
1836 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1838 intersectionList.clear();
1839 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1841 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1842 for ( ; it != borderLines.constEnd(); ++it )
1844 QPointF intersectionPoint;
1845 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1847 intersectionList.push_back( intersectionPoint );
1848 if ( intersectionList.size() >= 2 )
1855 if ( intersectionList.size() >= 2 )
1858 newLine.coordinate = currentLevel;
1860 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1861 mGridLines.append( newLine );
1864 currentLevel += gridIntervalX;
1872 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1877 const double roundCorrection = bbox.
yMaximum() > mEvaluatedOffsetY ? 1.0 : 0.0;
1878 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
1880 const double minX = bbox.
xMinimum();
1881 const double maxX = bbox.
xMaximum();
1882 double step = ( maxX - minX ) / 20;
1884 bool crosses180 =
false;
1885 bool crossed180 =
false;
1886 if ( mCRS.isGeographic() && ( minX > maxX ) )
1890 step = ( maxX + 360.0 - minX ) / 20;
1896 int gridLineCount = 0;
1900 double currentX = minX;
1904 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
1911 const QgsPointXY mapPoint = t.
transform( currentX, currentLevel );
1912 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
1914 catch ( QgsCsException &cse )
1921 if ( crosses180 && currentX > 180.0 )
1929 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
1930 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1931 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1933 if ( !( *lineIt ).isEmpty() )
1936 newLine.coordinate = currentLevel;
1938 newLine.line = QPolygonF( *lineIt );
1939 mGridLines.append( newLine );
1943 currentLevel -= mEvaluatedIntervalY;
1951 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1956 const double roundCorrection = bbox.
xMinimum() > mEvaluatedOffsetX ? 1.0 : 0.0;
1957 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
1959 const double minY = bbox.
yMinimum();
1960 const double maxY = bbox.
yMaximum();
1961 const double step = ( maxY - minY ) / 20;
1966 bool crosses180 =
false;
1967 bool crossed180 =
false;
1974 int gridLineCount = 0;
1975 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
1978 double currentY = minY;
1982 if ( currentY > maxY )
1989 const QgsPointXY mapPoint = t.
transform( currentLevel, currentY );
1991 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
1993 catch ( QgsCsException &cse )
2002 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
2003 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
2004 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
2006 if ( !( *lineIt ).isEmpty() )
2009 newLine.coordinate = currentLevel;
2011 newLine.line = QPolygonF( *lineIt );
2012 mGridLines.append( newLine );
2016 currentLevel += mEvaluatedIntervalX;
2017 if ( crosses180 && currentLevel > 180.0 )
2019 currentLevel -= 360.0;
2048 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
2050 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
2052 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
2054 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
2068 if ( ddValue.compare(
"x_only"_L1, Qt::CaseInsensitive ) == 0 )
2070 else if ( ddValue.compare(
"y_only"_L1, Qt::CaseInsensitive ) == 0 )
2072 else if ( ddValue.compare(
"disabled"_L1, Qt::CaseInsensitive ) == 0 )
2074 else if ( ddValue.compare(
"all"_L1, Qt::CaseInsensitive ) == 0 )
2080void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
2085 mTransformDirty = mTransformDirty
2098 mDrawAnnotationProperty->prepare( context );
2102 mDrawAnnotationProperty.reset();
2106 switch ( mGridUnit )
2119 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
2121 mEvaluatedEnabled =
false;
2126 const double mapWidthMapUnits = mapWidth();
2127 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2128 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2130 mEvaluatedIntervalX = interval;
2131 mEvaluatedIntervalY = interval;
2132 mTransformDirty =
true;
2154double QgsLayoutItemMapGrid::mapWidth()
const
2161 const QgsRectangle mapExtent =
mMap->extent();
2165 return mapExtent.
width();
2182 catch ( QgsCsException & )
2185 QgsDebugError( u
"An error occurred while calculating length"_s );
2191bool sortByDistance( QPair<qreal, Qgis::MapGridBorderSide> a, QPair<qreal, Qgis::MapGridBorderSide> b )
2193 return a.first < b.first;
2203 const double tolerance = std::max(
mMap->frameEnabled() ?
mMap->pen().widthF() : 0.0, 1.0 );
2206 if ( ( p.y() <= tolerance && p.x() <= tolerance )
2207 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2208 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2209 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2215 if ( p.x() <= tolerance )
2226 if ( p.y() <= tolerance )
2238 QList< QPair<qreal, Qgis::MapGridBorderSide > > distanceToSide;
2244 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2245 return distanceToSide.at( 0 ).second;
2250 mGridLineSymbol.reset( symbol );
2255 return mGridLineSymbol.get();
2260 return mGridLineSymbol.get();
2265 mGridMarkerSymbol.reset( symbol );
2270 return mGridMarkerSymbol.get();
2275 return mGridMarkerSymbol.get();
2280 mAnnotationFormat.setFont( font );
2281 if ( font.pointSizeF() > 0 )
2283 mAnnotationFormat.setSize( font.pointSizeF() );
2286 else if ( font.pixelSize() > 0 )
2288 mAnnotationFormat.setSize( font.pixelSize() );
2295 return mAnnotationFormat.toQFont();
2300 mAnnotationFormat.
setColor( color );
2305 return mAnnotationFormat.color();
2313 mLeftGridAnnotationDisplay = display;
2316 mRightGridAnnotationDisplay = display;
2319 mTopGridAnnotationDisplay = display;
2322 mBottomGridAnnotationDisplay = display;
2326 refreshDataDefinedProperties();
2330 mMap->updateBoundingRect();
2340 return mLeftGridAnnotationDisplay;
2342 return mRightGridAnnotationDisplay;
2344 return mTopGridAnnotationDisplay;
2346 return mBottomGridAnnotationDisplay;
2348 return mBottomGridAnnotationDisplay;
2355 double bottom = 0.0;
2358 return std::max( std::max( std::max( top, right ), bottom ), left );
2368 if ( !
mMap || !mEvaluatedEnabled )
2378 GridExtension extension;
2381 switch ( mGridUnit )
2386 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
2388 drawGridCrsTransform( context, 0,
true );
2395 drawGridNoTransform( context, 0,
true );
2400 updateGridLinesAnnotationsPositions();
2404 drawGridFrame(
nullptr, &extension );
2407 if ( mShowGridAnnotation )
2412 top = extension.top;
2413 right = extension.right;
2414 bottom = extension.bottom;
2415 left = extension.left;
2421 refreshDataDefinedProperties();
2426 if ( unit == mGridUnit )
2431 mTransformDirty =
true;
2440 mGridIntervalX = interval;
2441 mTransformDirty =
true;
2442 refreshDataDefinedProperties();
2451 mGridIntervalY = interval;
2452 mTransformDirty =
true;
2453 refreshDataDefinedProperties();
2462 mGridOffsetX = offset;
2463 mTransformDirty =
true;
2464 refreshDataDefinedProperties();
2473 mGridOffsetY = offset;
2474 mTransformDirty =
true;
2475 refreshDataDefinedProperties();
2484 mMinimumIntervalWidth = minWidth;
2485 mTransformDirty =
true;
2486 refreshDataDefinedProperties();
2495 mMaximumIntervalWidth = maxWidth;
2496 mTransformDirty =
true;
2497 refreshDataDefinedProperties();
2502 if (
style == mGridStyle )
2507 mTransformDirty =
true;
2512 mCrossLength = length;
2513 refreshDataDefinedProperties();
2521 mLeftGridAnnotationDirection = direction;
2524 mRightGridAnnotationDirection = direction;
2527 mTopGridAnnotationDirection = direction;
2530 mBottomGridAnnotationDirection = direction;
2536 mMap->updateBoundingRect();
2543 mGridFrameSides = flags;
2548 mGridFrameSides.setFlag( flag, on );
2553 return mGridFrameSides;
2568 if ( mGridLineSymbol )
2574 if ( mGridMarkerSymbol )
2586 mTransformDirty =
true;
2587 refreshDataDefinedProperties();
2588 mMap->updateBoundingRect();
2594 return mGridFrameSides.testFlag( flag );
2599 mGridFrameWidth = width;
2600 refreshDataDefinedProperties();
2605 mGridFrameMargin = margin;
2606 refreshDataDefinedProperties();
2611 mGridFramePenThickness = width;
2612 refreshDataDefinedProperties();
2617 mLeftGridAnnotationDirection = direction;
2618 mRightGridAnnotationDirection = direction;
2619 mTopGridAnnotationDirection = direction;
2620 mBottomGridAnnotationDirection = direction;
2628 mLeftGridAnnotationPosition = position;
2631 mRightGridAnnotationPosition = position;
2634 mTopGridAnnotationPosition = position;
2637 mBottomGridAnnotationPosition = position;
2643 mMap->updateBoundingRect();
2653 return mLeftGridAnnotationPosition;
2655 return mRightGridAnnotationPosition;
2657 return mTopGridAnnotationPosition;
2659 return mBottomGridAnnotationPosition;
2661 return mLeftGridAnnotationPosition;
2666 mAnnotationFrameDistance = distance;
2667 refreshDataDefinedProperties();
2674 return mLeftGridAnnotationDirection;
2680 return mLeftGridAnnotationDirection;
2682 return mRightGridAnnotationDirection;
2684 return mTopGridAnnotationDirection;
2686 return mBottomGridAnnotationDirection;
2688 return mLeftGridAnnotationDirection;
2693 mGridAnnotationExpressionString = expression;
2694 mGridAnnotationExpression.reset();
2702 mLeftFrameDivisions = divisions;
2705 mRightFrameDivisions = divisions;
2708 mTopFrameDivisions = divisions;
2711 mBottomFrameDivisions = divisions;
2715 refreshDataDefinedProperties();
2728 return mLeftFrameDivisions;
2730 return mRightFrameDivisions;
2732 return mTopFrameDivisions;
2734 return mBottomFrameDivisions;
2736 return mLeftFrameDivisions;
2748 const QgsCoordinateTransform tr(
mMap->crs(), mCRS,
mLayout->project() );
2749 QgsCoordinateTransform extentTransform = tr;
2751 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
2752 const QRectF mbr = mapPolygon.boundingRect();
2753 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2756 if ( mCRS.isGeographic() )
2759 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2760 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2762 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2763 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2765 if ( lowerLeft.x() > upperRight.x() )
2781 inverseTransform = QgsCoordinateTransform( mCRS,
mMap->crs(),
mLayout->project() );
2783 catch ( QgsCsException &cse )
2792QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2797 const QgsGeometry intersected = lineGeom.
intersection( rectGeom );
2800 QList<QPolygonF> trimmedLines;
2801 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2802 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2804 trimmedLines << ( *geomIt ).asQPolygonF();
2806 return trimmedLines;
2881 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.
@ AboveTick
Draw annotations parallel to tick (above the line).
@ OnTick
Draw annotations parallel to tick (on the line).
@ Horizontal
Draw annotations horizontally.
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.
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.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
QList< QgsLayoutItemMapGrid * > asList() const
Returns a list of QgsLayoutItemMapGrids contained by the stack.
void calculateMaxGridExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void removeGrid(const QString &gridId)
Removes a grid with matching gridId from the stack and deletes the corresponding QgsLayoutItemMapGrid...
double maxGridExtension() const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void addGrid(QgsLayoutItemMapGrid *grid)
Adds a new map grid to the stack and takes ownership of the grid.
QgsLayoutItemMapGrid * grid(const QString &gridId) const
Returns a reference to a grid with matching gridId within the stack.
bool readXml(const QDomElement &elem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets the item stack's state from a DOM document, where element is a DOM node corresponding to a 'Layo...
QgsLayoutItemMapGrid & operator[](int index)
Returns a reference to a grid at the specified index within the stack.
void moveGridUp(const QString &gridId)
Moves a grid with matching gridId up the stack, causing it to be rendered above other grids.
void moveGridDown(const QString &gridId)
Moves a grid with matching gridId down the stack, causing it to be rendered below other grids.
QgsLayoutItemMapGridStack(QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGridStack, attached to the specified map.
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
void setFrameSideFlags(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.
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].
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.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
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.