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(
"gridFrameMargin" ),
qgsDoubleToString( mGridFrameMargin ) );
238 mapGridElem.setAttribute( QStringLiteral(
"gridFramePenThickness" ),
qgsDoubleToString( mGridFramePenThickness ) );
242 mapGridElem.setAttribute( QStringLiteral(
"leftFrameDivisions" ), mLeftFrameDivisions );
243 mapGridElem.setAttribute( QStringLiteral(
"rightFrameDivisions" ), mRightFrameDivisions );
244 mapGridElem.setAttribute( QStringLiteral(
"topFrameDivisions" ), mTopFrameDivisions );
245 mapGridElem.setAttribute( QStringLiteral(
"bottomFrameDivisions" ), mBottomFrameDivisions );
251 mapGridElem.setAttribute( QStringLiteral(
"annotationFormat" ), mGridAnnotationFormat );
252 mapGridElem.setAttribute( QStringLiteral(
"showAnnotation" ), mShowGridAnnotation );
253 mapGridElem.setAttribute( QStringLiteral(
"annotationExpression" ), mGridAnnotationExpressionString );
254 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDisplay" ), mLeftGridAnnotationDisplay );
255 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDisplay" ), mRightGridAnnotationDisplay );
256 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDisplay" ), mTopGridAnnotationDisplay );
257 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDisplay" ), mBottomGridAnnotationDisplay );
258 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationPosition" ), mLeftGridAnnotationPosition );
259 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationPosition" ), mRightGridAnnotationPosition );
260 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationPosition" ), mTopGridAnnotationPosition );
261 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationPosition" ), mBottomGridAnnotationPosition );
262 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDirection" ), mLeftGridAnnotationDirection );
263 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDirection" ), mRightGridAnnotationDirection );
264 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDirection" ), mTopGridAnnotationDirection );
265 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDirection" ), mBottomGridAnnotationDirection );
266 mapGridElem.setAttribute( QStringLiteral(
"frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) );
267 mapGridElem.appendChild(
QgsFontUtils::toXmlElement( mGridAnnotationFont, doc, QStringLiteral(
"annotationFontProperties" ) ) );
269 mapGridElem.setAttribute( QStringLiteral(
"annotationPrecision" ), mGridAnnotationPrecision );
270 mapGridElem.setAttribute( QStringLiteral(
"unit" ), mGridUnit );
271 mapGridElem.setAttribute( QStringLiteral(
"blendMode" ), mBlendMode );
274 elem.appendChild( mapGridElem );
281 if ( itemElem.isNull() )
290 mGridIntervalX = itemElem.attribute( QStringLiteral(
"intervalX" ), QStringLiteral(
"0" ) ).toDouble();
291 mGridIntervalY = itemElem.attribute( QStringLiteral(
"intervalY" ), QStringLiteral(
"0" ) ).toDouble();
292 mGridOffsetX = itemElem.attribute( QStringLiteral(
"offsetX" ), QStringLiteral(
"0" ) ).toDouble();
293 mGridOffsetY = itemElem.attribute( QStringLiteral(
"offsetY" ), QStringLiteral(
"0" ) ).toDouble();
294 mCrossLength = itemElem.attribute( QStringLiteral(
"crossLength" ), QStringLiteral(
"3" ) ).toDouble();
295 mGridFrameStyle =
static_cast< QgsLayoutItemMapGrid::FrameStyle >( itemElem.attribute( QStringLiteral(
"gridFrameStyle" ), QStringLiteral(
"0" ) ).toInt() );
296 mGridFrameSides =
static_cast< QgsLayoutItemMapGrid::FrameSideFlags
>( itemElem.attribute( QStringLiteral(
"gridFrameSideFlags" ), QStringLiteral(
"15" ) ).toInt() );
297 mGridFrameWidth = itemElem.attribute( QStringLiteral(
"gridFrameWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
298 mGridFrameMargin = itemElem.attribute( QStringLiteral(
"gridFrameMargin" ), QStringLiteral(
"0.0" ) ).toDouble();
299 mGridFramePenThickness = itemElem.attribute( QStringLiteral(
"gridFramePenThickness" ), QStringLiteral(
"0.3" ) ).toDouble();
308 QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral(
"lineStyle" ) );
309 if ( !lineStyleElem.isNull() )
311 QDomElement symbolElem = lineStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
312 if ( !symbolElem.isNull() )
314 mGridLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
321 mGridLineSymbol->setWidth( itemElem.attribute( QStringLiteral(
"penWidth" ), QStringLiteral(
"0" ) ).toDouble() );
322 mGridLineSymbol->setColor( QColor( itemElem.attribute( QStringLiteral(
"penColorRed" ), QStringLiteral(
"0" ) ).toInt(),
323 itemElem.attribute( QStringLiteral(
"penColorGreen" ), QStringLiteral(
"0" ) ).toInt(),
324 itemElem.attribute( QStringLiteral(
"penColorBlue" ), QStringLiteral(
"0" ) ).toInt() ) );
327 QDomElement markerStyleElem = itemElem.firstChildElement( QStringLiteral(
"markerStyle" ) );
328 if ( !markerStyleElem.isNull() )
330 QDomElement symbolElem = markerStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
331 if ( !symbolElem.isNull() )
333 mGridMarkerSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context ) );
337 if ( !mCRS.
readXml( itemElem ) )
340 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( QStringLiteral(
"blendMode" ), QStringLiteral(
"0" ) ).toUInt() );
343 mShowGridAnnotation = ( itemElem.attribute( QStringLiteral(
"showAnnotation" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
345 mGridAnnotationExpressionString = itemElem.attribute( QStringLiteral(
"annotationExpression" ) );
346 mGridAnnotationExpression.reset();
351 mLeftGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"leftAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
352 mRightGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"rightAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
354 mBottomGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"bottomAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
360 mAnnotationFrameDistance = itemElem.attribute( QStringLiteral(
"frameAnnotationDistance" ), QStringLiteral(
"0" ) ).toDouble();
363 mGridAnnotationFont.fromString( itemElem.attribute( QStringLiteral(
"annotationFont" ), QString() ) );
365 mGridAnnotationFontColor =
QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral(
"annotationFontColor" ), QStringLiteral(
"0,0,0,255" ) ) );
366 mGridAnnotationPrecision = itemElem.attribute( QStringLiteral(
"annotationPrecision" ), QStringLiteral(
"3" ) ).toInt();
367 int gridUnitInt = itemElem.attribute( QStringLiteral(
"unit" ), QString::number(
MapUnit ) ).toInt();
368 mGridUnit = ( gridUnitInt <= static_cast< int >(
CM ) ) ?
static_cast< GridUnit >( gridUnitInt ) :
MapUnit;
375 mTransformDirty =
true;
380 return mBlendMode != QPainter::CompositionMode_SourceOver;
383 QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const 385 QTransform t = QTransform::fromScale( scale, scale );
386 return t.map( polygon );
389 void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM, QList< QPair< double, QLineF > > &horizontalLines,
390 QList< QPair< double, QLineF > > &verticalLines,
bool calculateLinesOnly )
const 399 if ( mapPolygon != mPrevMapPolygon )
401 mTransformDirty =
true;
402 mPrevMapPolygon = mapPolygon;
405 if ( mTransformDirty )
407 calculateCrsTransformLines();
411 if ( !calculateLinesOnly )
415 QList< QPair< double, QPolygonF > >::const_iterator xGridIt = mTransformedXLines.constBegin();
416 for ( ; xGridIt != mTransformedXLines.constEnd(); ++xGridIt )
418 drawGridLine( scalePolygon( xGridIt->second, dotsPerMM ), context );
421 QList< QPair< double, QPolygonF > >::const_iterator yGridIt = mTransformedYLines.constBegin();
422 for ( ; yGridIt != mTransformedYLines.constEnd(); ++yGridIt )
424 drawGridLine( scalePolygon( yGridIt->second, dotsPerMM ), context );
429 double maxX =
mMap->rect().width();
430 double maxY =
mMap->rect().height();
432 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
433 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
435 double x = intersectionIt->x();
436 double y = intersectionIt->y();
440 QLineF line1 = QLineF( x - mCrossLength, y, x + mCrossLength, y );
441 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
442 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
443 QLineF line2 = QLineF( x, y - mCrossLength, x, y + mCrossLength );
444 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
445 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
448 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
449 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
453 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
460 QList< QPair< double, QPolygonF > >::const_iterator yGridLineIt = mTransformedYLines.constBegin();
461 for ( ; yGridLineIt != mTransformedYLines.constEnd(); ++yGridLineIt )
463 verticalLines.push_back( qMakePair( yGridLineIt->first, QLineF( yGridLineIt->second.first(), yGridLineIt->second.last() ) ) );
465 QList< QPair< double, QPolygonF > >::const_iterator xGridLineIt = mTransformedXLines.constBegin();
466 for ( ; xGridLineIt != mTransformedXLines.constEnd(); ++xGridLineIt )
468 horizontalLines.push_back( qMakePair( xGridLineIt->first, QLineF( xGridLineIt->second.first(), xGridLineIt->second.last() ) ) );
472 void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const 476 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
482 mTransformedXLines.clear();
483 xGridLinesCrsTransform( crsBoundingRect, inverseTr, mTransformedXLines );
486 mTransformedYLines.clear();
487 yGridLinesCrsTransform( crsBoundingRect, inverseTr, mTransformedYLines );
494 QList< QgsGeometry > yLines;
495 QList< QPair< double, QPolygonF > >::const_iterator yGridIt = mTransformedYLines.constBegin();
496 for ( ; yGridIt != mTransformedYLines.constEnd(); ++yGridIt )
499 for (
int i = 0; i < ( *yGridIt ).second.size(); ++i )
501 yLine.append(
QgsPointXY( ( *yGridIt ).second.at( i ).x(), ( *yGridIt ).second.at( i ).y() ) );
505 QList< QgsGeometry > xLines;
506 QList< QPair< double, QPolygonF > >::const_iterator xGridIt = mTransformedXLines.constBegin();
507 for ( ; xGridIt != mTransformedXLines.constEnd(); ++xGridIt )
510 for (
int i = 0; i < ( *xGridIt ).second.size(); ++i )
512 xLine.append(
QgsPointXY( ( *xGridIt ).second.at( i ).x(), ( *xGridIt ).second.at( i ).y() ) );
518 mTransformedIntersections.clear();
519 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
520 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
522 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
523 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
527 if ( intersects.
isNull() )
535 mTransformedIntersections << vertex;
543 mTransformDirty =
false;
552 QPaintDevice *paintDevice = p->device();
559 p->setCompositionMode( mBlendMode );
562 QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
563 p->setClipRect( thisPaintRect );
564 if ( thisPaintRect != mPrevPaintRect )
567 mTransformDirty =
true;
568 mPrevPaintRect = thisPaintRect;
572 double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
573 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
581 QList< QPair< double, QLineF > > verticalLines;
582 QList< QPair< double, QLineF > > horizontalLines;
587 drawGridCrsTransform( context, dotsPerMM, horizontalLines, verticalLines );
591 drawGridNoTransform( context, dotsPerMM, horizontalLines, verticalLines );
596 p->setClipping(
false );
600 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
605 drawGridFrame( p, horizontalLines, verticalLines );
608 if ( mShowGridAnnotation )
610 drawCoordinateAnnotations( p, horizontalLines, verticalLines, context.
expressionContext() );
614 void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM, QList< QPair< double, QLineF > > &horizontalLines,
615 QList< QPair< double, QLineF > > &verticalLines,
bool calculateLinesOnly )
const 618 yGridLines( verticalLines );
619 xGridLines( horizontalLines );
621 if ( calculateLinesOnly )
624 QList< QPair< double, QLineF > >::const_iterator vIt = verticalLines.constBegin();
625 QList< QPair< double, QLineF > >::const_iterator hIt = horizontalLines.constBegin();
633 for ( ; vIt != verticalLines.constEnd(); ++vIt )
635 line = QLineF( vIt->second.p1() * dotsPerMM, vIt->second.p2() * dotsPerMM );
636 drawGridLine( line, context );
639 for ( ; hIt != horizontalLines.constEnd(); ++hIt )
641 line = QLineF( hIt->second.p1() * dotsPerMM, hIt->second.p2() * dotsPerMM );
642 drawGridLine( line, context );
647 QPointF intersectionPoint, crossEnd1, crossEnd2;
648 for ( ; vIt != verticalLines.constEnd(); ++vIt )
651 hIt = horizontalLines.constBegin();
652 for ( ; hIt != horizontalLines.constEnd(); ++hIt )
654 if ( hIt->second.intersect( vIt->second, &intersectionPoint ) == QLineF::BoundedIntersection )
659 crossEnd1 = ( ( intersectionPoint - vIt->second.p1() ).manhattanLength() > 0.01 ) ?
661 crossEnd2 = ( ( intersectionPoint - vIt->second.p2() ).manhattanLength() > 0.01 ) ?
664 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
668 drawGridMarker( intersectionPoint * dotsPerMM, context );
680 hIt = horizontalLines.constBegin();
681 for ( ; hIt != horizontalLines.constEnd(); ++hIt )
683 vIt = verticalLines.constBegin();
684 for ( ; vIt != verticalLines.constEnd(); ++vIt )
686 if ( vIt->second.intersect( hIt->second, &intersectionPoint ) == QLineF::BoundedIntersection )
689 crossEnd1 = ( ( intersectionPoint - hIt->second.p1() ).manhattanLength() > 0.01 ) ?
691 crossEnd2 = ( ( intersectionPoint - hIt->second.p2() ).manhattanLength() > 0.01 ) ?
694 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
701 void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p,
const QList< QPair< double, QLineF > > &hLines,
const QList< QPair< double, QLineF > > &vLines, GridExtension *extension )
const 706 p->setRenderHint( QPainter::Antialiasing );
710 QMap< double, double > leftGridFrame;
711 QMap< double, double > rightGridFrame;
712 QMap< double, double > topGridFrame;
713 QMap< double, double > bottomGridFrame;
715 sortGridLinesOnBorders( hLines, vLines, leftGridFrame, rightGridFrame, topGridFrame, bottomGridFrame );
737 void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const 740 poly << line.p1() << line.p2();
741 drawGridLine( poly, context );
744 void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const 751 mGridLineSymbol->startRender( context );
752 mGridLineSymbol->renderPolyline( line,
nullptr, context );
753 mGridLineSymbol->stopRender( context );
756 void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const 763 mGridMarkerSymbol->startRender( context );
764 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
765 mGridMarkerSymbol->stopRender( context );
768 void QgsLayoutItemMapGrid::drawGridFrameBorder( QPainter *p,
const QMap< double, double > &borderPos,
QgsLayoutItemMapGrid::BorderSide border,
double *extension )
const 775 switch ( mGridFrameStyle )
779 drawGridFrameZebraBorder( p, borderPos, border, extension );
784 drawGridFrameTicks( p, borderPos, border, extension );
789 drawGridFrameLineBorder( p, border, extension );
798 void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p,
const QMap< double, double > &borderPos,
QgsLayoutItemMapGrid::BorderSide border,
double *extension )
const 807 *extension = mGridFrameMargin + mGridFrameWidth + mGridFramePenThickness / 2.0;
811 QMap< double, double > pos = borderPos;
813 double currentCoord = 0.0;
820 bool drawTLBox =
false;
821 bool drawTRBox =
false;
822 bool drawBLBox =
false;
823 bool drawBRBox =
false;
827 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
843 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
847 QPen framePen = QPen( mGridFramePenColor );
848 framePen.setWidthF( mGridFramePenThickness );
849 framePen.setJoinStyle( Qt::MiterJoin );
850 p->setPen( framePen );
852 QMap< double, double >::const_iterator posIt = pos.constBegin();
853 for ( ; posIt != pos.constEnd(); ++posIt )
855 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
858 height = posIt.key() - currentCoord;
859 width = mGridFrameWidth;
865 height = mGridFrameWidth;
866 width = posIt.key() - currentCoord;
870 p->drawRect( QRectF( x, y, width, height ) );
871 currentCoord = posIt.key();
878 width = height = ( mGridFrameWidth + mGridFrameMargin ) ;
879 p->setBrush( QBrush( mGridFrameFillColor1 ) );
881 p->drawRect( QRectF( -( mGridFrameWidth + mGridFrameMargin ), -( mGridFrameWidth + mGridFrameMargin ), width, height ) );
883 p->drawRect( QRectF(
mMap->rect().width(), -( mGridFrameWidth + mGridFrameMargin ), width, height ) );
885 p->drawRect( QRectF( -( mGridFrameWidth + mGridFrameMargin ),
mMap->rect().height(), width, height ) );
887 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
891 void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p,
const QMap< double, double > &borderPos,
QgsLayoutItemMapGrid::BorderSide border,
double *extension )
const 901 *extension = mGridFrameMargin + mGridFrameWidth;
911 QPen framePen = QPen( mGridFramePenColor );
912 framePen.setWidthF( mGridFramePenThickness );
913 framePen.setCapStyle( Qt::FlatCap );
914 p->setBrush( Qt::NoBrush );
915 p->setPen( framePen );
917 QMap< double, double >::const_iterator posIt = borderPos.constBegin();
918 for ( ; posIt != borderPos.constEnd(); ++posIt )
926 width = mGridFrameWidth;
931 width = mGridFrameWidth;
936 width = mGridFrameWidth * 2;
946 height = mGridFrameWidth;
951 height = mGridFrameWidth;
956 height = mGridFrameWidth * 2;
957 y = ( border ==
QgsLayoutItemMapGrid::Top ) ? -mGridFrameWidth - mGridFrameMargin :
mMap->rect().height() - mGridFrameWidth + mGridFrameMargin;
960 p->drawLine( QLineF( x, y, x + width, y + height ) );
973 *extension = mGridFrameMargin + mGridFramePenThickness / 2.0;
978 QPen framePen = QPen( mGridFramePenColor );
979 framePen.setWidthF( mGridFramePenThickness );
980 framePen.setCapStyle( Qt::SquareCap );
981 p->setBrush( Qt::NoBrush );
982 p->setPen( framePen );
989 p->drawLine( QLineF( 0 - mGridFrameMargin, 0 - mGridFrameMargin, 0 - mGridFrameMargin,
mMap->rect().height() + mGridFrameMargin ) );
993 const double X1 = 0 - mGridFrameMargin + mGridFramePenThickness / 2.0;
994 const double Y1 = 0 - mGridFrameMargin + mGridFramePenThickness / 2.0;
995 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
999 p->drawLine( QLineF(
mMap->rect().width() + mGridFrameMargin, 0 - mGridFrameMargin,
mMap->rect().width() + mGridFrameMargin,
mMap->rect().height() + mGridFrameMargin ) );
1001 if ( drawDiagonals )
1003 const double X1 =
mMap->rect().width() + mGridFrameMargin - mGridFramePenThickness / 2.0 ;
1004 const double Y1 =
mMap->rect().height() + mGridFrameMargin - mGridFramePenThickness / 2.0 ;
1005 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1009 p->drawLine( QLineF( 0 - mGridFrameMargin, 0 - mGridFrameMargin,
mMap->rect().width() + mGridFrameMargin, 0 - mGridFrameMargin ) );
1011 if ( drawDiagonals )
1013 const double X1 =
mMap->rect().width() + mGridFrameMargin - mGridFramePenThickness / 2.0 ;
1014 const double Y1 = 0 - mGridFrameMargin + mGridFramePenThickness / 2.0 ;
1015 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1019 p->drawLine( QLineF( 0 - mGridFrameMargin,
mMap->rect().height() + mGridFrameMargin,
mMap->rect().width() + mGridFrameMargin,
mMap->rect().height() + mGridFrameMargin ) );
1021 if ( drawDiagonals )
1023 const double X1 = 0 - mGridFrameMargin + mGridFramePenThickness / 2.0 ;
1024 const double Y1 =
mMap->rect().height() + mGridFrameMargin - mGridFramePenThickness / 2.0 ;
1025 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1031 void QgsLayoutItemMapGrid::drawCoordinateAnnotations( QPainter *p,
const QList< QPair< double, QLineF > > &hLines,
const QList< QPair< double, QLineF > > &vLines,
QgsExpressionContext &expressionContext,
1032 GridExtension *extension )
const 1034 QString currentAnnotationString;
1035 QList< QPair< double, QLineF > >::const_iterator it = hLines.constBegin();
1036 for ( ; it != hLines.constEnd(); ++it )
1043 it = vLines.constBegin();
1044 for ( ; it != vLines.constEnd(); ++it )
1052 void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos,
const QString &annotationString,
const AnnotationCoordinate coordinateType, GridExtension *extension )
const 1064 double xpos = pos.x();
1065 double ypos = pos.y();
1068 double gridFrameDistance = 0;
1069 switch ( mGridFrameStyle )
1074 gridFrameDistance = mGridFrameWidth;
1081 gridFrameDistance += ( mGridFramePenThickness / 2.0 );
1098 gridFrameDistance = 0;
1105 gridFrameDistance = 0;
1109 xpos += textHeight + mAnnotationFrameDistance + gridFrameDistance;
1110 ypos += textWidth / 2.0;
1115 xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1116 ypos -= textWidth / 2.0;
1121 xpos += mAnnotationFrameDistance + gridFrameDistance;
1122 ypos += textHeight / 2.0;
1129 gridFrameDistance = 0;
1133 xpos -= ( mAnnotationFrameDistance + gridFrameDistance );
1134 ypos += textWidth / 2.0;
1137 extension->left = std::max( extension->left, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1141 xpos -= textHeight + mAnnotationFrameDistance + gridFrameDistance;
1142 ypos -= textWidth / 2.0;
1145 extension->left = std::max( extension->left, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1149 xpos -= ( textWidth + mAnnotationFrameDistance + gridFrameDistance );
1150 ypos += textHeight / 2.0;
1152 extension->left = std::max( extension->left, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1170 gridFrameDistance = 0;
1177 gridFrameDistance = 0;
1181 xpos -= mAnnotationFrameDistance + gridFrameDistance;
1182 ypos += textWidth / 2.0;
1187 xpos -= textHeight + mAnnotationFrameDistance + gridFrameDistance;
1188 ypos -= textWidth / 2.0;
1193 xpos -= textWidth + mAnnotationFrameDistance + gridFrameDistance;
1194 ypos += textHeight / 2.0;
1201 gridFrameDistance = 0;
1205 xpos += ( textHeight + mAnnotationFrameDistance + gridFrameDistance );
1206 ypos += textWidth / 2.0;
1209 extension->right = std::max( extension->right, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1213 xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1214 ypos -= textWidth / 2.0;
1217 extension->right = std::max( extension->right, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1221 xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1222 ypos += textHeight / 2.0;
1224 extension->right = std::max( extension->right, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1242 gridFrameDistance = 0;
1249 gridFrameDistance = 0;
1253 ypos -= mAnnotationFrameDistance + gridFrameDistance;
1254 xpos -= textWidth / 2.0;
1258 xpos -= textHeight / 2.0;
1259 ypos -= textWidth + mAnnotationFrameDistance + gridFrameDistance;
1264 xpos += textHeight / 2.0;
1265 ypos -= mAnnotationFrameDistance + gridFrameDistance;
1273 gridFrameDistance = 0;
1277 ypos += ( mAnnotationFrameDistance + textHeight + gridFrameDistance );
1278 xpos -= textWidth / 2.0;
1281 extension->bottom = std::max( extension->bottom, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1282 extension->left = std::max( extension->left, textWidth / 2.0 );
1283 extension->right = std::max( extension->right, textWidth / 2.0 );
1288 xpos -= textHeight / 2.0;
1289 ypos += gridFrameDistance + mAnnotationFrameDistance;
1292 extension->bottom = std::max( extension->bottom, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1296 xpos += textHeight / 2.0;
1297 ypos += ( textWidth + mAnnotationFrameDistance + gridFrameDistance );
1300 extension->bottom = std::max( extension->bottom, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1318 gridFrameDistance = 0;
1325 gridFrameDistance = 0;
1329 xpos -= textWidth / 2.0;
1330 ypos += textHeight + mAnnotationFrameDistance + gridFrameDistance;
1334 xpos -= textHeight / 2.0;
1335 ypos += mAnnotationFrameDistance + gridFrameDistance;
1340 xpos += textHeight / 2.0;
1341 ypos += textWidth + mAnnotationFrameDistance + gridFrameDistance;
1349 gridFrameDistance = 0;
1353 xpos -= textWidth / 2.0;
1354 ypos -= ( mAnnotationFrameDistance + gridFrameDistance );
1356 extension->top = std::max( extension->top, mAnnotationFrameDistance + gridFrameDistance + textHeight );
1360 xpos -= textHeight / 2.0;
1361 ypos -= textWidth + mAnnotationFrameDistance + gridFrameDistance;
1364 extension->top = std::max( extension->top, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1368 xpos += textHeight / 2.0;
1369 ypos -= ( mAnnotationFrameDistance + gridFrameDistance );
1372 extension->top = std::max( extension->top, mAnnotationFrameDistance + gridFrameDistance + textWidth );
1381 if ( extension || !p )
1384 drawAnnotation( p, QPointF( xpos, ypos ), rotation, annotationString );
1387 void QgsLayoutItemMapGrid::drawAnnotation( QPainter *p, QPointF pos,
int rotation,
const QString &annotationText )
const 1395 p->translate( pos );
1396 p->rotate( rotation );
1404 bool geographic =
false;
1418 double wrappedX = std::fmod( value, 360.0 );
1419 if ( wrappedX > 180.0 )
1421 value = wrappedX - 360.0;
1423 else if ( wrappedX < -180.0 )
1425 value = wrappedX + 360.0;
1431 return QString::number( value,
'f', mGridAnnotationPrecision );
1437 double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1441 if ( !geographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1443 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1449 if ( !geographic || coordRounded != 0.0 )
1451 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1457 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1461 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1468 if ( !mGridAnnotationExpression )
1470 mGridAnnotationExpression.reset(
new QgsExpression( mGridAnnotationExpressionString ) );
1471 mGridAnnotationExpression->prepare( &expressionContext );
1473 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1477 QgsCoordinateFormatter::FormatFlags flags =
nullptr;
1478 switch ( mGridAnnotationFormat )
1528 int QgsLayoutItemMapGrid::xGridLines( QList< QPair< double, QLineF > > &lines )
const 1531 if ( !
mMap || mGridIntervalY <= 0.0 )
1538 QRectF mapBoundingRect = mapPolygon.boundingRect();
1539 double gridIntervalY = mGridIntervalY;
1540 double gridOffsetY = mGridOffsetY;
1541 double annotationScale = 1.0;
1544 mapBoundingRect =
mMap->rect();
1545 mapPolygon = QPolygonF(
mMap->rect() );
1546 if ( mGridUnit ==
CM )
1548 annotationScale = 0.1;
1549 gridIntervalY *= 10;
1555 double roundCorrection = mapBoundingRect.top() > 0 ? 1.0 : 0.0;
1556 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1558 int gridLineCount = 0;
1563 double yCanvasCoord;
1564 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1566 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1567 lines.push_back( qMakePair( currentLevel * annotationScale, QLineF( 0, yCanvasCoord,
mMap->rect().width(), yCanvasCoord ) ) );
1568 currentLevel += gridIntervalY;
1575 QVector<QLineF> borderLines;
1576 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1577 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1578 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1579 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1581 QVector<QPointF> intersectionList;
1583 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1585 intersectionList.clear();
1586 QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1588 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1589 for ( ; it != borderLines.constEnd(); ++it )
1591 QPointF intersectionPoint;
1592 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1594 intersectionList.push_back( intersectionPoint );
1595 if ( intersectionList.size() >= 2 )
1602 if ( intersectionList.size() >= 2 )
1607 currentLevel += gridIntervalY;
1614 int QgsLayoutItemMapGrid::yGridLines( QList< QPair< double, QLineF > > &lines )
const 1617 if ( !
mMap || mGridIntervalX <= 0.0 )
1623 QRectF mapBoundingRect = mapPolygon.boundingRect();
1624 double gridIntervalX = mGridIntervalX;
1625 double gridOffsetX = mGridOffsetX;
1626 double annotationScale = 1.0;
1629 mapBoundingRect =
mMap->rect();
1630 mapPolygon = QPolygonF(
mMap->rect() );
1631 if ( mGridUnit ==
CM )
1633 annotationScale = 0.1;
1634 gridIntervalX *= 10;
1640 double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0;
1641 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1643 int gridLineCount = 0;
1647 double xCanvasCoord;
1648 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1650 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1651 lines.push_back( qMakePair( currentLevel * annotationScale, QLineF( xCanvasCoord, 0, xCanvasCoord,
mMap->rect().height() ) ) );
1652 currentLevel += gridIntervalX;
1659 QVector<QLineF> borderLines;
1660 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1661 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1662 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1663 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1665 QVector<QPointF> intersectionList;
1667 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1669 intersectionList.clear();
1670 QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1672 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1673 for ( ; it != borderLines.constEnd(); ++it )
1675 QPointF intersectionPoint;
1676 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1678 intersectionList.push_back( intersectionPoint );
1679 if ( intersectionList.size() >= 2 )
1686 if ( intersectionList.size() >= 2 )
1691 currentLevel += gridIntervalX;
1700 if ( !
mMap || mGridIntervalY <= 0.0 )
1705 double roundCorrection = bbox.
yMaximum() > 0 ? 1.0 : 0.0;
1706 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mGridOffsetY ) / mGridIntervalY + roundCorrection ) * mGridIntervalY + mGridOffsetY;
1710 double step = ( maxX - minX ) / 20;
1712 bool crosses180 =
false;
1713 bool crossed180 =
false;
1718 step = ( maxX + 360.0 - minX ) / 20;
1724 int gridLineCount = 0;
1728 double currentX = minX;
1732 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
1745 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1749 if ( crosses180 && currentX > 180.0 )
1757 QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1758 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1759 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1761 if ( !( *lineIt ).isEmpty() )
1763 lines.append( qMakePair( currentLevel, *lineIt ) );
1767 currentLevel -= mGridIntervalY;
1776 if ( !
mMap || mGridIntervalX <= 0.0 )
1781 double roundCorrection = bbox.
xMinimum() > 0 ? 1.0 : 0.0;
1782 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mGridOffsetX ) / mGridIntervalX + roundCorrection ) * mGridIntervalX + mGridOffsetX;
1786 double step = ( maxY - minY ) / 20;
1791 bool crosses180 =
false;
1792 bool crossed180 =
false;
1799 int gridLineCount = 0;
1800 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
1803 double currentY = minY;
1807 if ( currentY > maxY )
1821 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1827 QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1828 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1829 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1831 if ( !( *lineIt ).isEmpty() )
1833 lines.append( qMakePair( currentLevel, *lineIt ) );
1837 currentLevel += mGridIntervalX;
1838 if ( crosses180 && currentLevel > 180.0 )
1840 currentLevel -= 360.0;
1848 void QgsLayoutItemMapGrid::sortGridLinesOnBorders(
const QList< QPair< double, QLineF > > &hLines,
const QList< QPair< double, QLineF > > &vLines, QMap< double, double > &leftFrameEntries,
1849 QMap< double, double > &rightFrameEntries, QMap< double, double > &topFrameEntries, QMap< double, double > &bottomFrameEntries )
const 1851 QList< QgsMapAnnotation > borderPositions;
1852 QList< QPair< double, QLineF > >::const_iterator it = hLines.constBegin();
1853 for ( ; it != hLines.constEnd(); ++it )
1855 QgsMapAnnotation p1;
1856 p1.coordinate = it->first;
1857 p1.itemPosition = it->second.p1();
1859 borderPositions << p1;
1861 QgsMapAnnotation p2;
1862 p2.coordinate = it->first;
1863 p2.itemPosition = it->second.p2();
1865 borderPositions << p2;
1867 it = vLines.constBegin();
1868 for ( ; it != vLines.constEnd(); ++it )
1870 QgsMapAnnotation p1;
1871 p1.coordinate = it->first;
1872 p1.itemPosition = it->second.p1();
1874 borderPositions << p1;
1876 QgsMapAnnotation p2;
1877 p2.coordinate = it->first;
1878 p2.itemPosition = it->second.p2();
1880 borderPositions << p2;
1883 QList< QgsMapAnnotation >::const_iterator bIt = borderPositions.constBegin();
1884 for ( ; bIt != borderPositions.constEnd(); ++bIt )
1889 leftFrameEntries.insert( bIt->itemPosition.y(), bIt->coordinate );
1893 rightFrameEntries.insert( bIt->itemPosition.y(), bIt->coordinate );
1897 topFrameEntries.insert( bIt->itemPosition.x(), bIt->coordinate );
1901 bottomFrameEntries.insert( bIt->itemPosition.x(), bIt->coordinate );
1911 return shouldShowDivisionForDisplayMode( coordinate, mLeftFrameDivisions );
1913 return shouldShowDivisionForDisplayMode( coordinate, mRightFrameDivisions );
1915 return shouldShowDivisionForDisplayMode( coordinate, mTopFrameDivisions );
1917 return shouldShowDivisionForDisplayMode( coordinate, mBottomFrameDivisions );
1929 bool sortByDistance( QPair<qreal, QgsLayoutItemMapGrid::BorderSide> a, QPair<qreal, QgsLayoutItemMapGrid::BorderSide> b )
1931 return a.first < b.first;
1944 if ( ( p.y() <= tolerance && p.x() <= tolerance )
1945 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
1946 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
1947 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
1953 if ( p.x() <= tolerance )
1964 if ( p.y() <= tolerance )
1976 QList< QPair<qreal, QgsLayoutItemMapGrid::BorderSide > > distanceToSide;
1982 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
1983 return distanceToSide.at( 0 ).second;
1988 mGridLineSymbol.reset( symbol );
1993 return mGridLineSymbol.get();
1998 return mGridLineSymbol.get();
2003 mGridMarkerSymbol.reset( symbol );
2008 return mGridMarkerSymbol.get();
2013 return mGridMarkerSymbol.get();
2021 mLeftGridAnnotationDisplay = display;
2024 mRightGridAnnotationDisplay = display;
2027 mTopGridAnnotationDisplay = display;
2030 mBottomGridAnnotationDisplay = display;
2046 return mLeftGridAnnotationDisplay;
2048 return mRightGridAnnotationDisplay;
2050 return mTopGridAnnotationDisplay;
2052 return mBottomGridAnnotationDisplay;
2054 return mBottomGridAnnotationDisplay;
2061 double bottom = 0.0;
2064 return std::max( std::max( std::max( top, right ), bottom ), left );
2084 GridExtension extension;
2087 QList< QPair< double, QLineF > > verticalLines;
2088 QList< QPair< double, QLineF > > horizontalLines;
2091 drawGridCrsTransform( context, 0, horizontalLines, verticalLines,
true );
2095 drawGridNoTransform( context, 0, horizontalLines, verticalLines,
true );
2100 drawGridFrame(
nullptr, horizontalLines, verticalLines, &extension );
2103 if ( mShowGridAnnotation )
2105 drawCoordinateAnnotations(
nullptr, horizontalLines, verticalLines, context.
expressionContext(), &extension );
2108 top = extension.top;
2109 right = extension.right;
2110 bottom = extension.bottom;
2111 left = extension.left;
2116 if ( unit == mGridUnit )
2121 mTransformDirty =
true;
2130 mGridIntervalX = interval;
2131 mTransformDirty =
true;
2140 mGridIntervalY = interval;
2141 mTransformDirty =
true;
2150 mGridOffsetX = offset;
2151 mTransformDirty =
true;
2160 mGridOffsetY = offset;
2161 mTransformDirty =
true;
2166 if ( style == mGridStyle )
2171 mTransformDirty =
true;
2179 mLeftGridAnnotationDirection = direction;
2182 mRightGridAnnotationDirection = direction;
2185 mTopGridAnnotationDirection = direction;
2188 mBottomGridAnnotationDirection = direction;
2201 mGridFrameSides = flags;
2207 mGridFrameSides |= flag;
2209 mGridFrameSides &= ~flag;
2214 return mGridFrameSides;
2223 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"grid_number" ) << QStringLiteral(
"grid_axis" ) );
2229 return mGridFrameSides.testFlag( flag );
2234 mLeftGridAnnotationDirection = direction;
2235 mRightGridAnnotationDirection = direction;
2236 mTopGridAnnotationDirection = direction;
2237 mBottomGridAnnotationDirection = direction;
2245 mLeftGridAnnotationPosition = position;
2248 mRightGridAnnotationPosition = position;
2251 mTopGridAnnotationPosition = position;
2254 mBottomGridAnnotationPosition = position;
2270 return mLeftGridAnnotationPosition;
2272 return mRightGridAnnotationPosition;
2274 return mTopGridAnnotationPosition;
2276 return mBottomGridAnnotationPosition;
2278 return mLeftGridAnnotationPosition;
2285 return mLeftGridAnnotationDirection;
2291 return mLeftGridAnnotationDirection;
2293 return mRightGridAnnotationDirection;
2295 return mTopGridAnnotationDirection;
2297 return mBottomGridAnnotationDirection;
2299 return mLeftGridAnnotationDirection;
2307 mLeftFrameDivisions = divisions;
2310 mRightFrameDivisions = divisions;
2313 mTopFrameDivisions = divisions;
2316 mBottomFrameDivisions = divisions;
2331 return mLeftFrameDivisions;
2333 return mRightFrameDivisions;
2335 return mTopFrameDivisions;
2337 return mBottomFrameDivisions;
2339 return mLeftFrameDivisions;
2353 QRectF mbr = mapPolygon.boundingRect();
2354 QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2360 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2361 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2363 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2364 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2366 if ( lowerLeft.x() > upperRight.x() )
2374 crsRect = tr.transformBoundingBox( mapBoundingRect );
2379 crsRect = tr.transformBoundingBox( mapBoundingRect );
2387 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
2393 QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2401 QList<QPolygonF> trimmedLines;
2402 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2403 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2405 trimmedLines << ( *geomIt ).asQPolygonF();
2407 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)
The class is used as a container of context for various read/write operations on other objects...
bool testFrameSideFlag(FrameSideFlag flag) const
Tests whether the grid frame should be drawn on a specified side of the map item. ...
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.
QPointF mapToItemCoords(QPointF mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset) ...
void draw(QPainter *painter) override
Draws the item on to a destination painter.
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:
AnnotationDirection annotationDirection(BorderSide border) const
Returns the direction for drawing frame annotations, on the specified side of the map...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Coordinate is a longitude value.
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.
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)
double maxGridExtension() const
Calculates the maximum distance grids within the stack extend beyond the QgsLayoutItemMap's item rect...
void setGridLineWidth(double width)
Sets the width of grid lines (in layout units).
bool frameEnabled() const
Returns true if the item includes a frame.
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.
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.
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.
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
Degree/minutes, use NSEW suffix.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
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.
const QgsLineSymbol * lineSymbol() const
Returns the line symbol used for drawing grid lines.
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...
QgsLayoutItemMapGrid * grid(const QString &gridId) const
Returns a reference to a grid with matching gridId within the stack.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used for drawing grid points.
static QString encodeColor(const QColor &color)
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
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.
AnnotationPosition annotationPosition(BorderSide side) const
Returns the position for the grid annotations on a specified side of the map frame.
Custom expression-based format.
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...
const QgsLayout * layout() const
Returns the layout the object is attached to.
Grid units in centimeters.
QgsLayoutRenderContext::Flags flags() const
Returns the current combination of flags used for rendering the layout.
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.
Decimal degrees, use NSEW suffix.
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 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...
Show latitude/y annotations/divisions only.
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.
DisplayMode annotationDisplay(BorderSide border) const
Returns the display mode for the grid annotations on a specified side of the map frame.
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.
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.
const QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol used for drawing grid points.
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...
double maxExtension() const
Calculates the maximum distance the grid extends beyond the QgsLayoutItemMap's item rect (in layout u...
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.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
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...
double xMaximum() const
Returns the x maximum value (right side of rectangle).
void moveGridUp(const QString &gridId)
Moves a grid with matching gridId up the stack, causing it to be rendered above other grids...
DisplayMode frameDivisions(BorderSide side) const
Returns the type of grid divisions which are used for frames on a specified side of the map...
AnnotationCoordinate
Annotation coordinate type.
BorderSide
Border sides for annotations.
void setGridLineColor(const QColor &color)
Sets the color of grid lines.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Contains information about the context of a rendering operation.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Degree/minutes/seconds, with minutes using leading zeros where required.
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.
QgsLayoutItemMapItem * item(const QString &itemId) const
Returns a reference to an item which matching itemId within the stack.
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...
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Draw markers at intersections of grid lines.
QgsLayoutItemMapGrid::FrameSideFlags frameSideFlags() const
Returns the flags which control which sides of the map item the grid frame is drawn on...
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.
Black/white pattern, with nautical style diagonals on corners.
QList< QgsLayoutItemMapGrid *> asList() const
Returns a list of QgsLayoutItemMapGrids contained by the stack.
Degree/minutes, with minutes using leading zeros where required.
This class represents a coordinate reference system (CRS).
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.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
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...
double yMaximum() const
Returns the y maximum value (top side of rectangle).
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.
Simple solid line frame, with nautical style diagonals on corners.
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.
void moveItemDown(const QString &itemId)
Moves an item which matching itemId up the stack, causing it to be rendered above other items...
QList< QgsLayoutItemMapItem *> mItems
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
GridStyle style() const
Returns the grid's style, which controls how the grid is drawn over the map's contents.
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 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.
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.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
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...
static QColor decodeColor(const QString &str)
QgsCoordinateReferenceSystem crs() const
Retrieves the CRS for the grid.
Degree/minutes/seconds, use - for S/W coordinates.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Tick markers drawn outside map frame.