41 #define MAX_GRID_LINES 1000 //maximum number of horizontal or vertical grid lines to draw 83 QList< QgsLayoutItemMapGrid * > list;
106 QDomNodeList mapGridNodeList = elem.elementsByTagName( QStringLiteral(
"ComposerMapGrid" ) );
107 for (
int i = 0; i < mapGridNodeList.size(); ++i )
109 QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
111 mapGrid->
readXml( mapGridElem, doc, context );
125 return std::max( std::max( std::max( top, right ), bottom ), left );
139 double gridTop = 0.0;
140 double gridRight = 0.0;
141 double gridBottom = 0.0;
142 double gridLeft = 0.0;
144 top = std::max( top, gridTop );
145 right = std::max( right, gridRight );
146 bottom = std::max( bottom, gridBottom );
147 left = std::max( left, gridLeft );
165 QString defaultFontString = settings.
value( QStringLiteral(
"LayoutDesigner/defaultFont" ), QVariant(),
QgsSettings::Gui ).toString();
166 if ( !defaultFontString.isEmpty() )
168 mGridAnnotationFont.setFamily( defaultFontString );
171 createDefaultGridLineSymbol();
172 createDefaultGridMarkerSymbol();
175 void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
178 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
179 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
180 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"flat" ) );
184 void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
187 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"circle" ) );
188 properties.insert( QStringLiteral(
"size" ), QStringLiteral(
"2.0" ) );
189 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
195 if ( mGridLineSymbol )
197 mGridLineSymbol->setWidth( width );
203 if ( mGridLineSymbol )
205 mGridLineSymbol->setColor( c );
216 QDomElement mapGridElem = doc.createElement( QStringLiteral(
"ComposerMapGrid" ) );
217 mapGridElem.setAttribute( QStringLiteral(
"gridStyle" ), mGridStyle );
218 mapGridElem.setAttribute( QStringLiteral(
"intervalX" ),
qgsDoubleToString( mGridIntervalX ) );
219 mapGridElem.setAttribute( QStringLiteral(
"intervalY" ),
qgsDoubleToString( mGridIntervalY ) );
220 mapGridElem.setAttribute( QStringLiteral(
"offsetX" ),
qgsDoubleToString( mGridOffsetX ) );
221 mapGridElem.setAttribute( QStringLiteral(
"offsetY" ),
qgsDoubleToString( mGridOffsetY ) );
222 mapGridElem.setAttribute( QStringLiteral(
"crossLength" ),
qgsDoubleToString( mCrossLength ) );
224 QDomElement lineStyleElem = doc.createElement( QStringLiteral(
"lineStyle" ) );
226 lineStyleElem.appendChild( gridLineStyleElem );
227 mapGridElem.appendChild( lineStyleElem );
229 QDomElement markerStyleElem = doc.createElement( QStringLiteral(
"markerStyle" ) );
231 markerStyleElem.appendChild( gridMarkerStyleElem );
232 mapGridElem.appendChild( markerStyleElem );
234 mapGridElem.setAttribute( QStringLiteral(
"gridFrameStyle" ), mGridFrameStyle );
235 mapGridElem.setAttribute( QStringLiteral(
"gridFrameSideFlags" ), mGridFrameSides );
236 mapGridElem.setAttribute( QStringLiteral(
"gridFrameWidth" ),
qgsDoubleToString( mGridFrameWidth ) );
237 mapGridElem.setAttribute( QStringLiteral(
"gridFramePenThickness" ),
qgsDoubleToString( mGridFramePenThickness ) );
241 mapGridElem.setAttribute( QStringLiteral(
"leftFrameDivisions" ), mLeftFrameDivisions );
242 mapGridElem.setAttribute( QStringLiteral(
"rightFrameDivisions" ), mRightFrameDivisions );
243 mapGridElem.setAttribute( QStringLiteral(
"topFrameDivisions" ), mTopFrameDivisions );
244 mapGridElem.setAttribute( QStringLiteral(
"bottomFrameDivisions" ), mBottomFrameDivisions );
250 mapGridElem.setAttribute( QStringLiteral(
"annotationFormat" ), mGridAnnotationFormat );
251 mapGridElem.setAttribute( QStringLiteral(
"showAnnotation" ), mShowGridAnnotation );
252 mapGridElem.setAttribute( QStringLiteral(
"annotationExpression" ), mGridAnnotationExpressionString );
253 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDisplay" ), mLeftGridAnnotationDisplay );
254 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDisplay" ), mRightGridAnnotationDisplay );
255 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDisplay" ), mTopGridAnnotationDisplay );
256 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDisplay" ), mBottomGridAnnotationDisplay );
257 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationPosition" ), mLeftGridAnnotationPosition );
258 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationPosition" ), mRightGridAnnotationPosition );
259 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationPosition" ), mTopGridAnnotationPosition );
260 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationPosition" ), mBottomGridAnnotationPosition );
261 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDirection" ), mLeftGridAnnotationDirection );
262 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDirection" ), mRightGridAnnotationDirection );
263 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDirection" ), mTopGridAnnotationDirection );
264 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDirection" ), mBottomGridAnnotationDirection );
265 mapGridElem.setAttribute( QStringLiteral(
"frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) );
266 mapGridElem.appendChild(
QgsFontUtils::toXmlElement( mGridAnnotationFont, doc, QStringLiteral(
"annotationFontProperties" ) ) );
268 mapGridElem.setAttribute( QStringLiteral(
"annotationPrecision" ), mGridAnnotationPrecision );
269 mapGridElem.setAttribute( QStringLiteral(
"unit" ), mGridUnit );
270 mapGridElem.setAttribute( QStringLiteral(
"blendMode" ), mBlendMode );
273 elem.appendChild( mapGridElem );
280 if ( itemElem.isNull() )
289 mGridIntervalX = itemElem.attribute( QStringLiteral(
"intervalX" ), QStringLiteral(
"0" ) ).toDouble();
290 mGridIntervalY = itemElem.attribute( QStringLiteral(
"intervalY" ), QStringLiteral(
"0" ) ).toDouble();
291 mGridOffsetX = itemElem.attribute( QStringLiteral(
"offsetX" ), QStringLiteral(
"0" ) ).toDouble();
292 mGridOffsetY = itemElem.attribute( QStringLiteral(
"offsetY" ), QStringLiteral(
"0" ) ).toDouble();
293 mCrossLength = itemElem.attribute( QStringLiteral(
"crossLength" ), QStringLiteral(
"3" ) ).toDouble();
294 mGridFrameStyle =
static_cast< QgsLayoutItemMapGrid::FrameStyle >( itemElem.attribute( QStringLiteral(
"gridFrameStyle" ), QStringLiteral(
"0" ) ).toInt() );
295 mGridFrameSides =
static_cast< QgsLayoutItemMapGrid::FrameSideFlags
>( itemElem.attribute( QStringLiteral(
"gridFrameSideFlags" ), QStringLiteral(
"15" ) ).toInt() );
296 mGridFrameWidth = itemElem.attribute( QStringLiteral(
"gridFrameWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
297 mGridFramePenThickness = itemElem.attribute( QStringLiteral(
"gridFramePenThickness" ), QStringLiteral(
"0.3" ) ).toDouble();
306 QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral(
"lineStyle" ) );
307 if ( !lineStyleElem.isNull() )
309 QDomElement symbolElem = lineStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
310 if ( !symbolElem.isNull() )
312 mGridLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
319 mGridLineSymbol->setWidth( itemElem.attribute( QStringLiteral(
"penWidth" ), QStringLiteral(
"0" ) ).toDouble() );
320 mGridLineSymbol->setColor( QColor( itemElem.attribute( QStringLiteral(
"penColorRed" ), QStringLiteral(
"0" ) ).toInt(),
321 itemElem.attribute( QStringLiteral(
"penColorGreen" ), QStringLiteral(
"0" ) ).toInt(),
322 itemElem.attribute( QStringLiteral(
"penColorBlue" ), QStringLiteral(
"0" ) ).toInt() ) );
325 QDomElement markerStyleElem = itemElem.firstChildElement( QStringLiteral(
"markerStyle" ) );
326 if ( !markerStyleElem.isNull() )
328 QDomElement symbolElem = markerStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
329 if ( !symbolElem.isNull() )
331 mGridMarkerSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context ) );
335 if ( !mCRS.
readXml( itemElem ) )
338 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( QStringLiteral(
"blendMode" ), QStringLiteral(
"0" ) ).toUInt() );
341 mShowGridAnnotation = ( itemElem.attribute( QStringLiteral(
"showAnnotation" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
343 mGridAnnotationExpressionString = itemElem.attribute( QStringLiteral(
"annotationExpression" ) );
344 mGridAnnotationExpression.reset();
349 mLeftGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"leftAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
350 mRightGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"rightAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
352 mBottomGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"bottomAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
358 mAnnotationFrameDistance = itemElem.attribute( QStringLiteral(
"frameAnnotationDistance" ), QStringLiteral(
"0" ) ).toDouble();
361 mGridAnnotationFont.fromString( itemElem.attribute( QStringLiteral(
"annotationFont" ), QString() ) );
363 mGridAnnotationFontColor =
QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral(
"annotationFontColor" ), QStringLiteral(
"0,0,0,255" ) ) );
364 mGridAnnotationPrecision = itemElem.attribute( QStringLiteral(
"annotationPrecision" ), QStringLiteral(
"3" ) ).toInt();
365 int gridUnitInt = itemElem.attribute( QStringLiteral(
"unit" ), QString::number(
MapUnit ) ).toInt();
366 mGridUnit = ( gridUnitInt <= static_cast< int >(
CM ) ) ?
static_cast< GridUnit >( gridUnitInt ) :
MapUnit;
373 mTransformDirty =
true;
378 return mBlendMode != QPainter::CompositionMode_SourceOver;
381 QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const 383 QTransform t = QTransform::fromScale( scale, scale );
384 return t.map( polygon );
387 void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM, QList< QPair< double, QLineF > > &horizontalLines,
388 QList< QPair< double, QLineF > > &verticalLines,
bool calculateLinesOnly )
const 397 if ( mapPolygon != mPrevMapPolygon )
399 mTransformDirty =
true;
400 mPrevMapPolygon = mapPolygon;
403 if ( mTransformDirty )
405 calculateCrsTransformLines();
409 if ( !calculateLinesOnly )
413 QList< QPair< double, QPolygonF > >::const_iterator xGridIt = mTransformedXLines.constBegin();
414 for ( ; xGridIt != mTransformedXLines.constEnd(); ++xGridIt )
416 drawGridLine( scalePolygon( xGridIt->second, dotsPerMM ), context );
419 QList< QPair< double, QPolygonF > >::const_iterator yGridIt = mTransformedYLines.constBegin();
420 for ( ; yGridIt != mTransformedYLines.constEnd(); ++yGridIt )
422 drawGridLine( scalePolygon( yGridIt->second, dotsPerMM ), context );
427 double maxX =
mMap->rect().width();
428 double maxY =
mMap->rect().height();
430 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
431 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
433 double x = intersectionIt->x();
434 double y = intersectionIt->y();
438 QLineF line1 = QLineF( x - mCrossLength, y, x + mCrossLength, y );
439 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
440 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
441 QLineF line2 = QLineF( x, y - mCrossLength, x, y + mCrossLength );
442 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
443 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
446 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
447 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
451 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
458 QList< QPair< double, QPolygonF > >::const_iterator yGridLineIt = mTransformedYLines.constBegin();
459 for ( ; yGridLineIt != mTransformedYLines.constEnd(); ++yGridLineIt )
461 verticalLines.push_back( qMakePair( yGridLineIt->first, QLineF( yGridLineIt->second.first(), yGridLineIt->second.last() ) ) );
463 QList< QPair< double, QPolygonF > >::const_iterator xGridLineIt = mTransformedXLines.constBegin();
464 for ( ; xGridLineIt != mTransformedXLines.constEnd(); ++xGridLineIt )
466 horizontalLines.push_back( qMakePair( xGridLineIt->first, QLineF( xGridLineIt->second.first(), xGridLineIt->second.last() ) ) );
470 void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const 474 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
480 mTransformedXLines.clear();
481 xGridLinesCrsTransform( crsBoundingRect, inverseTr, mTransformedXLines );
484 mTransformedYLines.clear();
485 yGridLinesCrsTransform( crsBoundingRect, inverseTr, mTransformedYLines );
492 QList< QgsGeometry > yLines;
493 QList< QPair< double, QPolygonF > >::const_iterator yGridIt = mTransformedYLines.constBegin();
494 for ( ; yGridIt != mTransformedYLines.constEnd(); ++yGridIt )
497 for (
int i = 0; i < ( *yGridIt ).second.size(); ++i )
499 yLine.append(
QgsPointXY( ( *yGridIt ).second.at( i ).x(), ( *yGridIt ).second.at( i ).y() ) );
503 QList< QgsGeometry > xLines;
504 QList< QPair< double, QPolygonF > >::const_iterator xGridIt = mTransformedXLines.constBegin();
505 for ( ; xGridIt != mTransformedXLines.constEnd(); ++xGridIt )
508 for (
int i = 0; i < ( *xGridIt ).second.size(); ++i )
510 xLine.append(
QgsPointXY( ( *xGridIt ).second.at( i ).x(), ( *xGridIt ).second.at( i ).y() ) );
516 mTransformedIntersections.clear();
517 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
518 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
520 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
521 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
525 if ( intersects.
isNull() )
533 mTransformedIntersections << vertex;
541 mTransformDirty =
false;
550 QPaintDevice *paintDevice = p->device();
557 p->setCompositionMode( mBlendMode );
560 QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
561 p->setClipRect( thisPaintRect );
562 if ( thisPaintRect != mPrevPaintRect )
565 mTransformDirty =
true;
566 mPrevPaintRect = thisPaintRect;
570 double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
571 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
579 QList< QPair< double, QLineF > > verticalLines;
580 QList< QPair< double, QLineF > > horizontalLines;
585 drawGridCrsTransform( context, dotsPerMM, horizontalLines, verticalLines );
589 drawGridNoTransform( context, dotsPerMM, horizontalLines, verticalLines );
594 p->setClipping(
false );
598 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
603 drawGridFrame( p, horizontalLines, verticalLines );
606 if ( mShowGridAnnotation )
608 drawCoordinateAnnotations( p, horizontalLines, verticalLines, context.
expressionContext() );
612 void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM, QList< QPair< double, QLineF > > &horizontalLines,
613 QList< QPair< double, QLineF > > &verticalLines,
bool calculateLinesOnly )
const 616 yGridLines( verticalLines );
617 xGridLines( horizontalLines );
619 if ( calculateLinesOnly )
622 QList< QPair< double, QLineF > >::const_iterator vIt = verticalLines.constBegin();
623 QList< QPair< double, QLineF > >::const_iterator hIt = horizontalLines.constBegin();
631 for ( ; vIt != verticalLines.constEnd(); ++vIt )
633 line = QLineF( vIt->second.p1() * dotsPerMM, vIt->second.p2() * dotsPerMM );
634 drawGridLine( line, context );
637 for ( ; hIt != horizontalLines.constEnd(); ++hIt )
639 line = QLineF( hIt->second.p1() * dotsPerMM, hIt->second.p2() * dotsPerMM );
640 drawGridLine( line, context );
645 QPointF intersectionPoint, crossEnd1, crossEnd2;
646 for ( ; vIt != verticalLines.constEnd(); ++vIt )
649 hIt = horizontalLines.constBegin();
650 for ( ; hIt != horizontalLines.constEnd(); ++hIt )
652 if ( hIt->second.intersect( vIt->second, &intersectionPoint ) == QLineF::BoundedIntersection )
657 crossEnd1 = ( ( intersectionPoint - vIt->second.p1() ).manhattanLength() > 0.01 ) ?
659 crossEnd2 = ( ( intersectionPoint - vIt->second.p2() ).manhattanLength() > 0.01 ) ?
662 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
666 drawGridMarker( intersectionPoint * dotsPerMM, context );
678 hIt = horizontalLines.constBegin();
679 for ( ; hIt != horizontalLines.constEnd(); ++hIt )
681 vIt = verticalLines.constBegin();
682 for ( ; vIt != verticalLines.constEnd(); ++vIt )
684 if ( vIt->second.intersect( hIt->second, &intersectionPoint ) == QLineF::BoundedIntersection )
687 crossEnd1 = ( ( intersectionPoint - hIt->second.p1() ).manhattanLength() > 0.01 ) ?
689 crossEnd2 = ( ( intersectionPoint - hIt->second.p2() ).manhattanLength() > 0.01 ) ?
692 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
699 void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p,
const QList< QPair< double, QLineF > > &hLines,
const QList< QPair< double, QLineF > > &vLines, GridExtension *extension )
const 704 p->setRenderHint( QPainter::Antialiasing );
708 QMap< double, double > leftGridFrame;
709 QMap< double, double > rightGridFrame;
710 QMap< double, double > topGridFrame;
711 QMap< double, double > bottomGridFrame;
713 sortGridLinesOnBorders( hLines, vLines, leftGridFrame, rightGridFrame, topGridFrame, bottomGridFrame );
735 void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const 738 poly << line.p1() << line.p2();
739 drawGridLine( poly, context );
742 void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const 749 mGridLineSymbol->startRender( context );
750 mGridLineSymbol->renderPolyline( line,
nullptr, context );
751 mGridLineSymbol->stopRender( context );
754 void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const 761 mGridMarkerSymbol->startRender( context );
762 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
763 mGridMarkerSymbol->stopRender( context );
766 void QgsLayoutItemMapGrid::drawGridFrameBorder( QPainter *p,
const QMap< double, double > &borderPos,
QgsLayoutItemMapGrid::BorderSide border,
double *extension )
const 773 switch ( mGridFrameStyle )
776 drawGridFrameZebraBorder( p, borderPos, border, extension );
781 drawGridFrameTicks( p, borderPos, border, extension );
785 drawGridFrameLineBorder( p, border, extension );
794 void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
const QMap< double, double > &borderPos,
QgsLayoutItemMapGrid::BorderSide border,
double *extension )
const 803 *extension = mGridFrameWidth + mGridFramePenThickness / 2.0;
807 QMap< double, double > pos = borderPos;
809 double currentCoord = 0;
812 currentCoord = - mGridFrameWidth;
817 currentCoord = - mGridFrameWidth;
828 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
831 pos.insert(
mMap->rect().height() + mGridFrameWidth,
mMap->rect().height() + mGridFrameWidth );
836 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
839 pos.insert(
mMap->rect().width() + mGridFrameWidth,
mMap->rect().width() + mGridFrameWidth );
844 QPen framePen = QPen( mGridFramePenColor );
845 framePen.setWidthF( mGridFramePenThickness );
846 framePen.setJoinStyle( Qt::MiterJoin );
847 p->setPen( framePen );
849 QMap< double, double >::const_iterator posIt = pos.constBegin();
850 for ( ; posIt != pos.constEnd(); ++posIt )
852 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
855 height = posIt.key() - currentCoord;
856 width = mGridFrameWidth;
862 height = mGridFrameWidth;
863 width = posIt.key() - currentCoord;
867 p->drawRect( QRectF( x, y, width, height ) );
868 currentCoord = posIt.key();
873 void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p,
const QMap< double, double > &borderPos,
QgsLayoutItemMapGrid::BorderSide border,
double *extension )
const 883 *extension = mGridFrameWidth;
893 QPen framePen = QPen( mGridFramePenColor );
894 framePen.setWidthF( mGridFramePenThickness );
895 framePen.setCapStyle( Qt::FlatCap );
896 p->setBrush( Qt::NoBrush );
897 p->setPen( framePen );
899 QMap< double, double >::const_iterator posIt = borderPos.constBegin();
900 for ( ; posIt != borderPos.constEnd(); ++posIt )
908 width = mGridFrameWidth;
913 width = mGridFrameWidth;
918 width = mGridFrameWidth * 2;
928 height = mGridFrameWidth;
933 height = mGridFrameWidth;
938 height = mGridFrameWidth * 2;
942 p->drawLine( QLineF( x, y, x + width, y + height ) );
955 *extension = mGridFramePenThickness / 2.0;
960 QPen framePen = QPen( mGridFramePenColor );
961 framePen.setWidthF( mGridFramePenThickness );
962 framePen.setCapStyle( Qt::SquareCap );
963 p->setBrush( Qt::NoBrush );
964 p->setPen( framePen );
969 p->drawLine( QLineF( 0, 0, 0,
mMap->rect().height() ) );
972 p->drawLine( QLineF(
mMap->rect().width(), 0,
mMap->rect().width(),
mMap->rect().height() ) );
975 p->drawLine( QLineF( 0, 0,
mMap->rect().width(), 0 ) );
978 p->drawLine( QLineF( 0,
mMap->rect().height(),
mMap->rect().width(),
mMap->rect().height() ) );
983 void QgsLayoutItemMapGrid::drawCoordinateAnnotations( QPainter *p,
const QList< QPair< double, QLineF > > &hLines,
const QList< QPair< double, QLineF > > &vLines,
QgsExpressionContext &expressionContext,
984 GridExtension *extension )
const 986 QString currentAnnotationString;
987 QList< QPair< double, QLineF > >::const_iterator it = hLines.constBegin();
988 for ( ; it != hLines.constEnd(); ++it )
995 it = vLines.constBegin();
996 for ( ; it != vLines.constEnd(); ++it )
1004 void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos,
const QString &annotationString,
const AnnotationCoordinate coordinateType, GridExtension *extension )
const 1016 double xpos = pos.x();
1017 double ypos = pos.y();
1020 double gridFrameDistance = 0;
1023 gridFrameDistance = mGridFrameWidth;
1027 gridFrameDistance += ( mGridFramePenThickness / 2.0 );
1040 gridFrameDistance = 0;
1047 gridFrameDistance = 0;
1051 xpos += textHeight + mAnnotationFrameDistance + gridFrameDistance;
1052 ypos += textWidth / 2.0;
1057 xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1058 ypos -= textWidth / 2.0;
1063 xpos += mAnnotationFrameDistance + gridFrameDistance;
1064 ypos += textHeight / 2.0;
1071 gridFrameDistance = 0;
1075 xpos -= ( mAnnotationFrameDistance + gridFrameDistance );
1076 ypos += textWidth / 2.0;
1079 extension->left = std::max( extension->left, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1083 xpos -= textHeight + mAnnotationFrameDistance + gridFrameDistance;
1084 ypos -= textWidth / 2.0;
1087 extension->left = std::max( extension->left, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1091 xpos -= ( textWidth + mAnnotationFrameDistance + gridFrameDistance );
1092 ypos += textHeight / 2.0;
1094 extension->left = std::max( extension->left, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1112 gridFrameDistance = 0;
1119 gridFrameDistance = 0;
1123 xpos -= mAnnotationFrameDistance + gridFrameDistance;
1124 ypos += textWidth / 2.0;
1129 xpos -= textHeight + mAnnotationFrameDistance + gridFrameDistance;
1130 ypos -= textWidth / 2.0;
1135 xpos -= textWidth + mAnnotationFrameDistance + gridFrameDistance;
1136 ypos += textHeight / 2.0;
1143 gridFrameDistance = 0;
1147 xpos += ( textHeight + mAnnotationFrameDistance + gridFrameDistance );
1148 ypos += textWidth / 2.0;
1151 extension->right = std::max( extension->right, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1155 xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1156 ypos -= textWidth / 2.0;
1159 extension->right = std::max( extension->right, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1163 xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1164 ypos += textHeight / 2.0;
1166 extension->right = std::max( extension->right, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1184 gridFrameDistance = 0;
1191 gridFrameDistance = 0;
1195 ypos -= mAnnotationFrameDistance + gridFrameDistance;
1196 xpos -= textWidth / 2.0;
1200 xpos -= textHeight / 2.0;
1201 ypos -= textWidth + mAnnotationFrameDistance + gridFrameDistance;
1206 xpos += textHeight / 2.0;
1207 ypos -= mAnnotationFrameDistance + gridFrameDistance;
1215 gridFrameDistance = 0;
1219 ypos += ( mAnnotationFrameDistance + textHeight + gridFrameDistance );
1220 xpos -= textWidth / 2.0;
1223 extension->bottom = std::max( extension->bottom, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1224 extension->left = std::max( extension->left, textWidth / 2.0 );
1225 extension->right = std::max( extension->right, textWidth / 2.0 );
1230 xpos -= textHeight / 2.0;
1231 ypos += gridFrameDistance + mAnnotationFrameDistance;
1234 extension->bottom = std::max( extension->bottom, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1238 xpos += textHeight / 2.0;
1239 ypos += ( textWidth + mAnnotationFrameDistance + gridFrameDistance );
1242 extension->bottom = std::max( extension->bottom, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1260 gridFrameDistance = 0;
1267 gridFrameDistance = 0;
1271 xpos -= textWidth / 2.0;
1272 ypos += textHeight + mAnnotationFrameDistance + gridFrameDistance;
1276 xpos -= textHeight / 2.0;
1277 ypos += mAnnotationFrameDistance + gridFrameDistance;
1282 xpos += textHeight / 2.0;
1283 ypos += textWidth + mAnnotationFrameDistance + gridFrameDistance;
1291 gridFrameDistance = 0;
1295 xpos -= textWidth / 2.0;
1296 ypos -= ( mAnnotationFrameDistance + gridFrameDistance );
1298 extension->top = std::max( extension->top, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1302 xpos -= textHeight / 2.0;
1303 ypos -= textWidth + mAnnotationFrameDistance + gridFrameDistance;
1306 extension->top = std::max( extension->top, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1310 xpos += textHeight / 2.0;
1311 ypos -= ( mAnnotationFrameDistance + gridFrameDistance );
1314 extension->top = std::max( extension->top, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1323 if ( extension || !p )
1326 drawAnnotation( p, QPointF( xpos, ypos ), rotation, annotationString );
1329 void QgsLayoutItemMapGrid::drawAnnotation( QPainter *p, QPointF pos,
int rotation,
const QString &annotationText )
const 1337 p->translate( pos );
1338 p->rotate( rotation );
1346 bool geographic =
false;
1360 double wrappedX = std::fmod( value, 360.0 );
1361 if ( wrappedX > 180.0 )
1363 value = wrappedX - 360.0;
1365 else if ( wrappedX < -180.0 )
1367 value = wrappedX + 360.0;
1373 return QString::number( value,
'f', mGridAnnotationPrecision );
1379 double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1383 if ( !geographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1385 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1391 if ( !geographic || coordRounded != 0.0 )
1393 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1399 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1403 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1410 if ( !mGridAnnotationExpression )
1412 mGridAnnotationExpression.reset(
new QgsExpression( mGridAnnotationExpressionString ) );
1413 mGridAnnotationExpression->prepare( &expressionContext );
1415 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1419 QgsCoordinateFormatter::FormatFlags flags =
nullptr;
1420 switch ( mGridAnnotationFormat )
1470 int QgsLayoutItemMapGrid::xGridLines( QList< QPair< double, QLineF > > &lines )
const 1473 if ( !
mMap || mGridIntervalY <= 0.0 )
1480 QRectF mapBoundingRect = mapPolygon.boundingRect();
1481 double gridIntervalY = mGridIntervalY;
1482 double gridOffsetY = mGridOffsetY;
1483 double annotationScale = 1.0;
1486 mapBoundingRect =
mMap->rect();
1487 mapPolygon = QPolygonF(
mMap->rect() );
1488 if ( mGridUnit ==
CM )
1490 annotationScale = 0.1;
1491 gridIntervalY *= 10;
1497 double roundCorrection = mapBoundingRect.top() > 0 ? 1.0 : 0.0;
1498 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1500 int gridLineCount = 0;
1505 double yCanvasCoord;
1506 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1508 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1509 lines.push_back( qMakePair( currentLevel * annotationScale, QLineF( 0, yCanvasCoord,
mMap->rect().width(), yCanvasCoord ) ) );
1510 currentLevel += gridIntervalY;
1517 QVector<QLineF> borderLines;
1518 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1519 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1520 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1521 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1523 QVector<QPointF> intersectionList;
1525 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1527 intersectionList.clear();
1528 QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1530 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1531 for ( ; it != borderLines.constEnd(); ++it )
1533 QPointF intersectionPoint;
1534 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1536 intersectionList.push_back( intersectionPoint );
1537 if ( intersectionList.size() >= 2 )
1544 if ( intersectionList.size() >= 2 )
1549 currentLevel += gridIntervalY;
1556 int QgsLayoutItemMapGrid::yGridLines( QList< QPair< double, QLineF > > &lines )
const 1559 if ( !
mMap || mGridIntervalX <= 0.0 )
1565 QRectF mapBoundingRect = mapPolygon.boundingRect();
1566 double gridIntervalX = mGridIntervalX;
1567 double gridOffsetX = mGridOffsetX;
1568 double annotationScale = 1.0;
1571 mapBoundingRect =
mMap->rect();
1572 mapPolygon = QPolygonF(
mMap->rect() );
1573 if ( mGridUnit ==
CM )
1575 annotationScale = 0.1;
1576 gridIntervalX *= 10;
1582 double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0;
1583 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1585 int gridLineCount = 0;
1589 double xCanvasCoord;
1590 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1592 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1593 lines.push_back( qMakePair( currentLevel * annotationScale, QLineF( xCanvasCoord, 0, xCanvasCoord,
mMap->rect().height() ) ) );
1594 currentLevel += gridIntervalX;
1601 QVector<QLineF> borderLines;
1602 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1603 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1604 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1605 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1607 QVector<QPointF> intersectionList;
1609 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1611 intersectionList.clear();
1612 QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1614 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1615 for ( ; it != borderLines.constEnd(); ++it )
1617 QPointF intersectionPoint;
1618 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1620 intersectionList.push_back( intersectionPoint );
1621 if ( intersectionList.size() >= 2 )
1628 if ( intersectionList.size() >= 2 )
1633 currentLevel += gridIntervalX;
1642 if ( !
mMap || mGridIntervalY <= 0.0 )
1647 double roundCorrection = bbox.
yMaximum() > 0 ? 1.0 : 0.0;
1648 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mGridOffsetY ) / mGridIntervalY + roundCorrection ) * mGridIntervalY + mGridOffsetY;
1652 double step = ( maxX - minX ) / 20;
1654 bool crosses180 =
false;
1655 bool crossed180 =
false;
1660 step = ( maxX + 360.0 - minX ) / 20;
1666 int gridLineCount = 0;
1670 double currentX = minX;
1674 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
1687 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1691 if ( crosses180 && currentX > 180.0 )
1699 QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1700 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1701 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1703 if ( !( *lineIt ).isEmpty() )
1705 lines.append( qMakePair( currentLevel, *lineIt ) );
1709 currentLevel -= mGridIntervalY;
1718 if ( !
mMap || mGridIntervalX <= 0.0 )
1723 double roundCorrection = bbox.
xMinimum() > 0 ? 1.0 : 0.0;
1724 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mGridOffsetX ) / mGridIntervalX + roundCorrection ) * mGridIntervalX + mGridOffsetX;
1728 double step = ( maxY - minY ) / 20;
1733 bool crosses180 =
false;
1734 bool crossed180 =
false;
1741 int gridLineCount = 0;
1742 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
1745 double currentY = minY;
1749 if ( currentY > maxY )
1763 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1769 QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1770 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1771 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1773 if ( !( *lineIt ).isEmpty() )
1775 lines.append( qMakePair( currentLevel, *lineIt ) );
1779 currentLevel += mGridIntervalX;
1780 if ( crosses180 && currentLevel > 180.0 )
1782 currentLevel -= 360.0;
1790 void QgsLayoutItemMapGrid::sortGridLinesOnBorders(
const QList< QPair< double, QLineF > > &hLines,
const QList< QPair< double, QLineF > > &vLines, QMap< double, double > &leftFrameEntries,
1791 QMap< double, double > &rightFrameEntries, QMap< double, double > &topFrameEntries, QMap< double, double > &bottomFrameEntries )
const 1793 QList< QgsMapAnnotation > borderPositions;
1794 QList< QPair< double, QLineF > >::const_iterator it = hLines.constBegin();
1795 for ( ; it != hLines.constEnd(); ++it )
1797 QgsMapAnnotation p1;
1798 p1.coordinate = it->first;
1799 p1.itemPosition = it->second.p1();
1801 borderPositions << p1;
1803 QgsMapAnnotation p2;
1804 p2.coordinate = it->first;
1805 p2.itemPosition = it->second.p2();
1807 borderPositions << p2;
1809 it = vLines.constBegin();
1810 for ( ; it != vLines.constEnd(); ++it )
1812 QgsMapAnnotation p1;
1813 p1.coordinate = it->first;
1814 p1.itemPosition = it->second.p1();
1816 borderPositions << p1;
1818 QgsMapAnnotation p2;
1819 p2.coordinate = it->first;
1820 p2.itemPosition = it->second.p2();
1822 borderPositions << p2;
1825 QList< QgsMapAnnotation >::const_iterator bIt = borderPositions.constBegin();
1826 for ( ; bIt != borderPositions.constEnd(); ++bIt )
1831 leftFrameEntries.insert( bIt->itemPosition.y(), bIt->coordinate );
1835 rightFrameEntries.insert( bIt->itemPosition.y(), bIt->coordinate );
1839 topFrameEntries.insert( bIt->itemPosition.x(), bIt->coordinate );
1843 bottomFrameEntries.insert( bIt->itemPosition.x(), bIt->coordinate );
1853 return shouldShowDivisionForDisplayMode( coordinate, mLeftFrameDivisions );
1855 return shouldShowDivisionForDisplayMode( coordinate, mRightFrameDivisions );
1857 return shouldShowDivisionForDisplayMode( coordinate, mTopFrameDivisions );
1860 return shouldShowDivisionForDisplayMode( coordinate, mBottomFrameDivisions );
1871 bool sortByDistance( QPair<qreal, QgsLayoutItemMapGrid::BorderSide> a, QPair<qreal, QgsLayoutItemMapGrid::BorderSide> b )
1873 return a.first < b.first;
1886 if ( ( p.y() <= tolerance && p.x() <= tolerance )
1887 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
1888 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
1889 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
1895 if ( p.x() <= tolerance )
1906 if ( p.y() <= tolerance )
1918 QList< QPair<qreal, QgsLayoutItemMapGrid::BorderSide > > distanceToSide;
1924 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
1925 return distanceToSide.at( 0 ).second;
1930 mGridLineSymbol.reset( symbol );
1935 return mGridLineSymbol.get();
1940 return mGridLineSymbol.get();
1945 mGridMarkerSymbol.reset( symbol );
1950 return mGridMarkerSymbol.get();
1955 return mGridMarkerSymbol.get();
1963 mLeftGridAnnotationDisplay = display;
1966 mRightGridAnnotationDisplay = display;
1969 mTopGridAnnotationDisplay = display;
1972 mBottomGridAnnotationDisplay = display;
1990 return mLeftGridAnnotationDisplay;
1992 return mRightGridAnnotationDisplay;
1994 return mTopGridAnnotationDisplay;
1997 return mBottomGridAnnotationDisplay;
2005 double bottom = 0.0;
2008 return std::max( std::max( std::max( top, right ), bottom ), left );
2028 GridExtension extension;
2031 QList< QPair< double, QLineF > > verticalLines;
2032 QList< QPair< double, QLineF > > horizontalLines;
2035 drawGridCrsTransform( context, 0, horizontalLines, verticalLines,
true );
2039 drawGridNoTransform( context, 0, horizontalLines, verticalLines,
true );
2044 drawGridFrame(
nullptr, horizontalLines, verticalLines, &extension );
2047 if ( mShowGridAnnotation )
2049 drawCoordinateAnnotations(
nullptr, horizontalLines, verticalLines, context.
expressionContext(), &extension );
2052 top = extension.top;
2053 right = extension.right;
2054 bottom = extension.bottom;
2055 left = extension.left;
2060 if ( unit == mGridUnit )
2065 mTransformDirty =
true;
2074 mGridIntervalX = interval;
2075 mTransformDirty =
true;
2084 mGridIntervalY = interval;
2085 mTransformDirty =
true;
2094 mGridOffsetX = offset;
2095 mTransformDirty =
true;
2104 mGridOffsetY = offset;
2105 mTransformDirty =
true;
2110 if ( style == mGridStyle )
2115 mTransformDirty =
true;
2123 mLeftGridAnnotationDirection = direction;
2126 mRightGridAnnotationDirection = direction;
2129 mTopGridAnnotationDirection = direction;
2132 mBottomGridAnnotationDirection = direction;
2147 mGridFrameSides = flags;
2153 mGridFrameSides |= flag;
2155 mGridFrameSides &= ~flag;
2160 return mGridFrameSides;
2169 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"grid_number" ) << QStringLiteral(
"grid_axis" ) );
2175 return mGridFrameSides.testFlag( flag );
2180 mLeftGridAnnotationDirection = direction;
2181 mRightGridAnnotationDirection = direction;
2182 mTopGridAnnotationDirection = direction;
2183 mBottomGridAnnotationDirection = direction;
2191 mLeftGridAnnotationPosition = position;
2194 mRightGridAnnotationPosition = position;
2197 mTopGridAnnotationPosition = position;
2200 mBottomGridAnnotationPosition = position;
2218 return mLeftGridAnnotationPosition;
2220 return mRightGridAnnotationPosition;
2222 return mTopGridAnnotationPosition;
2225 return mBottomGridAnnotationPosition;
2233 return mLeftGridAnnotationDirection;
2239 return mLeftGridAnnotationDirection;
2241 return mRightGridAnnotationDirection;
2243 return mTopGridAnnotationDirection;
2246 return mBottomGridAnnotationDirection;
2255 mLeftFrameDivisions = divisions;
2258 mRightFrameDivisions = divisions;
2261 mTopFrameDivisions = divisions;
2264 mBottomFrameDivisions = divisions;
2281 return mLeftFrameDivisions;
2283 return mRightFrameDivisions;
2285 return mTopFrameDivisions;
2288 return mBottomFrameDivisions;
2303 QRectF mbr = mapPolygon.boundingRect();
2304 QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2310 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2311 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2313 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2314 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2316 if ( lowerLeft.x() > upperRight.x() )
2324 crsRect = tr.transformBoundingBox( mapBoundingRect );
2329 crsRect = tr.transformBoundingBox( mapBoundingRect );
2337 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
2343 QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2351 QList<QPolygonF> trimmedLines;
2352 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2353 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2355 trimmedLines << ( *geomIt ).asQPolygonF();
2357 return trimmedLines;
Class for parsing and evaluation of expressions (formerly called "search strings").
void setAnnotationDisplay(DisplayMode display, BorderSide border)
Sets what types of grid annotations should be drawn for a specified side of the map frame...
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
The class is used as a container of context for various read/write operations on other objects...
Single variable definition for use within a QgsExpressionContextScope.
void setIntervalY(double interval)
Sets the interval between grid lines in the y-direction.
A rectangle specified with double values.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs for the grid.
QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the objects' current state.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
void setOffsetX(double offset)
Sets the offset for grid lines in the x-direction.
Degree/minutes/seconds, use NSEW suffix.
Draw annotations inside the map frame.
QgsCoordinateReferenceSystem crs() const
Retrieves the CRS for the grid.
void draw(QPainter *painter) override
Draws the item on to a destination painter.
AnnotationPosition annotationPosition(BorderSide side) const
Returns the position for the grid annotations on a specified side of the map frame.
QgsLayoutItemMapItem * item(const QString &itemId) const
Returns a reference to an item which matching itemId within the stack.
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
static double textWidthMM(const QFont &font, const QString &text)
Calculate a font width in millimeters for a text string, including workarounds for QT font rendering ...
This class is a composition of two QSettings instances:
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Coordinate is a longitude value.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
FrameSideFlag
Flags for controlling which side of the map a frame is drawn on.
const QgsLineSymbol * lineSymbol() const
Returns the line symbol used for drawing grid lines.
An item which is drawn inside a QgsLayoutItemMap, e.g., a grid or map overview.
Draw annotations vertically, ascending.
A class to represent a 2D point.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
void setGridLineWidth(double width)
Sets the width of grid lines (in layout units).
A collection of map items which are drawn above the map content in a QgsLayoutItemMap.
FrameStyle
Style for grid frame.
DisplayMode
Display settings for grid annotations and frames.
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
double maxGridExtension() const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QList< QgsLayoutItemMapGrid * > asList() const
Returns a list of QgsLayoutItemMapGrids contained by the stack.
void setAnnotationPosition(AnnotationPosition position, BorderSide side)
Sets the position for the grid annotations on a specified side of the map frame.
A geometry is the spatial representation of a feature.
DisplayMode annotationDisplay(BorderSide border) const
Returns the display mode for the grid annotations on a specified side of the map frame.
bool testFrameSideFlag(FrameSideFlag flag) const
Tests whether the grid frame should be drawn on a specified side of the map item. ...
QPointF mapToItemCoords(QPointF mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset) ...
bool usesAdvancedEffects() const override
Returns true if the item is drawn using advanced effects, such as blend modes.
Degree/minutes, use - for S/W coordinates.
Degree/minutes, use NSEW suffix.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
QMap< QString, QString > QgsStringMap
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
void removeItems()
Clears the item stack and deletes all QgsLayoutItemMapItems contained by the stack.
A marker symbol type, for rendering Point and MultiPoint geometries.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLayoutItemMap * mMap
Associated map.
bool sortByDistance(QPair< qreal, QgsLayoutItemMapGrid::BorderSide > a, QPair< qreal, QgsLayoutItemMapGrid::BorderSide > b)
void removeGrid(const QString &gridId)
Removes a grid with matching gridId from the stack and deletes the corresponding QgsLayoutItemMapGrid...
QgsLayoutRenderContext::Flags flags() const
Returns the current combination of flags used for rendering the layout.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used for drawing grid points.
static QString encodeColor(const QColor &color)
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
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 QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Draw line crosses at intersections of grid lines.
Custom expression-based format.
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...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void addGrid(QgsLayoutItemMapGrid *grid)
Adds a new map grid to the stack and takes ownership of the grid.
Tick markers drawn inside map frame.
bool mEnabled
True if item is to be displayed on map.
Layout graphical items for displaying a map.
void setFrameSideFlags(QgsLayoutItemMapGrid::FrameSideFlags flags)
Sets flags for grid frame sides.
Draw annotations horizontally.
void setFrameDivisions(DisplayMode divisions, BorderSide side)
Sets what type of grid divisions should be used for frames on a specified side of the map...
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Grid units in centimeters.
Decimal degrees, use - for S/W coordinates.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void addItem(QgsLayoutItemMapItem *item)
Adds a new map item to the stack and takes ownership of the item.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
Decimal degrees, use NSEW suffix.
const QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol used for drawing grid points.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
QPointer< QgsLayout > mLayout
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...
QgsLayoutItemMapGrid * grid(const QString &gridId) const
Returns a reference to a grid with matching gridId within the stack.
Show latitude/y annotations/divisions only.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
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...
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.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsLayoutItemMapGrid(const QString &name, QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGrid.
Single scope for storing variables and functions for use within a QgsExpressionContext.
Annotations follow the boundary direction.
AnnotationFormat
Format for displaying grid annotations.
Coordinate is a latitude value.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
void moveItemUp(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items...
void setStyle(GridStyle style)
Sets the grid style, which controls how the grid is drawn over the map's contents.
void setAnnotationDirection(AnnotationDirection direction, BorderSide side)
Sets the direction for drawing frame annotations for the specified map side.
double maxExtension() const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect (in layout u...
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
AnnotationDirection
Direction of grid annotations.
static void drawText(QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color=QColor())
Draws text on a painter at a specific position, taking care of layout specific issues (calculation to...
GridUnit
Unit for grid values.
Use antialiasing when drawing items.
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used for drawing grid lines.
Show both latitude and longitude annotations/divisions.
AnnotationPosition
Position for grid annotations.
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...
QgsExpressionContext & expressionContext()
Gets the expression context.
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...
void moveGridUp(const QString &gridId)
Moves a grid with matching gridId up the stack, causing it to be rendered above other grids...
AnnotationCoordinate
Annotation coordinate type.
BorderSide
Border sides for annotations.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
void setGridLineColor(const QColor &color)
Sets the color of grid lines.
DisplayMode frameDivisions(BorderSide side) const
Returns the type of grid divisions which are used for frames on a specified side of the map...
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Contains information about the context of a rendering operation.
Degree/minutes/seconds, with minutes using leading zeros where required.
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...
static double fontHeightCharacterMM(const QFont &font, QChar character)
Calculate a font height in millimeters of a single character, including workarounds for QT font rende...
Draw annotations vertically, descending.
Show longitude/x annotations/divisions only.
QgsLayoutItemMapGrid & operator[](int index)
Returns a reference to a grid at the specified index within the stack.
static double fontAscentMM(const QFont &font)
Calculates a font ascent in millimeters, including workarounds for QT font rendering issues...
Draw markers at intersections of grid lines.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places...
void updateBoundingRect()
Updates the bounding rect of this item. Call this function before doing any changes related to annota...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Degree/minutes, with minutes using leading zeros where required.
This class represents a coordinate reference system (CRS).
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
void setFrameSideFlag(QgsLayoutItemMapGrid::FrameSideFlag flag, bool on=true)
Sets whether the grid frame is drawn for a certain side of the map item.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
No grid lines over the map, only draw frame and annotations.
AnnotationDirection annotationDirection(BorderSide border) const
Returns the direction for drawing frame annotations, on the specified side of the map...
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user...
QgsLayoutItemMapGridStack(QgsLayoutItemMap *map)
Constructor for QgsLayoutItemMapGridStack, attached to the specified map.
void setOffsetY(double offset)
Sets the offset for grid lines in the y-direction.
void setIntervalX(double interval)
Sets the interval between grid lines in the x-direction.
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
void removeItem(const QString &itemId)
Removes an item which matching itemId from the stack and deletes the corresponding QgsLayoutItemMapIt...
Custom exception class for Coordinate Reference System related exceptions.
GridStyle
Grid drawing style.
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
Tick markers drawn both inside and outside the map frame.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void moveItemDown(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items...
GridStyle style() const
Returns the grid's style, which controls how the grid is drawn over the map's contents.
QList< QgsLayoutItemMapItem * > mItems
bool isGeographic() const
Returns whether the CRS is a geographic CRS (using lat/lon coordinates)
double xMinimum() const
Returns the x minimum value (left side of rectangle).
void setUnits(GridUnit unit)
Sets the unit to use for grid measurements such as the interval and offset for grid lines...
Draw annotations outside the map frame.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
bool frameEnabled() const
Returns true if the item includes a frame.
void moveGridDown(const QString &gridId)
Moves a grid with matching gridId down the stack, causing it to be rendered below other grids...
Grid units follow map units.
QgsLayoutItemMapGrid::FrameSideFlags frameSideFlags() const
Returns the flags which control which sides of the map item the grid frame is drawn on...
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 setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
static QColor decodeColor(const QString &str)
Degree/minutes/seconds, use - for S/W coordinates.
Tick markers drawn outside map frame.