50#include "moc_qgslayoutitemmapgrid.cpp"
52#define MAX_GRID_LINES 1000
83 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
89 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
94 QList< QgsLayoutItemMapGrid * > list;
117 const QDomNodeList mapGridNodeList = elem.elementsByTagName( QStringLiteral(
"ComposerMapGrid" ) );
118 for (
int i = 0; i < mapGridNodeList.size(); ++i )
120 const QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
122 mapGrid->
readXml( mapGridElem, doc, context );
136 return std::max( std::max( std::max( top, right ), bottom ), left );
150 double gridTop = 0.0;
151 double gridRight = 0.0;
152 double gridBottom = 0.0;
153 double gridLeft = 0.0;
154 grid->calculateMaxExtension( gridTop, gridRight, gridBottom, gridLeft );
155 top = std::max( top, gridTop );
156 right = std::max( right, gridRight );
157 bottom = std::max( bottom, gridBottom );
158 left = std::max( left, gridLeft );
174 return QVector2D( 0, 1 );
176 return QVector2D( -1, 0 );
178 return QVector2D( 0, -1 );
180 return QVector2D( 1, 0 );
188 return QVector2D( borderVector.y(), -borderVector.x() );
198 const QString defaultFontString = settings.
value( QStringLiteral(
"LayoutDesigner/defaultFont" ), QVariant(),
QgsSettings::Gui ).toString();
199 if ( !defaultFontString.isEmpty() )
202 QgsFontUtils::setFontFamily( font, defaultFontString );
203 mAnnotationFormat.setFont( font );
206 createDefaultGridLineSymbol();
207 createDefaultGridMarkerSymbol();
213 if ( !mCRS.isValid() )
220void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
222 QVariantMap properties;
223 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
224 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
225 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"flat" ) );
229void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
231 QVariantMap properties;
232 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"circle" ) );
233 properties.insert( QStringLiteral(
"size" ), QStringLiteral(
"2.0" ) );
234 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
240 if ( mGridLineSymbol )
242 mGridLineSymbol->setWidth( width );
248 if ( mGridLineSymbol )
250 mGridLineSymbol->setColor(
c );
261 QDomElement mapGridElem = doc.createElement( QStringLiteral(
"ComposerMapGrid" ) );
262 mapGridElem.setAttribute( QStringLiteral(
"gridStyle" ), mGridStyle );
263 mapGridElem.setAttribute( QStringLiteral(
"intervalX" ),
qgsDoubleToString( mGridIntervalX ) );
264 mapGridElem.setAttribute( QStringLiteral(
"intervalY" ),
qgsDoubleToString( mGridIntervalY ) );
265 mapGridElem.setAttribute( QStringLiteral(
"offsetX" ),
qgsDoubleToString( mGridOffsetX ) );
266 mapGridElem.setAttribute( QStringLiteral(
"offsetY" ),
qgsDoubleToString( mGridOffsetY ) );
267 mapGridElem.setAttribute( QStringLiteral(
"crossLength" ),
qgsDoubleToString( mCrossLength ) );
269 QDomElement lineStyleElem = doc.createElement( QStringLiteral(
"lineStyle" ) );
271 lineStyleElem.appendChild( gridLineStyleElem );
272 mapGridElem.appendChild( lineStyleElem );
274 QDomElement markerStyleElem = doc.createElement( QStringLiteral(
"markerStyle" ) );
276 markerStyleElem.appendChild( gridMarkerStyleElem );
277 mapGridElem.appendChild( markerStyleElem );
279 mapGridElem.setAttribute( QStringLiteral(
"gridFrameStyle" ), mGridFrameStyle );
280 mapGridElem.setAttribute( QStringLiteral(
"gridFrameSideFlags" ), mGridFrameSides );
281 mapGridElem.setAttribute( QStringLiteral(
"gridFrameWidth" ),
qgsDoubleToString( mGridFrameWidth ) );
282 mapGridElem.setAttribute( QStringLiteral(
"gridFrameMargin" ),
qgsDoubleToString( mGridFrameMargin ) );
283 mapGridElem.setAttribute( QStringLiteral(
"gridFramePenThickness" ),
qgsDoubleToString( mGridFramePenThickness ) );
287 mapGridElem.setAttribute( QStringLiteral(
"leftFrameDivisions" ), mLeftFrameDivisions );
288 mapGridElem.setAttribute( QStringLiteral(
"rightFrameDivisions" ), mRightFrameDivisions );
289 mapGridElem.setAttribute( QStringLiteral(
"topFrameDivisions" ), mTopFrameDivisions );
290 mapGridElem.setAttribute( QStringLiteral(
"bottomFrameDivisions" ), mBottomFrameDivisions );
291 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksLengthMode" ), mRotatedTicksLengthMode );
292 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksEnabled" ), mRotatedTicksEnabled );
293 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksMinimumAngle" ), QString::number( mRotatedTicksMinimumAngle ) );
294 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksMarginToCorner" ), QString::number( mRotatedTicksMarginToCorner ) );
295 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsLengthMode" ), mRotatedAnnotationsLengthMode );
296 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsEnabled" ), mRotatedAnnotationsEnabled );
297 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsMinimumAngle" ), QString::number( mRotatedAnnotationsMinimumAngle ) );
298 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsMarginToCorner" ), QString::number( mRotatedAnnotationsMarginToCorner ) );
299 if ( mCRS.isValid() )
301 mCRS.writeXml( mapGridElem, doc );
304 mapGridElem.setAttribute( QStringLiteral(
"annotationFormat" ), mGridAnnotationFormat );
305 mapGridElem.setAttribute( QStringLiteral(
"showAnnotation" ), mShowGridAnnotation );
306 mapGridElem.setAttribute( QStringLiteral(
"annotationExpression" ), mGridAnnotationExpressionString );
307 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDisplay" ), mLeftGridAnnotationDisplay );
308 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDisplay" ), mRightGridAnnotationDisplay );
309 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDisplay" ), mTopGridAnnotationDisplay );
310 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDisplay" ), mBottomGridAnnotationDisplay );
311 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationPosition" ), mLeftGridAnnotationPosition );
312 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationPosition" ), mRightGridAnnotationPosition );
313 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationPosition" ), mTopGridAnnotationPosition );
314 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationPosition" ), mBottomGridAnnotationPosition );
315 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDirection" ), mLeftGridAnnotationDirection );
316 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDirection" ), mRightGridAnnotationDirection );
317 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDirection" ), mTopGridAnnotationDirection );
318 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDirection" ), mBottomGridAnnotationDirection );
319 mapGridElem.setAttribute( QStringLiteral(
"frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) );
320 mapGridElem.appendChild( mAnnotationFormat.writeXml( doc, context ) );
321 mapGridElem.setAttribute( QStringLiteral(
"annotationPrecision" ), mGridAnnotationPrecision );
322 mapGridElem.setAttribute( QStringLiteral(
"unit" ), mGridUnit );
323 mapGridElem.setAttribute( QStringLiteral(
"blendMode" ), mBlendMode );
324 mapGridElem.setAttribute( QStringLiteral(
"minimumIntervalWidth" ), QString::number( mMinimumIntervalWidth ) );
325 mapGridElem.setAttribute( QStringLiteral(
"maximumIntervalWidth" ), QString::number( mMaximumIntervalWidth ) );
328 elem.appendChild( mapGridElem );
335 if ( itemElem.isNull() )
344 mGridIntervalX = itemElem.attribute( QStringLiteral(
"intervalX" ), QStringLiteral(
"0" ) ).toDouble();
345 mGridIntervalY = itemElem.attribute( QStringLiteral(
"intervalY" ), QStringLiteral(
"0" ) ).toDouble();
346 mGridOffsetX = itemElem.attribute( QStringLiteral(
"offsetX" ), QStringLiteral(
"0" ) ).toDouble();
347 mGridOffsetY = itemElem.attribute( QStringLiteral(
"offsetY" ), QStringLiteral(
"0" ) ).toDouble();
348 mCrossLength = itemElem.attribute( QStringLiteral(
"crossLength" ), QStringLiteral(
"3" ) ).toDouble();
349 mGridFrameStyle =
static_cast< QgsLayoutItemMapGrid::FrameStyle >( itemElem.attribute( QStringLiteral(
"gridFrameStyle" ), QStringLiteral(
"0" ) ).toInt() );
351 mGridFrameWidth = itemElem.attribute( QStringLiteral(
"gridFrameWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
352 mGridFrameMargin = itemElem.attribute( QStringLiteral(
"gridFrameMargin" ), QStringLiteral(
"0.0" ) ).toDouble();
353 mGridFramePenThickness = itemElem.attribute( QStringLiteral(
"gridFramePenThickness" ), QStringLiteral(
"0.3" ) ).toDouble();
355 mGridFrameFillColor1 =
QgsColorUtils::colorFromString( itemElem.attribute( QStringLiteral(
"frameFillColor1" ), QStringLiteral(
"255,255,255,255" ) ) );
356 mGridFrameFillColor2 =
QgsColorUtils::colorFromString( itemElem.attribute( QStringLiteral(
"frameFillColor2" ), QStringLiteral(
"0,0,0,255" ) ) );
361 mRotatedTicksLengthMode =
TickLengthMode( itemElem.attribute( QStringLiteral(
"rotatedTicksLengthMode" ), QStringLiteral(
"0" ) ).toInt() );
362 mRotatedTicksEnabled = itemElem.attribute( QStringLiteral(
"rotatedTicksEnabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
363 mRotatedTicksMinimumAngle = itemElem.attribute( QStringLiteral(
"rotatedTicksMinimumAngle" ), QStringLiteral(
"0" ) ).toDouble();
364 mRotatedTicksMarginToCorner = itemElem.attribute( QStringLiteral(
"rotatedTicksMarginToCorner" ), QStringLiteral(
"0" ) ).toDouble();
365 mRotatedAnnotationsLengthMode =
TickLengthMode( itemElem.attribute( QStringLiteral(
"rotatedAnnotationsLengthMode" ), QStringLiteral(
"0" ) ).toInt() );
366 mRotatedAnnotationsEnabled = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsEnabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
367 mRotatedAnnotationsMinimumAngle = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsMinimumAngle" ), QStringLiteral(
"0" ) ).toDouble();
368 mRotatedAnnotationsMarginToCorner = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsMarginToCorner" ), QStringLiteral(
"0" ) ).toDouble();
370 const QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral(
"lineStyle" ) );
371 if ( !lineStyleElem.isNull() )
373 const QDomElement symbolElem = lineStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
374 if ( !symbolElem.isNull() )
383 mGridLineSymbol->setWidth( itemElem.attribute( QStringLiteral(
"penWidth" ), QStringLiteral(
"0" ) ).toDouble() );
384 mGridLineSymbol->setColor( QColor( itemElem.attribute( QStringLiteral(
"penColorRed" ), QStringLiteral(
"0" ) ).toInt(),
385 itemElem.attribute( QStringLiteral(
"penColorGreen" ), QStringLiteral(
"0" ) ).toInt(),
386 itemElem.attribute( QStringLiteral(
"penColorBlue" ), QStringLiteral(
"0" ) ).toInt() ) );
389 const QDomElement markerStyleElem = itemElem.firstChildElement( QStringLiteral(
"markerStyle" ) );
390 if ( !markerStyleElem.isNull() )
392 const QDomElement symbolElem = markerStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
393 if ( !symbolElem.isNull() )
399 if ( !mCRS.readXml( itemElem ) )
402 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( QStringLiteral(
"blendMode" ), QStringLiteral(
"0" ) ).toUInt() );
405 mShowGridAnnotation = ( itemElem.attribute( QStringLiteral(
"showAnnotation" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
407 mGridAnnotationExpressionString = itemElem.attribute( QStringLiteral(
"annotationExpression" ) );
408 mGridAnnotationExpression.reset();
413 mLeftGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"leftAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
414 mRightGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"rightAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
416 mBottomGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"bottomAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
422 mAnnotationFrameDistance = itemElem.attribute( QStringLiteral(
"frameAnnotationDistance" ), QStringLiteral(
"0" ) ).toDouble();
424 if ( !itemElem.firstChildElement(
"text-style" ).isNull() )
426 mAnnotationFormat.readXml( itemElem, context );
433 font.fromString( itemElem.attribute(
"annotationFont", QString() ) );
435 mAnnotationFormat.setFont( font );
436 mAnnotationFormat.setSize( font.pointSizeF() );
441 mGridAnnotationPrecision = itemElem.attribute( QStringLiteral(
"annotationPrecision" ), QStringLiteral(
"3" ) ).toInt();
442 const int gridUnitInt = itemElem.attribute( QStringLiteral(
"unit" ), QString::number(
MapUnit ) ).toInt();
444 mMinimumIntervalWidth = itemElem.attribute( QStringLiteral(
"minimumIntervalWidth" ), QStringLiteral(
"50" ) ).toDouble();
445 mMaximumIntervalWidth = itemElem.attribute( QStringLiteral(
"maximumIntervalWidth" ), QStringLiteral(
"100" ) ).toDouble();
447 refreshDataDefinedProperties();
457 mTransformDirty =
true;
463 return mBlendMode != QPainter::CompositionMode_SourceOver;
466QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
468 const QTransform t = QTransform::fromScale( scale, scale );
469 return t.map( polygon );
472void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
474 if ( !
mMap || !mEvaluatedEnabled )
480 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
481 if ( mapPolygon != mPrevMapPolygon )
483 mTransformDirty =
true;
484 mPrevMapPolygon = mapPolygon;
487 if ( mTransformDirty )
489 calculateCrsTransformLines();
493 if ( !calculateLinesOnly )
495 int countLongitudeLines = 0;
496 int countLatitudeLines = 0;
497 for (
const GridLine &line : mGridLines )
499 switch ( line.coordinateType )
502 countLongitudeLines++;
505 countLatitudeLines++;
510 int latitudeLineIndex = 0;
511 int longitudeLineIndex = 0;
514 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
515 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
517 switch ( gridIt->coordinateType )
520 longitudeLineIndex++;
534 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
539 const double maxX =
mMap->rect().width();
540 const double maxY =
mMap->rect().height();
542 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
543 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
545 const double x = intersectionIt->x();
546 const double y = intersectionIt->y();
550 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
551 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
552 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
553 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
554 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
555 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
558 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
559 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
563 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
570void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
572 QgsRectangle crsBoundingRect;
573 QgsCoordinateTransform inverseTr;
574 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
581 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
582 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
589 QList< QgsGeometry > xLines;
590 QList< QgsGeometry > yLines;
591 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
592 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
596 for (
int i = 0; i < gridIt->line.size(); ++i )
598 line.append( QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
607 mTransformedIntersections.clear();
608 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
609 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
611 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
612 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
615 const QgsGeometry intersects = ( *yLineIt ).intersection( ( *xLineIt ) );
616 if ( intersects.
isNull() )
621 QgsPointXY vertex = intersects.
vertexAt( i );
624 mTransformedIntersections << vertex;
632 mTransformDirty =
false;
637 if ( !
mMap || !mEvaluatedEnabled )
641 QPaintDevice *paintDevice = p->device();
648 p->setCompositionMode( mBlendMode );
651 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
652 p->setClipRect( thisPaintRect );
653 if ( thisPaintRect != mPrevPaintRect )
656 mTransformDirty =
true;
657 mPrevPaintRect = thisPaintRect;
661 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
662 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
677 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
679 drawGridCrsTransform( context, dotsPerMM );
686 drawGridNoTransform( context, dotsPerMM );
691 p->setClipping(
false );
695 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
700 updateGridLinesAnnotationsPositions();
707 if ( mShowGridAnnotation )
713void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
715 QList< GridLine >::iterator it = mGridLines.begin();
716 for ( ; it != mGridLines.end(); ++it )
718 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
719 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
720 it->startAnnotation.position = QVector2D( it->line.first() );
721 it->endAnnotation.position = QVector2D( it->line.last() );
722 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
723 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
725 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() );
727 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() );
731void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
738 if ( calculateLinesOnly )
741 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
742 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
744 int countLongitudeLines = 0;
745 int countLatitudeLines = 0;
746 for (
const GridLine &line : mGridLines )
748 switch ( line.coordinateType )
751 countLongitudeLines++;
754 countLatitudeLines++;
759 int latitudeLineIndex = 0;
760 int longitudeLineIndex = 0;
768 for ( ; vIt != mGridLines.constEnd(); ++vIt )
772 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
774 longitudeLineIndex++;
780 drawGridLine( line, context );
783 for ( ; hIt != mGridLines.constEnd(); ++hIt )
787 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
795 drawGridLine( line, context );
801 QPointF intersectionPoint, crossEnd1, crossEnd2;
802 for ( ; vIt != mGridLines.constEnd(); ++vIt )
807 l1 = QLineF( vIt->line.first(), vIt->line.last() );
810 hIt = mGridLines.constBegin();
811 for ( ; hIt != mGridLines.constEnd(); ++hIt )
816 l2 = QLineF( hIt->line.first(), hIt->line.last() );
818 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
823 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
825 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
828 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
832 drawGridMarker( intersectionPoint * dotsPerMM, context );
844 hIt = mGridLines.constBegin();
845 for ( ; hIt != mGridLines.constEnd(); ++hIt )
850 l1 = QLineF( hIt->line.first(), hIt->line.last() );
852 vIt = mGridLines.constBegin();
853 for ( ; vIt != mGridLines.constEnd(); ++vIt )
858 l2 = QLineF( vIt->line.first(), vIt->line.last() );
860 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
863 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
865 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
868 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
875void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
884 switch ( mGridFrameStyle )
888 drawGridFrameZebra( p, extension );
893 drawGridFrameTicks( p, extension );
898 drawGridFrameLine( p, extension );
909void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
912 poly << line.p1() << line.p2();
913 drawGridLine( poly, context );
916void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
918 if ( !
mMap || !
mMap->layout() || !mGridLineSymbol )
923 mGridLineSymbol->startRender( context );
924 mGridLineSymbol->renderPolyline( line,
nullptr, context );
925 mGridLineSymbol->stopRender( context );
928void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
930 if ( !
mMap || !
mMap->layout() || !mGridMarkerSymbol )
935 mGridMarkerSymbol->startRender( context );
936 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
937 mGridMarkerSymbol->stopRender( context );
940void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
960void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p, BorderSide border,
double *extension )
const
969 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
973 double currentCoord = 0.0;
980 bool drawTLBox =
false;
981 bool drawTRBox =
false;
982 bool drawBLBox =
false;
983 bool drawBRBox =
false;
985 QMap< double, double > pos = QMap< double, double >();
986 QList< GridLine >::const_iterator it = mGridLines.constBegin();
987 for ( ; it != mGridLines.constEnd(); ++it )
990 for (
int i = 0 ; i < 2 ; ++i )
992 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
995 if ( annot.border != border )
998 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1002 pos.insert( annot.position.y(), it->coordinate );
1004 pos.insert( annot.position.x(), it->coordinate );
1011 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
1027 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
1031 QPen framePen = QPen( mGridFramePenColor );
1032 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1033 framePen.setJoinStyle( Qt::MiterJoin );
1034 p->setPen( framePen );
1036 QMap< double, double >::const_iterator posIt = pos.constBegin();
1037 for ( ; posIt != pos.constEnd(); ++posIt )
1039 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1042 height = posIt.key() - currentCoord;
1043 width = mEvaluatedGridFrameWidth;
1044 x = ( border ==
QgsLayoutItemMapGrid::Left ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().width() + mEvaluatedGridFrameMargin;
1049 height = mEvaluatedGridFrameWidth;
1050 width = posIt.key() - currentCoord;
1052 y = ( border ==
QgsLayoutItemMapGrid::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
1054 p->drawRect( QRectF( x, y, width, height ) );
1055 currentCoord = posIt.key();
1062 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) ;
1063 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1065 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1067 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1069 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1071 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1075void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1085 QPen framePen = QPen( mGridFramePenColor );
1086 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1087 framePen.setCapStyle( Qt::FlatCap );
1088 p->setBrush( Qt::NoBrush );
1089 p->setPen( framePen );
1092 QList< GridLine >::iterator it = mGridLines.begin();
1093 for ( ; it != mGridLines.end(); ++it )
1096 for (
int i = 0 ; i < 2 ; ++i )
1098 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1100 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1104 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1112 facingLeft = ( annot.angle != 0 );
1113 facingRight = ( annot.angle != 0 );
1117 facingLeft = ( annot.angle > 0 );
1118 facingRight = ( annot.angle < 0 );
1122 facingLeft = ( annot.angle < 0 );
1123 facingRight = ( annot.angle > 0 );
1126 if ( annot.border ==
BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) ||
1127 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1129 if ( annot.border ==
BorderSide::Bottom && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ||
1130 ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1132 if ( annot.border ==
BorderSide::Left && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ||
1133 ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1135 if ( annot.border ==
BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) ||
1136 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1140 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1142 double fA = mEvaluatedGridFrameMargin;
1143 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1145 if ( mRotatedTicksEnabled && mRotatedTicksLengthMode ==
OrthogonalTicks )
1147 fA /= QVector2D::dotProduct( vector, normalVector );
1148 fB /= QVector2D::dotProduct( vector, normalVector );
1155 extension->UpdateBorder( annot.border, fB );
1163 pA = annot.position + fA * vector;
1164 pB = annot.position + fB * vector;
1168 pA = annot.position - fA * vector;
1169 pB = annot.position - fB * vector;
1173 pA = annot.position - fB * vector;
1174 pB = annot.position + ( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1176 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1182void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1192 QPen framePen = QPen( mGridFramePenColor );
1193 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1194 framePen.setCapStyle( Qt::SquareCap );
1195 p->setBrush( Qt::NoBrush );
1196 p->setPen( framePen );
1206 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1214 p->drawLine( QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1220 extension->UpdateBorder(
QgsLayoutItemMapGrid::Top, mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 );
1222 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1230 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1233 if ( ! extension && drawDiagonals )
1238 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1239 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1240 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1245 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1246 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1247 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1252 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1253 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1254 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1259 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1260 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1261 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1267 GridExtension *extension )
const
1269 if ( mGridLines.empty() )
1272 QString currentAnnotationString;
1273 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1275 QgsExpressionContextScope *gridScope =
new QgsExpressionContextScope();
1276 QgsExpressionContextScopePopper scopePopper( expressionContext, gridScope );
1278 bool geographic =
false;
1279 if ( mCRS.isValid() )
1281 geographic = mCRS.isGeographic();
1285 geographic =
mMap->crs().isGeographic();
1291 int countLongitudeLines = 0;
1292 int countLatitudeLines = 0;
1293 for (
const GridLine &line : mGridLines )
1295 switch ( line.coordinateType )
1298 countLongitudeLines++;
1301 countLatitudeLines++;
1306 int latitudeLineIndex = 0;
1307 int longitudeLineIndex = 0;
1308 for ( ; it != mGridLines.constEnd(); ++it )
1310 double value = it->coordinate;
1311 switch ( it->coordinateType )
1314 longitudeLineIndex++;
1315 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_count" ), countLongitudeLines,
true ) );
1316 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_index" ), longitudeLineIndex,
true ) );
1317 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_axis" ), QStringLiteral(
"x" ),
true ) );
1321 latitudeLineIndex++;
1322 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_count" ), countLatitudeLines,
true ) );
1323 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_index" ), latitudeLineIndex,
true ) );
1324 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_axis" ), QStringLiteral(
"y" ),
true ) );
1331 const double wrappedX = std::fmod( value, 360.0 );
1332 if ( wrappedX > 180.0 )
1334 value = wrappedX - 360.0;
1336 else if ( wrappedX < -180.0 )
1338 value = wrappedX + 360.0;
1342 gridScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"grid_number" ), value,
true ) );
1344 if ( mDrawAnnotationProperty )
1347 const bool display = mDrawAnnotationProperty->valueAsBool( expressionContext,
true, &ok );
1348 if ( ok && !display )
1351 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext, geographic );
1352 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1353 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1357void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
QgsRenderContext &context, GridLineAnnotation annot,
const QString &annotationString,
const AnnotationCoordinate coordinateType, GridExtension *extension )
const
1364 if ( ! shouldShowAnnotationForSide( coordinateType, annot.border ) )
1376 double xpos = annot.position.x();
1377 double ypos = annot.position.y();
1378 QPointF anchor = QPointF();
1385 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1389 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1392 double f = mEvaluatedAnnotationFrameDistance;
1400 f += mEvaluatedGridFrameWidth;
1401 if ( hasBorderWidth )
1402 f += mEvaluatedGridFrameLineThickness / 2.0;
1407 if ( mRotatedAnnotationsEnabled && mRotatedAnnotationsLengthMode ==
OrthogonalTicks )
1409 f /= QVector2D::dotProduct( vector, normalVector );
1412 const QVector2D pos = annot.position + f * vector;
1425 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1427 if ( rotation <= -90 || rotation > 90 )
1430 anchor.setX( outside ? 0 : textWidth );
1434 anchor.setX( outside ? textWidth : 0 );
1438 anchor.setY( 0.5 * textHeight );
1440 anchor.setY( -1.5 * textHeight );
1442 anchor.setY( -0.5 * textHeight );
1448 anchor.setX( 0.5 * textWidth );
1449 anchor.setY( -0.5 * textHeight );
1451 anchor.setY( outside ? 0 : -textHeight );
1453 anchor.setX( outside ? 0 : textWidth );
1455 anchor.setY( outside ? -textHeight : 0 );
1457 anchor.setX( outside ? textWidth : 0 );
1462 anchor.setX( 0.5 * textWidth );
1463 anchor.setY( -0.5 * textHeight );
1465 anchor.setX( outside ? 0 : textWidth );
1467 anchor.setY( outside ? -textHeight : 0 );
1469 anchor.setX( outside ? textWidth : 0 );
1471 anchor.setY( outside ? 0 : -textHeight );
1476 anchor.setX( 0.5 * textWidth );
1477 anchor.setY( -0.5 * textHeight );
1479 anchor.setX( outside ? textWidth : 0 );
1481 anchor.setY( outside ? 0 : -textHeight );
1483 anchor.setX( outside ? 0 : textWidth );
1485 anchor.setY( outside ? -textHeight : 0 );
1490 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1491 anchor.setX( 0.5 * textWidth );
1493 anchor.setY( -textHeight );
1501 extension->UpdateBorder( frameBorder, -f + textWidth );
1503 extension->UpdateAll( textWidth / 2.0 );
1506 if ( extension || !context.
painter() )
1510 bool facingLeft = ( annot.angle < 0 );
1511 bool facingRight = ( annot.angle > 0 );
1514 facingLeft = !facingLeft;
1515 facingRight = !facingRight;
1517 if ( annot.border ==
BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ||
1518 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
1520 if ( annot.border ==
BorderSide::Bottom && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ||
1521 ( facingRight && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ) )
1523 if ( annot.border ==
BorderSide::Left && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ||
1524 ( facingRight && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ) )
1526 if ( annot.border ==
BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ||
1527 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
1530 const QgsScopedQPainterState painterState( context.
painter() );
1531 context.
painter()->translate( QPointF( xpos, ypos ) );
1532 context.
painter()->rotate( rotation );
1533 context.
painter()->translate( -anchor );
1534 const QgsScopedRenderContextScaleToPixels scale( context );
1544 return QString::number( value,
'f', mGridAnnotationPrecision );
1550 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1554 if ( !isGeographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1556 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1562 if ( !isGeographic || coordRounded != 0.0 )
1564 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1570 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1574 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1579 if ( !mGridAnnotationExpression )
1581 mGridAnnotationExpression = std::make_unique<QgsExpression>( mGridAnnotationExpressionString );
1582 mGridAnnotationExpression->prepare( &expressionContext );
1584 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1589 switch ( mGridAnnotationFormat )
1639int QgsLayoutItemMapGrid::xGridLines()
const
1641 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1647 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1648 QRectF mapBoundingRect = mapPolygon.boundingRect();
1649 double gridIntervalY = mEvaluatedIntervalY;
1650 double gridOffsetY = mEvaluatedOffsetY;
1651 double annotationScale = 1.0;
1652 switch ( mGridUnit )
1657 mapBoundingRect =
mMap->rect();
1658 mapPolygon = QPolygonF(
mMap->rect() );
1659 if ( mGridUnit ==
CM )
1661 annotationScale = 0.1;
1662 gridIntervalY *= 10;
1674 const double roundCorrection = mapBoundingRect.top() > gridOffsetY ? 1.0 : 0.0;
1675 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1677 int gridLineCount = 0;
1682 double yCanvasCoord;
1683 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1685 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1687 newLine.coordinate = currentLevel * annotationScale;
1689 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1690 mGridLines.append( newLine );
1691 currentLevel += gridIntervalY;
1698 QVector<QLineF> borderLines;
1699 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1700 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1701 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1702 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1704 QVector<QPointF> intersectionList;
1706 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1708 intersectionList.clear();
1709 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1711 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1712 for ( ; it != borderLines.constEnd(); ++it )
1714 QPointF intersectionPoint;
1715 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1717 intersectionList.push_back( intersectionPoint );
1718 if ( intersectionList.size() >= 2 )
1725 if ( intersectionList.size() >= 2 )
1728 newLine.coordinate = currentLevel;
1730 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1731 mGridLines.append( newLine );
1734 currentLevel += gridIntervalY;
1741int QgsLayoutItemMapGrid::yGridLines()
const
1743 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1748 QPolygonF mapPolygon =
mMap->transformedMapPolygon();
1749 QRectF mapBoundingRect = mapPolygon.boundingRect();
1750 double gridIntervalX = mEvaluatedIntervalX;
1751 double gridOffsetX = mEvaluatedOffsetX;
1752 double annotationScale = 1.0;
1753 switch ( mGridUnit )
1758 mapBoundingRect =
mMap->rect();
1759 mapPolygon = QPolygonF(
mMap->rect() );
1760 if ( mGridUnit ==
CM )
1762 annotationScale = 0.1;
1763 gridIntervalX *= 10;
1775 const double roundCorrection = mapBoundingRect.left() > gridOffsetX ? 1.0 : 0.0;
1776 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1778 int gridLineCount = 0;
1782 double xCanvasCoord;
1783 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1785 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1788 newLine.coordinate = currentLevel * annotationScale;
1790 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
1791 mGridLines.append( newLine );
1792 currentLevel += gridIntervalX;
1799 QVector<QLineF> borderLines;
1800 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1801 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1802 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1803 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1805 QVector<QPointF> intersectionList;
1807 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1809 intersectionList.clear();
1810 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1812 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1813 for ( ; it != borderLines.constEnd(); ++it )
1815 QPointF intersectionPoint;
1816 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1818 intersectionList.push_back( intersectionPoint );
1819 if ( intersectionList.size() >= 2 )
1826 if ( intersectionList.size() >= 2 )
1829 newLine.coordinate = currentLevel;
1831 newLine.line = QPolygonF() <<
mMap->mapToItemCoords( intersectionList.at( 0 ) ) <<
mMap->mapToItemCoords( intersectionList.at( 1 ) );
1832 mGridLines.append( newLine );
1835 currentLevel += gridIntervalX;
1843 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1848 const double roundCorrection = bbox.
yMaximum() > mEvaluatedOffsetY ? 1.0 : 0.0;
1849 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
1851 const double minX = bbox.
xMinimum();
1852 const double maxX = bbox.
xMaximum();
1853 double step = ( maxX - minX ) / 20;
1855 bool crosses180 =
false;
1856 bool crossed180 =
false;
1857 if ( mCRS.isGeographic() && ( minX > maxX ) )
1861 step = ( maxX + 360.0 - minX ) / 20;
1867 int gridLineCount = 0;
1871 double currentX = minX;
1875 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
1882 const QgsPointXY mapPoint = t.
transform( currentX, currentLevel );
1883 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
1885 catch ( QgsCsException &cse )
1892 if ( crosses180 && currentX > 180.0 )
1900 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
1901 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1902 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1904 if ( !( *lineIt ).isEmpty() )
1907 newLine.coordinate = currentLevel;
1909 newLine.line = QPolygonF( *lineIt );
1910 mGridLines.append( newLine );
1914 currentLevel -= mEvaluatedIntervalY;
1922 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1927 const double roundCorrection = bbox.
xMinimum() > mEvaluatedOffsetX ? 1.0 : 0.0;
1928 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
1930 const double minY = bbox.
yMinimum();
1931 const double maxY = bbox.
yMaximum();
1932 const double step = ( maxY - minY ) / 20;
1937 bool crosses180 =
false;
1938 bool crossed180 =
false;
1945 int gridLineCount = 0;
1946 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
1949 double currentY = minY;
1953 if ( currentY > maxY )
1960 const QgsPointXY mapPoint = t.
transform( currentLevel, currentY );
1962 gridLine.append(
mMap->mapToItemCoords( QPointF( mapPoint.
x(), mapPoint.
y() ) ) );
1964 catch ( QgsCsException &cse )
1973 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine, QgsRectangle(
mMap->rect() ) );
1974 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1975 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1977 if ( !( *lineIt ).isEmpty() )
1980 newLine.coordinate = currentLevel;
1982 newLine.line = QPolygonF( *lineIt );
1983 mGridLines.append( newLine );
1987 currentLevel += mEvaluatedIntervalX;
1988 if ( crosses180 && currentLevel > 180.0 )
1990 currentLevel -= 360.0;
2019 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
2021 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
2023 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
2025 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
2039 if ( ddValue.compare( QLatin1String(
"x_only" ), Qt::CaseInsensitive ) == 0 )
2041 else if ( ddValue.compare( QLatin1String(
"y_only" ), Qt::CaseInsensitive ) == 0 )
2043 else if ( ddValue.compare( QLatin1String(
"disabled" ), Qt::CaseInsensitive ) == 0 )
2045 else if ( ddValue.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
2051void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
2056 mTransformDirty = mTransformDirty
2069 mDrawAnnotationProperty->prepare( context );
2073 mDrawAnnotationProperty.reset();
2077 switch ( mGridUnit )
2090 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
2092 mEvaluatedEnabled =
false;
2097 const double mapWidthMapUnits = mapWidth();
2098 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2099 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
2101 mEvaluatedIntervalX = interval;
2102 mEvaluatedIntervalY = interval;
2103 mTransformDirty =
true;
2125double QgsLayoutItemMapGrid::mapWidth()
const
2132 const QgsRectangle mapExtent =
mMap->extent();
2136 return mapExtent.
width();
2153 catch ( QgsCsException & )
2156 QgsDebugError( QStringLiteral(
"An error occurred while calculating length" ) );
2162bool sortByDistance( QPair<qreal, QgsLayoutItemMapGrid::BorderSide> a, QPair<qreal, QgsLayoutItemMapGrid::BorderSide> b )
2164 return a.first < b.first;
2174 const double tolerance = std::max(
mMap->frameEnabled() ?
mMap->pen().widthF() : 0.0, 1.0 );
2177 if ( ( p.y() <= tolerance && p.x() <= tolerance )
2178 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2179 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2180 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2186 if ( p.x() <= tolerance )
2197 if ( p.y() <= tolerance )
2209 QList< QPair<qreal, QgsLayoutItemMapGrid::BorderSide > > distanceToSide;
2215 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2216 return distanceToSide.at( 0 ).second;
2221 mGridLineSymbol.reset( symbol );
2226 return mGridLineSymbol.get();
2231 return mGridLineSymbol.get();
2236 mGridMarkerSymbol.reset( symbol );
2241 return mGridMarkerSymbol.get();
2246 return mGridMarkerSymbol.get();
2251 mAnnotationFormat.setFont( font );
2252 if ( font.pointSizeF() > 0 )
2254 mAnnotationFormat.setSize( font.pointSizeF() );
2257 else if ( font.pixelSize() > 0 )
2259 mAnnotationFormat.setSize( font.pixelSize() );
2266 return mAnnotationFormat.toQFont();
2271 mAnnotationFormat.
setColor( color );
2276 return mAnnotationFormat.color();
2284 mLeftGridAnnotationDisplay = display;
2287 mRightGridAnnotationDisplay = display;
2290 mTopGridAnnotationDisplay = display;
2293 mBottomGridAnnotationDisplay = display;
2297 refreshDataDefinedProperties();
2301 mMap->updateBoundingRect();
2311 return mLeftGridAnnotationDisplay;
2313 return mRightGridAnnotationDisplay;
2315 return mTopGridAnnotationDisplay;
2317 return mBottomGridAnnotationDisplay;
2319 return mBottomGridAnnotationDisplay;
2326 double bottom = 0.0;
2329 return std::max( std::max( std::max( top, right ), bottom ), left );
2339 if ( !
mMap || !mEvaluatedEnabled )
2349 GridExtension extension;
2352 switch ( mGridUnit )
2357 if ( mCRS.isValid() && mCRS !=
mMap->crs() )
2359 drawGridCrsTransform( context, 0,
true );
2366 drawGridNoTransform( context, 0,
true );
2371 updateGridLinesAnnotationsPositions();
2375 drawGridFrame(
nullptr, &extension );
2378 if ( mShowGridAnnotation )
2383 top = extension.top;
2384 right = extension.right;
2385 bottom = extension.bottom;
2386 left = extension.left;
2392 refreshDataDefinedProperties();
2397 if ( unit == mGridUnit )
2402 mTransformDirty =
true;
2411 mGridIntervalX = interval;
2412 mTransformDirty =
true;
2413 refreshDataDefinedProperties();
2422 mGridIntervalY = interval;
2423 mTransformDirty =
true;
2424 refreshDataDefinedProperties();
2433 mGridOffsetX = offset;
2434 mTransformDirty =
true;
2435 refreshDataDefinedProperties();
2444 mGridOffsetY = offset;
2445 mTransformDirty =
true;
2446 refreshDataDefinedProperties();
2455 mMinimumIntervalWidth = minWidth;
2456 mTransformDirty =
true;
2457 refreshDataDefinedProperties();
2466 mMaximumIntervalWidth = maxWidth;
2467 mTransformDirty =
true;
2468 refreshDataDefinedProperties();
2473 if (
style == mGridStyle )
2478 mTransformDirty =
true;
2483 mCrossLength = length;
2484 refreshDataDefinedProperties();
2492 mLeftGridAnnotationDirection = direction;
2495 mRightGridAnnotationDirection = direction;
2498 mTopGridAnnotationDirection = direction;
2501 mBottomGridAnnotationDirection = direction;
2507 mMap->updateBoundingRect();
2514 mGridFrameSides = flags;
2520 mGridFrameSides |= flag;
2522 mGridFrameSides &= ~flag;
2527 return mGridFrameSides;
2536 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"grid_number" ) << QStringLiteral(
"grid_axis" ) );
2542 if ( mGridLineSymbol )
2548 if ( mGridMarkerSymbol )
2560 mTransformDirty =
true;
2561 refreshDataDefinedProperties();
2562 mMap->updateBoundingRect();
2568 return mGridFrameSides.testFlag( flag );
2573 mGridFrameWidth = width;
2574 refreshDataDefinedProperties();
2579 mGridFrameMargin = margin;
2580 refreshDataDefinedProperties();
2585 mGridFramePenThickness = width;
2586 refreshDataDefinedProperties();
2591 mLeftGridAnnotationDirection = direction;
2592 mRightGridAnnotationDirection = direction;
2593 mTopGridAnnotationDirection = direction;
2594 mBottomGridAnnotationDirection = direction;
2602 mLeftGridAnnotationPosition = position;
2605 mRightGridAnnotationPosition = position;
2608 mTopGridAnnotationPosition = position;
2611 mBottomGridAnnotationPosition = position;
2617 mMap->updateBoundingRect();
2627 return mLeftGridAnnotationPosition;
2629 return mRightGridAnnotationPosition;
2631 return mTopGridAnnotationPosition;
2633 return mBottomGridAnnotationPosition;
2635 return mLeftGridAnnotationPosition;
2640 mAnnotationFrameDistance = distance;
2641 refreshDataDefinedProperties();
2648 return mLeftGridAnnotationDirection;
2654 return mLeftGridAnnotationDirection;
2656 return mRightGridAnnotationDirection;
2658 return mTopGridAnnotationDirection;
2660 return mBottomGridAnnotationDirection;
2662 return mLeftGridAnnotationDirection;
2667 mGridAnnotationExpressionString = expression;
2668 mGridAnnotationExpression.reset();
2676 mLeftFrameDivisions = divisions;
2679 mRightFrameDivisions = divisions;
2682 mTopFrameDivisions = divisions;
2685 mBottomFrameDivisions = divisions;
2689 refreshDataDefinedProperties();
2702 return mLeftFrameDivisions;
2704 return mRightFrameDivisions;
2706 return mTopFrameDivisions;
2708 return mBottomFrameDivisions;
2710 return mLeftFrameDivisions;
2722 const QgsCoordinateTransform tr(
mMap->crs(), mCRS,
mLayout->project() );
2723 QgsCoordinateTransform extentTransform = tr;
2725 const QPolygonF mapPolygon =
mMap->transformedMapPolygon();
2726 const QRectF mbr = mapPolygon.boundingRect();
2727 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2730 if ( mCRS.isGeographic() )
2733 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2734 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2736 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2737 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2739 if ( lowerLeft.x() > upperRight.x() )
2755 inverseTransform = QgsCoordinateTransform( mCRS,
mMap->crs(),
mLayout->project() );
2757 catch ( QgsCsException &cse )
2766QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2771 const QgsGeometry intersected = lineGeom.
intersection( rectGeom );
2774 QList<QPolygonF> trimmedLines;
2775 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2776 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2778 trimmedLines << ( *geomIt ).asQPolygonF();
2780 return trimmedLines;
2855 refreshDataDefinedProperties();
@ 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.
DistanceUnit
Units of distance.
@ Unknown
Unknown distance unit.
@ 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 ...
@ 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(QgsLayoutItemMapGrid::FrameSideFlags flags)
Sets flags for grid frame sides.
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.
GridStyle
Grid drawing style.
@ Markers
Draw markers at intersections of grid lines.
@ Cross
Draw line crosses at intersections of grid lines.
@ FrameAnnotationsOnly
No grid lines over the map, only draw frame and annotations.
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.
GridUnit
Unit for grid values.
@ CM
Grid units in centimeters.
@ MM
Grid units in millimeters.
@ DynamicPageSizeBased
Dynamically sized, based on a on-page size range.
@ MapUnit
Grid units follow map units.
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.
GridStyle style() const
Returns the grid's style, which controls how the grid is drawn over the map's contents.
void setFrameSideFlag(QgsLayoutItemMapGrid::FrameSideFlag flag, bool on=true)
Sets whether the grid frame is drawn for a certain side of the map item.
FrameSideFlag
Flags for controlling which side of the map a frame is drawn on.
@ FrameTop
Top side of map.
@ FrameBottom
Bottom side of map.
@ FrameLeft
Left side of map.
@ FrameRight
Right side of map.
Q_DECL_DEPRECATED void setAnnotationFontColor(const QColor &color)
Sets the font color used for drawing grid annotations.
void setAnnotationFormat(const AnnotationFormat format)
Sets the format 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.
AnnotationFormat annotationFormat() const
Returns the format for drawing grid annotations.
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 setAnnotationDisplay(DisplayMode display, BorderSide border)
Sets what types of grid annotations should be drawn for a specified side of the map frame,...
void setRotatedTicksEnabled(const bool state)
Enable/disable ticks rotation for rotated or reprojected grids.
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...
AnnotationPosition
Position for grid annotations.
@ InsideMapFrame
Draw annotations inside the map frame.
@ OutsideMapFrame
Draw annotations outside the map frame.
TickLengthMode rotatedAnnotationsLengthMode() const
Returns the annotation length calculation mode.
double rotatedTicksMinimumAngle() const
Gets the minimum angle (in degrees) below which ticks are not drawn.
void setAnnotationPosition(AnnotationPosition position, BorderSide side)
Sets the position for the grid annotations on a specified side of the map frame.
AnnotationPosition annotationPosition(BorderSide side) const
Returns the position for the grid annotations on a specified side of the map frame.
void setUnits(GridUnit unit)
Sets the unit to use for grid measurements such as the interval and offset for grid lines.
QgsLayoutItemMapGrid::FrameSideFlags frameSideFlags() const
Returns the flags which control which sides of the map item the grid frame is drawn on.
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...
bool testFrameSideFlag(FrameSideFlag flag) const
Tests whether the grid frame should be drawn on a specified side of the map item.
void setFrameDivisions(DisplayMode divisions, BorderSide side)
Sets what type of grid divisions should be used for frames on a specified side of the map.
void setMinimumIntervalWidth(double width)
Sets the minimum width (in millimeters) for grid segments.
friend class QgsLayoutItemMap
AnnotationCoordinate
Annotation coordinate type.
@ Latitude
Coordinate is a latitude value.
@ Longitude
Coordinate is a longitude value.
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 setRotatedTicksLengthMode(const TickLengthMode mode)
Sets the tick length calculation mode.
void setEnabled(bool enabled) override
Controls whether the item will be drawn.
DisplayMode
Display settings for grid annotations and frames.
@ LongitudeOnly
Show longitude/x annotations/divisions only.
@ ShowAll
Show both latitude and longitude annotations/divisions.
@ LatitudeOnly
Show latitude/y annotations/divisions only.
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.
~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.
void setFrameStyle(const FrameStyle style)
Sets the grid frame style.
QFlags< FrameSideFlag > FrameSideFlags
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.
FrameStyle frameStyle() const
Returns the grid frame style.
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 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.
void setRotatedAnnotationsLengthMode(const TickLengthMode mode)
Sets the annotation length calculation mode.
TickLengthMode
Tick length mode (useful for rotated grids).
@ OrthogonalTicks
Align ticks orthogonaly.
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.
AnnotationFormat
Format for displaying grid annotations.
@ DegreeMinuteSecondNoSuffix
Degree/minutes/seconds, use - for S/W coordinates.
@ DegreeMinuteSecondPadded
Degree/minutes/seconds, with minutes using leading zeros where required.
@ DegreeMinuteSecond
Degree/minutes/seconds, use NSEW suffix.
@ DecimalWithSuffix
Decimal degrees, use NSEW suffix.
@ DegreeMinute
Degree/minutes, use NSEW suffix.
@ DegreeMinuteNoSuffix
Degree/minutes, use - for S/W coordinates.
@ Decimal
Decimal degrees, use - for S/W coordinates.
@ DegreeMinutePadded
Degree/minutes, with minutes using leading zeros where required.
@ CustomFormat
Custom expression-based format.
DisplayMode frameDivisions(BorderSide side) const
Returns the type of grid divisions which are used for frames on a specified side of the map.
AnnotationDirection
Direction of grid annotations.
@ OnTick
Draw annotations parallel to tick (on the line).
@ Horizontal
Draw annotations horizontally.
@ Vertical
Draw annotations vertically, ascending.
@ AboveTick
Draw annotations parallel to tick (above the line).
@ UnderTick
Draw annotations parallel to tick (under the line).
@ VerticalDescending
Draw annotations vertically, descending.
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.
GridUnit units() const
Returns the units used for grid measurements such as the interval and offset for grid lines.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs for the grid.
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.
FrameStyle
Style for grid frame.
@ Zebra
Black/white pattern.
@ InteriorTicks
Tick markers drawn inside map frame.
@ LineBorder
Simple solid line frame.
@ InteriorExteriorTicks
Tick markers drawn both inside and outside the map frame.
@ LineBorderNautical
Simple solid line frame, with nautical style diagonals on corners.
@ ExteriorTicks
Tick markers drawn outside map frame.
@ NoFrame
Disable grid frame.
@ ZebraNautical
Black/white pattern, with nautical style diagonals on corners.
void setFrameWidth(const double width)
Sets the grid frame width (in layout units).
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).
DisplayMode annotationDisplay(BorderSide border) const
Returns the display mode for the grid annotations on a specified side of the map frame.
void setOffsetX(double offset)
Sets the offset for grid lines in the x-direction.
BorderSide
Border sides for annotations.
AnnotationDirection annotationDirection(BorderSide border) const
Returns the direction for drawing frame annotations, on the specified side of the map.
void setAnnotationDirection(AnnotationDirection direction, BorderSide side)
Sets the direction for drawing frame annotations for the specified map side.
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...
void setStyle(GridStyle style)
Sets the grid style, which controls how the grid is drawn over the map's contents.
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.
TickLengthMode rotatedTicksLengthMode() const
Returns the grid frame style.
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.
static double textWidth(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics=nullptr)
Returns the width of a text based on a given format.
static void drawText(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, Qgis::TextVerticalAlignment vAlignment=Qgis::TextVerticalAlignment::Top, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle)
Draws text within a rectangle using the specified settings.
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.
QgsLayoutItemMapGrid::DisplayMode gridAnnotationDisplayModeFromDD(QString ddValue, QgsLayoutItemMapGrid::DisplayMode defValue)
bool sortByDistance(QPair< qreal, QgsLayoutItemMapGrid::BorderSide > a, QPair< qreal, QgsLayoutItemMapGrid::BorderSide > b)
QVector2D borderToNormal2D(QgsLayoutItemMapGrid::BorderSide border)
QVector2D borderToVector2D(QgsLayoutItemMapGrid::BorderSide border)
#define QgsDebugError(str)
Single variable definition for use within a QgsExpressionContextScope.
Contains information relating to the style entity currently being visited.