47 #define MAX_GRID_LINES 1000 //maximum number of horizontal or vertical grid lines to draw
78 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
84 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
89 QList< QgsLayoutItemMapGrid * > list;
112 QDomNodeList mapGridNodeList = elem.elementsByTagName( QStringLiteral(
"ComposerMapGrid" ) );
113 for (
int i = 0; i < mapGridNodeList.size(); ++i )
115 QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
117 mapGrid->
readXml( mapGridElem, doc, context );
131 return std::max( std::max( std::max( top, right ), bottom ), left );
145 double gridTop = 0.0;
146 double gridRight = 0.0;
147 double gridBottom = 0.0;
148 double gridLeft = 0.0;
150 top = std::max( top, gridTop );
151 right = std::max( right, gridRight );
152 bottom = std::max( bottom, gridBottom );
153 left = std::max( left, gridLeft );
169 return QVector2D( 0, 1 );
171 return QVector2D( -1, 0 );
173 return QVector2D( 0, -1 );
175 return QVector2D( 1, 0 );
183 return QVector2D( borderVector.y(), -borderVector.x() );
193 QString defaultFontString = settings.
value( QStringLiteral(
"LayoutDesigner/defaultFont" ), QVariant(),
QgsSettings::Gui ).toString();
194 if ( !defaultFontString.isEmpty() )
197 font.setFamily( defaultFontString );
198 mAnnotationFormat.
setFont( font );
201 createDefaultGridLineSymbol();
202 createDefaultGridMarkerSymbol();
208 void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
211 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
212 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
213 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"flat" ) );
217 void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
220 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"circle" ) );
221 properties.insert( QStringLiteral(
"size" ), QStringLiteral(
"2.0" ) );
222 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
228 if ( mGridLineSymbol )
230 mGridLineSymbol->setWidth( width );
236 if ( mGridLineSymbol )
238 mGridLineSymbol->setColor(
c );
249 QDomElement mapGridElem = doc.createElement( QStringLiteral(
"ComposerMapGrid" ) );
250 mapGridElem.setAttribute( QStringLiteral(
"gridStyle" ), mGridStyle );
251 mapGridElem.setAttribute( QStringLiteral(
"intervalX" ),
qgsDoubleToString( mGridIntervalX ) );
252 mapGridElem.setAttribute( QStringLiteral(
"intervalY" ),
qgsDoubleToString( mGridIntervalY ) );
253 mapGridElem.setAttribute( QStringLiteral(
"offsetX" ),
qgsDoubleToString( mGridOffsetX ) );
254 mapGridElem.setAttribute( QStringLiteral(
"offsetY" ),
qgsDoubleToString( mGridOffsetY ) );
255 mapGridElem.setAttribute( QStringLiteral(
"crossLength" ),
qgsDoubleToString( mCrossLength ) );
257 QDomElement lineStyleElem = doc.createElement( QStringLiteral(
"lineStyle" ) );
259 lineStyleElem.appendChild( gridLineStyleElem );
260 mapGridElem.appendChild( lineStyleElem );
262 QDomElement markerStyleElem = doc.createElement( QStringLiteral(
"markerStyle" ) );
264 markerStyleElem.appendChild( gridMarkerStyleElem );
265 mapGridElem.appendChild( markerStyleElem );
267 mapGridElem.setAttribute( QStringLiteral(
"gridFrameStyle" ), mGridFrameStyle );
268 mapGridElem.setAttribute( QStringLiteral(
"gridFrameSideFlags" ), mGridFrameSides );
269 mapGridElem.setAttribute( QStringLiteral(
"gridFrameWidth" ),
qgsDoubleToString( mGridFrameWidth ) );
270 mapGridElem.setAttribute( QStringLiteral(
"gridFrameMargin" ),
qgsDoubleToString( mGridFrameMargin ) );
271 mapGridElem.setAttribute( QStringLiteral(
"gridFramePenThickness" ),
qgsDoubleToString( mGridFramePenThickness ) );
275 mapGridElem.setAttribute( QStringLiteral(
"leftFrameDivisions" ), mLeftFrameDivisions );
276 mapGridElem.setAttribute( QStringLiteral(
"rightFrameDivisions" ), mRightFrameDivisions );
277 mapGridElem.setAttribute( QStringLiteral(
"topFrameDivisions" ), mTopFrameDivisions );
278 mapGridElem.setAttribute( QStringLiteral(
"bottomFrameDivisions" ), mBottomFrameDivisions );
279 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksLengthMode" ), mRotatedTicksLengthMode );
280 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksEnabled" ), mRotatedTicksEnabled );
281 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksMinimumAngle" ), QString::number( mRotatedTicksMinimumAngle ) );
282 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksMarginToCorner" ), QString::number( mRotatedTicksMarginToCorner ) );
283 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsLengthMode" ), mRotatedAnnotationsLengthMode );
284 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsEnabled" ), mRotatedAnnotationsEnabled );
285 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsMinimumAngle" ), QString::number( mRotatedAnnotationsMinimumAngle ) );
286 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsMarginToCorner" ), QString::number( mRotatedAnnotationsMarginToCorner ) );
292 mapGridElem.setAttribute( QStringLiteral(
"annotationFormat" ), mGridAnnotationFormat );
293 mapGridElem.setAttribute( QStringLiteral(
"showAnnotation" ), mShowGridAnnotation );
294 mapGridElem.setAttribute( QStringLiteral(
"annotationExpression" ), mGridAnnotationExpressionString );
295 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDisplay" ), mLeftGridAnnotationDisplay );
296 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDisplay" ), mRightGridAnnotationDisplay );
297 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDisplay" ), mTopGridAnnotationDisplay );
298 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDisplay" ), mBottomGridAnnotationDisplay );
299 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationPosition" ), mLeftGridAnnotationPosition );
300 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationPosition" ), mRightGridAnnotationPosition );
301 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationPosition" ), mTopGridAnnotationPosition );
302 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationPosition" ), mBottomGridAnnotationPosition );
303 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDirection" ), mLeftGridAnnotationDirection );
304 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDirection" ), mRightGridAnnotationDirection );
305 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDirection" ), mTopGridAnnotationDirection );
306 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDirection" ), mBottomGridAnnotationDirection );
307 mapGridElem.setAttribute( QStringLiteral(
"frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) );
308 mapGridElem.appendChild( mAnnotationFormat.
writeXml( doc, context ) );
309 mapGridElem.setAttribute( QStringLiteral(
"annotationPrecision" ), mGridAnnotationPrecision );
310 mapGridElem.setAttribute( QStringLiteral(
"unit" ), mGridUnit );
311 mapGridElem.setAttribute( QStringLiteral(
"blendMode" ), mBlendMode );
312 mapGridElem.setAttribute( QStringLiteral(
"minimumIntervalWidth" ), QString::number( mMinimumIntervalWidth ) );
313 mapGridElem.setAttribute( QStringLiteral(
"maximumIntervalWidth" ), QString::number( mMaximumIntervalWidth ) );
316 elem.appendChild( mapGridElem );
323 if ( itemElem.isNull() )
332 mGridIntervalX = itemElem.attribute( QStringLiteral(
"intervalX" ), QStringLiteral(
"0" ) ).toDouble();
333 mGridIntervalY = itemElem.attribute( QStringLiteral(
"intervalY" ), QStringLiteral(
"0" ) ).toDouble();
334 mGridOffsetX = itemElem.attribute( QStringLiteral(
"offsetX" ), QStringLiteral(
"0" ) ).toDouble();
335 mGridOffsetY = itemElem.attribute( QStringLiteral(
"offsetY" ), QStringLiteral(
"0" ) ).toDouble();
336 mCrossLength = itemElem.attribute( QStringLiteral(
"crossLength" ), QStringLiteral(
"3" ) ).toDouble();
337 mGridFrameStyle =
static_cast< QgsLayoutItemMapGrid::FrameStyle >( itemElem.attribute( QStringLiteral(
"gridFrameStyle" ), QStringLiteral(
"0" ) ).toInt() );
338 mGridFrameSides =
static_cast< QgsLayoutItemMapGrid::FrameSideFlags
>( itemElem.attribute( QStringLiteral(
"gridFrameSideFlags" ), QStringLiteral(
"15" ) ).toInt() );
339 mGridFrameWidth = itemElem.attribute( QStringLiteral(
"gridFrameWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
340 mGridFrameMargin = itemElem.attribute( QStringLiteral(
"gridFrameMargin" ), QStringLiteral(
"0.0" ) ).toDouble();
341 mGridFramePenThickness = itemElem.attribute( QStringLiteral(
"gridFramePenThickness" ), QStringLiteral(
"0.3" ) ).toDouble();
349 mRotatedTicksLengthMode =
TickLengthMode( itemElem.attribute( QStringLiteral(
"rotatedTicksLengthMode" ), QStringLiteral(
"0" ) ).toInt() );
350 mRotatedTicksEnabled = itemElem.attribute( QStringLiteral(
"rotatedTicksEnabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
351 mRotatedTicksMinimumAngle = itemElem.attribute( QStringLiteral(
"rotatedTicksMinimumAngle" ), QStringLiteral(
"0" ) ).toDouble();
352 mRotatedTicksMarginToCorner = itemElem.attribute( QStringLiteral(
"rotatedTicksMarginToCorner" ), QStringLiteral(
"0" ) ).toDouble();
353 mRotatedAnnotationsLengthMode =
TickLengthMode( itemElem.attribute( QStringLiteral(
"rotatedAnnotationsLengthMode" ), QStringLiteral(
"0" ) ).toInt() );
354 mRotatedAnnotationsEnabled = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsEnabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
355 mRotatedAnnotationsMinimumAngle = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsMinimumAngle" ), QStringLiteral(
"0" ) ).toDouble();
356 mRotatedAnnotationsMarginToCorner = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsMarginToCorner" ), QStringLiteral(
"0" ) ).toDouble();
358 QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral(
"lineStyle" ) );
359 if ( !lineStyleElem.isNull() )
361 QDomElement symbolElem = lineStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
362 if ( !symbolElem.isNull() )
364 mGridLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
371 mGridLineSymbol->setWidth( itemElem.attribute( QStringLiteral(
"penWidth" ), QStringLiteral(
"0" ) ).toDouble() );
372 mGridLineSymbol->setColor( QColor( itemElem.attribute( QStringLiteral(
"penColorRed" ), QStringLiteral(
"0" ) ).toInt(),
373 itemElem.attribute( QStringLiteral(
"penColorGreen" ), QStringLiteral(
"0" ) ).toInt(),
374 itemElem.attribute( QStringLiteral(
"penColorBlue" ), QStringLiteral(
"0" ) ).toInt() ) );
377 QDomElement markerStyleElem = itemElem.firstChildElement( QStringLiteral(
"markerStyle" ) );
378 if ( !markerStyleElem.isNull() )
380 QDomElement symbolElem = markerStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
381 if ( !symbolElem.isNull() )
383 mGridMarkerSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context ) );
387 if ( !mCRS.
readXml( itemElem ) )
390 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( QStringLiteral(
"blendMode" ), QStringLiteral(
"0" ) ).toUInt() );
393 mShowGridAnnotation = ( itemElem.attribute( QStringLiteral(
"showAnnotation" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
395 mGridAnnotationExpressionString = itemElem.attribute( QStringLiteral(
"annotationExpression" ) );
396 mGridAnnotationExpression.reset();
401 mLeftGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"leftAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
402 mRightGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"rightAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
404 mBottomGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"bottomAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
410 mAnnotationFrameDistance = itemElem.attribute( QStringLiteral(
"frameAnnotationDistance" ), QStringLiteral(
"0" ) ).toDouble();
412 if ( !itemElem.firstChildElement(
"text-style" ).isNull() )
414 mAnnotationFormat.
readXml( itemElem, context );
421 font.fromString( itemElem.attribute(
"annotationFont", QString() ) );
423 mAnnotationFormat.
setFont( font );
424 mAnnotationFormat.
setSize( font.pointSizeF() );
429 mGridAnnotationPrecision = itemElem.attribute( QStringLiteral(
"annotationPrecision" ), QStringLiteral(
"3" ) ).toInt();
430 int gridUnitInt = itemElem.attribute( QStringLiteral(
"unit" ), QString::number(
MapUnit ) ).toInt();
432 mMinimumIntervalWidth = itemElem.attribute( QStringLiteral(
"minimumIntervalWidth" ), QStringLiteral(
"50" ) ).toDouble();
433 mMaximumIntervalWidth = itemElem.attribute( QStringLiteral(
"maximumIntervalWidth" ), QStringLiteral(
"100" ) ).toDouble();
435 refreshDataDefinedProperties();
442 mTransformDirty =
true;
447 return mBlendMode != QPainter::CompositionMode_SourceOver;
450 QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
452 QTransform t = QTransform::fromScale( scale, scale );
453 return t.map( polygon );
456 void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
458 if ( !
mMap || !mEvaluatedEnabled )
465 if ( mapPolygon != mPrevMapPolygon )
467 mTransformDirty =
true;
468 mPrevMapPolygon = mapPolygon;
471 if ( mTransformDirty )
473 calculateCrsTransformLines();
477 if ( !calculateLinesOnly )
481 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
482 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
484 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
489 double maxX =
mMap->rect().width();
490 double maxY =
mMap->rect().height();
492 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
493 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
495 double x = intersectionIt->x();
496 double y = intersectionIt->y();
500 QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
501 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
502 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
503 QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
504 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
505 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
508 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
509 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
513 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
520 void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
524 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
531 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
532 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
539 QList< QgsGeometry > xLines;
540 QList< QgsGeometry > yLines;
541 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
542 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
546 for (
int i = 0; i < gridIt->line.size(); ++i )
548 line.append(
QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
550 if ( gridIt->coordinateType == AnnotationCoordinate::Longitude )
552 else if ( gridIt->coordinateType == AnnotationCoordinate::Latitude )
557 mTransformedIntersections.clear();
558 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
559 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
561 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
562 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
566 if ( intersects.
isNull() )
574 mTransformedIntersections << vertex;
582 mTransformDirty =
false;
587 if ( !
mMap || !mEvaluatedEnabled )
591 QPaintDevice *paintDevice = p->device();
598 p->setCompositionMode( mBlendMode );
601 QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
602 p->setClipRect( thisPaintRect );
603 if ( thisPaintRect != mPrevPaintRect )
606 mTransformDirty =
true;
607 mPrevPaintRect = thisPaintRect;
611 double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
612 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
628 drawGridCrsTransform( context, dotsPerMM );
635 drawGridNoTransform( context, dotsPerMM );
640 p->setClipping(
false );
644 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
649 updateGridLinesAnnotationsPositions();
656 if ( mShowGridAnnotation )
662 void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
664 QList< GridLine >::iterator it = mGridLines.begin();
665 for ( ; it != mGridLines.end(); ++it )
667 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
668 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
669 it->startAnnotation.position = QVector2D( it->line.first() );
670 it->endAnnotation.position = QVector2D( it->line.last() );
671 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
672 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
674 it->startAnnotation.angle = atan2( it->startAnnotation.vector.x() * normS.y() - it->startAnnotation.vector.y() * normS.x(), it->startAnnotation.vector.x() * normS.x() + it->startAnnotation.vector.y() * normS.y() );
676 it->endAnnotation.angle = atan2( it->endAnnotation.vector.x() * normE.y() - it->endAnnotation.vector.y() * normE.x(), it->endAnnotation.vector.x() * normE.x() + it->endAnnotation.vector.y() * normE.y() );
680 void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
687 if ( calculateLinesOnly )
690 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
691 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
699 for ( ; vIt != mGridLines.constEnd(); ++vIt )
701 if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
703 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
704 drawGridLine( line, context );
707 for ( ; hIt != mGridLines.constEnd(); ++hIt )
709 if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
711 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
712 drawGridLine( line, context );
718 QPointF intersectionPoint, crossEnd1, crossEnd2;
719 for ( ; vIt != mGridLines.constEnd(); ++vIt )
721 if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
724 l1 = QLineF( vIt->line.first(), vIt->line.last() );
727 hIt = mGridLines.constBegin();
728 for ( ; hIt != mGridLines.constEnd(); ++hIt )
730 if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
733 l2 = QLineF( hIt->line.first(), hIt->line.last() );
735 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
736 if ( l2.intersect( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
738 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
744 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
746 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
749 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
753 drawGridMarker( intersectionPoint * dotsPerMM, context );
765 hIt = mGridLines.constBegin();
766 for ( ; hIt != mGridLines.constEnd(); ++hIt )
768 if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
771 l1 = QLineF( hIt->line.first(), hIt->line.last() );
773 vIt = mGridLines.constBegin();
774 for ( ; vIt != mGridLines.constEnd(); ++vIt )
776 if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
779 l2 = QLineF( vIt->line.first(), vIt->line.last() );
781 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
782 if ( l2.intersect( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
784 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
788 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
790 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
793 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
800 void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
809 switch ( mGridFrameStyle )
813 drawGridFrameZebra( p, extension );
818 drawGridFrameTicks( p, extension );
823 drawGridFrameLine( p, extension );
834 void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
837 poly << line.p1() << line.p2();
838 drawGridLine( poly, context );
841 void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
848 mGridLineSymbol->startRender( context );
849 mGridLineSymbol->renderPolyline( line,
nullptr, context );
850 mGridLineSymbol->stopRender( context );
853 void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
860 mGridMarkerSymbol->startRender( context );
861 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
862 mGridMarkerSymbol->stopRender( context );
865 void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
885 void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p, BorderSide border,
double *extension )
const
894 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
898 double currentCoord = 0.0;
905 bool drawTLBox =
false;
906 bool drawTRBox =
false;
907 bool drawBLBox =
false;
908 bool drawBRBox =
false;
910 QMap< double, double > pos = QMap< double, double >();
911 QList< GridLine >::const_iterator it = mGridLines.constBegin();
912 for ( ; it != mGridLines.constEnd(); ++it )
915 for (
int i = 0 ; i < 2 ; ++i )
917 GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
920 if ( annot.border != border )
923 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
927 pos.insert( annot.position.y(), it->coordinate );
929 pos.insert( annot.position.x(), it->coordinate );
936 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
952 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
956 QPen framePen = QPen( mGridFramePenColor );
957 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
958 framePen.setJoinStyle( Qt::MiterJoin );
959 p->setPen( framePen );
961 QMap< double, double >::const_iterator posIt = pos.constBegin();
962 for ( ; posIt != pos.constEnd(); ++posIt )
964 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
967 height = posIt.key() - currentCoord;
968 width = mEvaluatedGridFrameWidth;
969 x = ( border ==
QgsLayoutItemMapGrid::Left ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().width() + mEvaluatedGridFrameMargin;
974 height = mEvaluatedGridFrameWidth;
975 width = posIt.key() - currentCoord;
977 y = ( border ==
QgsLayoutItemMapGrid::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
979 p->drawRect( QRectF( x, y, width, height ) );
980 currentCoord = posIt.key();
987 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) ;
988 p->setBrush( QBrush( mGridFrameFillColor1 ) );
990 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
992 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
994 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
996 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1000 void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1010 QPen framePen = QPen( mGridFramePenColor );
1011 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1012 framePen.setCapStyle( Qt::FlatCap );
1013 p->setBrush( Qt::NoBrush );
1014 p->setPen( framePen );
1017 QList< GridLine >::iterator it = mGridLines.begin();
1018 for ( ; it != mGridLines.end(); ++it )
1021 for (
int i = 0 ; i < 2 ; ++i )
1023 GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1025 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1029 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1037 facingLeft = ( annot.angle != 0 );
1038 facingRight = ( annot.angle != 0 );
1042 facingLeft = ( annot.angle > 0 );
1043 facingRight = ( annot.angle < 0 );
1047 facingLeft = ( annot.angle < 0 );
1048 facingRight = ( annot.angle > 0 );
1051 if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) ||
1052 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1054 if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ||
1055 ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1057 if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ||
1058 ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1060 if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) ||
1061 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1065 QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1067 double fA = mEvaluatedGridFrameMargin;
1068 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1070 if ( mRotatedTicksEnabled && mRotatedTicksLengthMode ==
OrthogonalTicks )
1072 fA /= QVector2D::dotProduct( vector, normalVector );
1073 fB /= QVector2D::dotProduct( vector, normalVector );
1080 extension->UpdateBorder( annot.border, fB );
1088 pA = annot.position + fA * vector;
1089 pB = annot.position + fB * vector;
1093 pA = annot.position - fA * vector;
1094 pB = annot.position - fB * vector;
1098 pA = annot.position - fB * vector;
1099 pB = annot.position + ( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1101 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1107 void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1117 QPen framePen = QPen( mGridFramePenColor );
1118 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1119 framePen.setCapStyle( Qt::SquareCap );
1120 p->setBrush( Qt::NoBrush );
1121 p->setPen( framePen );
1131 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1139 p->drawLine( QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1145 extension->UpdateBorder(
QgsLayoutItemMapGrid::Top, mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 );
1147 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1155 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1158 if ( ! extension && drawDiagonals )
1163 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1164 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1165 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1170 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1171 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1172 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1177 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1178 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1179 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1184 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1185 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1186 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1192 GridExtension *extension )
const
1194 QString currentAnnotationString;
1195 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1196 for ( ; it != mGridLines.constEnd(); ++it )
1198 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext );
1199 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1200 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1204 void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
QgsRenderContext &context, GridLineAnnotation annot,
const QString &annotationString,
const AnnotationCoordinate coordinateType, GridExtension *extension )
const
1211 if ( ! shouldShowAnnotationForSide( coordinateType, annot.border ) )
1223 double xpos = annot.position.x();
1224 double ypos = annot.position.y();
1225 QPointF anchor = QPointF();
1232 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1236 QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1239 double f = mEvaluatedAnnotationFrameDistance;
1247 f += mEvaluatedGridFrameWidth;
1248 if ( hasBorderWidth )
1249 f += mEvaluatedGridFrameLineThickness / 2.0;
1254 if ( mRotatedAnnotationsEnabled && mRotatedAnnotationsLengthMode ==
OrthogonalTicks )
1256 f /= QVector2D::dotProduct( vector, normalVector );
1259 QVector2D pos = annot.position + f * vector;
1272 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1274 if ( rotation <= -90 || rotation > 90 )
1277 anchor.setX( outside ? 0 : textWidth );
1281 anchor.setX( outside ? textWidth : 0 );
1285 anchor.setY( 0.5 * textHeight );
1287 anchor.setY( -1.5 * textHeight );
1289 anchor.setY( -0.5 * textHeight );
1295 anchor.setX( 0.5 * textWidth );
1296 anchor.setY( -0.5 * textHeight );
1298 anchor.setY( outside ? 0 : -textHeight );
1300 anchor.setX( outside ? 0 : textWidth );
1302 anchor.setY( outside ? -textHeight : 0 );
1304 anchor.setX( outside ? textWidth : 0 );
1309 anchor.setX( 0.5 * textWidth );
1310 anchor.setY( -0.5 * textHeight );
1312 anchor.setX( outside ? 0 : textWidth );
1314 anchor.setY( outside ? -textHeight : 0 );
1316 anchor.setX( outside ? textWidth : 0 );
1318 anchor.setY( outside ? 0 : -textHeight );
1323 anchor.setX( 0.5 * textWidth );
1324 anchor.setY( -0.5 * textHeight );
1326 anchor.setX( outside ? textWidth : 0 );
1328 anchor.setY( outside ? 0 : -textHeight );
1330 anchor.setX( outside ? 0 : textWidth );
1332 anchor.setY( outside ? -textHeight : 0 );
1337 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1338 anchor.setX( 0.5 * textWidth );
1340 anchor.setY( -textHeight );
1348 extension->UpdateBorder( frameBorder, -f + textWidth );
1350 extension->UpdateAll( textWidth / 2.0 );
1353 if ( extension || !context.
painter() )
1357 bool facingLeft = ( annot.angle < 0 );
1358 bool facingRight = ( annot.angle > 0 );
1361 facingLeft = !facingLeft;
1362 facingRight = !facingRight;
1364 if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ||
1365 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
1367 if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ||
1368 ( facingRight && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ) )
1370 if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ||
1371 ( facingRight && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ) )
1373 if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ||
1374 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
1378 context.
painter()->translate( QPointF( xpos, ypos ) );
1379 context.
painter()->rotate( rotation );
1380 context.
painter()->translate( -anchor );
1388 bool geographic =
false;
1402 double wrappedX = std::fmod( value, 360.0 );
1403 if ( wrappedX > 180.0 )
1405 value = wrappedX - 360.0;
1407 else if ( wrappedX < -180.0 )
1409 value = wrappedX + 360.0;
1415 return QString::number( value,
'f', mGridAnnotationPrecision );
1421 double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1425 if ( !geographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1427 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1433 if ( !geographic || coordRounded != 0.0 )
1435 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1441 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1445 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1452 if ( !mGridAnnotationExpression )
1454 mGridAnnotationExpression.reset(
new QgsExpression( mGridAnnotationExpressionString ) );
1455 mGridAnnotationExpression->prepare( &expressionContext );
1457 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1461 QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FormatFlags();
1462 switch ( mGridAnnotationFormat )
1481 flags = QgsCoordinateFormatter::FormatFlags();
1491 flags = QgsCoordinateFormatter::FormatFlags();
1512 int QgsLayoutItemMapGrid::xGridLines()
const
1514 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1521 QRectF mapBoundingRect = mapPolygon.boundingRect();
1522 double gridIntervalY = mEvaluatedIntervalY;
1523 double gridOffsetY = mEvaluatedOffsetY;
1524 double annotationScale = 1.0;
1525 switch ( mGridUnit )
1530 mapBoundingRect =
mMap->rect();
1531 mapPolygon = QPolygonF(
mMap->rect() );
1532 if ( mGridUnit ==
CM )
1534 annotationScale = 0.1;
1535 gridIntervalY *= 10;
1547 double roundCorrection = mapBoundingRect.top() > 0 ? 1.0 : 0.0;
1548 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1550 int gridLineCount = 0;
1555 double yCanvasCoord;
1556 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1558 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1560 newLine.coordinate = currentLevel * annotationScale;
1561 newLine.coordinateType = AnnotationCoordinate::Latitude;
1562 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1563 mGridLines.append( newLine );
1564 currentLevel += gridIntervalY;
1571 QVector<QLineF> borderLines;
1572 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1573 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1574 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1575 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1577 QVector<QPointF> intersectionList;
1579 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1581 intersectionList.clear();
1582 QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1584 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1585 for ( ; it != borderLines.constEnd(); ++it )
1587 QPointF intersectionPoint;
1588 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1589 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1591 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1594 intersectionList.push_back( intersectionPoint );
1595 if ( intersectionList.size() >= 2 )
1602 if ( intersectionList.size() >= 2 )
1605 newLine.coordinate = currentLevel;
1606 newLine.coordinateType = AnnotationCoordinate::Latitude;
1608 mGridLines.append( newLine );
1611 currentLevel += gridIntervalY;
1618 int QgsLayoutItemMapGrid::yGridLines()
const
1620 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1626 QRectF mapBoundingRect = mapPolygon.boundingRect();
1627 double gridIntervalX = mEvaluatedIntervalX;
1628 double gridOffsetX = mEvaluatedOffsetX;
1629 double annotationScale = 1.0;
1630 switch ( mGridUnit )
1635 mapBoundingRect =
mMap->rect();
1636 mapPolygon = QPolygonF(
mMap->rect() );
1637 if ( mGridUnit ==
CM )
1639 annotationScale = 0.1;
1640 gridIntervalX *= 10;
1652 double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0;
1653 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1655 int gridLineCount = 0;
1659 double xCanvasCoord;
1660 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1662 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1665 newLine.coordinate = currentLevel * annotationScale;
1666 newLine.coordinateType = AnnotationCoordinate::Longitude;
1667 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
1668 mGridLines.append( newLine );
1669 currentLevel += gridIntervalX;
1676 QVector<QLineF> borderLines;
1677 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1678 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1679 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1680 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1682 QVector<QPointF> intersectionList;
1684 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1686 intersectionList.clear();
1687 QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1689 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1690 for ( ; it != borderLines.constEnd(); ++it )
1692 QPointF intersectionPoint;
1693 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1694 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1696 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1699 intersectionList.push_back( intersectionPoint );
1700 if ( intersectionList.size() >= 2 )
1707 if ( intersectionList.size() >= 2 )
1710 newLine.coordinate = currentLevel;
1711 newLine.coordinateType = AnnotationCoordinate::Longitude;
1713 mGridLines.append( newLine );
1716 currentLevel += gridIntervalX;
1724 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1729 double roundCorrection = bbox.
yMaximum() > 0 ? 1.0 : 0.0;
1730 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
1734 double step = ( maxX - minX ) / 20;
1736 bool crosses180 =
false;
1737 bool crossed180 =
false;
1742 step = ( maxX + 360.0 - minX ) / 20;
1748 int gridLineCount = 0;
1752 double currentX = minX;
1756 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
1769 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1773 if ( crosses180 && currentX > 180.0 )
1781 QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1782 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1783 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1785 if ( !( *lineIt ).isEmpty() )
1788 newLine.coordinate = currentLevel;
1789 newLine.coordinateType = AnnotationCoordinate::Latitude;
1790 newLine.line = QPolygonF( *lineIt );
1791 mGridLines.append( newLine );
1795 currentLevel -= mEvaluatedIntervalY;
1803 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1808 double roundCorrection = bbox.
xMinimum() > 0 ? 1.0 : 0.0;
1809 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
1813 double step = ( maxY - minY ) / 20;
1818 bool crosses180 =
false;
1819 bool crossed180 =
false;
1826 int gridLineCount = 0;
1827 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
1830 double currentY = minY;
1834 if ( currentY > maxY )
1848 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1854 QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1855 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1856 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1858 if ( !( *lineIt ).isEmpty() )
1861 newLine.coordinate = currentLevel;
1862 newLine.coordinateType = AnnotationCoordinate::Longitude;
1863 newLine.line = QPolygonF( *lineIt );
1864 mGridLines.append( newLine );
1868 currentLevel += mEvaluatedIntervalX;
1869 if ( crosses180 && currentLevel > 180.0 )
1871 currentLevel -= 360.0;
1900 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
1902 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
1904 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
1906 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
1921 if ( ddValue.compare( QLatin1String(
"x_only" ), Qt::CaseInsensitive ) == 0 )
1923 else if ( ddValue.compare( QLatin1String(
"y_only" ), Qt::CaseInsensitive ) == 0 )
1925 else if ( ddValue.compare( QLatin1String(
"disabled" ), Qt::CaseInsensitive ) == 0 )
1927 else if ( ddValue.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
1934 void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
1939 switch ( mGridUnit )
1952 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
1954 mEvaluatedEnabled =
false;
1959 const double mapWidthMapUnits = mapWidth();
1960 double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
1961 double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
1963 mEvaluatedIntervalX = interval;
1964 mEvaluatedIntervalY = interval;
1987 double QgsLayoutItemMapGrid::mapWidth()
const
1998 return mapExtent.
width();
2015 bool sortByDistance( QPair<qreal, QgsLayoutItemMapGrid::BorderSide> a, QPair<qreal, QgsLayoutItemMapGrid::BorderSide> b )
2017 return a.first < b.first;
2030 if ( ( p.y() <= tolerance && p.x() <= tolerance )
2031 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2032 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2033 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2039 if ( p.x() <= tolerance )
2050 if ( p.y() <= tolerance )
2062 QList< QPair<qreal, QgsLayoutItemMapGrid::BorderSide > > distanceToSide;
2068 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2069 return distanceToSide.at( 0 ).second;
2074 mGridLineSymbol.reset( symbol );
2079 return mGridLineSymbol.get();
2084 return mGridLineSymbol.get();
2089 mGridMarkerSymbol.reset( symbol );
2094 return mGridMarkerSymbol.get();
2099 return mGridMarkerSymbol.get();
2104 mAnnotationFormat.
setFont( font );
2105 if ( font.pointSizeF() > 0 )
2107 mAnnotationFormat.
setSize( font.pointSizeF() );
2110 else if ( font.pixelSize() > 0 )
2112 mAnnotationFormat.
setSize( font.pixelSize() );
2119 return mAnnotationFormat.
toQFont();
2124 mAnnotationFormat.
setColor( color );
2129 return mAnnotationFormat.
color();
2137 mLeftGridAnnotationDisplay = display;
2140 mRightGridAnnotationDisplay = display;
2143 mTopGridAnnotationDisplay = display;
2146 mBottomGridAnnotationDisplay = display;
2150 refreshDataDefinedProperties();
2164 return mLeftGridAnnotationDisplay;
2166 return mRightGridAnnotationDisplay;
2168 return mTopGridAnnotationDisplay;
2170 return mBottomGridAnnotationDisplay;
2172 return mBottomGridAnnotationDisplay;
2179 double bottom = 0.0;
2182 return std::max( std::max( std::max( top, right ), bottom ), left );
2192 if ( !
mMap || !mEvaluatedEnabled )
2202 GridExtension extension;
2205 switch ( mGridUnit )
2212 drawGridCrsTransform( context, 0,
true );
2219 drawGridNoTransform( context, 0,
true );
2224 updateGridLinesAnnotationsPositions();
2228 drawGridFrame(
nullptr, &extension );
2231 if ( mShowGridAnnotation )
2236 top = extension.top;
2237 right = extension.right;
2238 bottom = extension.bottom;
2239 left = extension.left;
2245 refreshDataDefinedProperties();
2250 if ( unit == mGridUnit )
2255 mTransformDirty =
true;
2264 mGridIntervalX = interval;
2265 mTransformDirty =
true;
2266 refreshDataDefinedProperties();
2275 mGridIntervalY = interval;
2276 mTransformDirty =
true;
2277 refreshDataDefinedProperties();
2286 mGridOffsetX = offset;
2287 mTransformDirty =
true;
2288 refreshDataDefinedProperties();
2297 mGridOffsetY = offset;
2298 mTransformDirty =
true;
2299 refreshDataDefinedProperties();
2308 mMinimumIntervalWidth = minWidth;
2309 mTransformDirty =
true;
2310 refreshDataDefinedProperties();
2319 mMaximumIntervalWidth = maxWidth;
2320 mTransformDirty =
true;
2321 refreshDataDefinedProperties();
2326 if (
style == mGridStyle )
2331 mTransformDirty =
true;
2336 mCrossLength = length;
2337 refreshDataDefinedProperties();
2345 mLeftGridAnnotationDirection = direction;
2348 mRightGridAnnotationDirection = direction;
2351 mTopGridAnnotationDirection = direction;
2354 mBottomGridAnnotationDirection = direction;
2367 mGridFrameSides = flags;
2373 mGridFrameSides |= flag;
2375 mGridFrameSides &= ~flag;
2380 return mGridFrameSides;
2389 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"grid_number" ) << QStringLiteral(
"grid_axis" ) );
2395 if ( mGridLineSymbol )
2401 if ( mGridMarkerSymbol )
2413 mTransformDirty =
true;
2414 refreshDataDefinedProperties();
2421 return mGridFrameSides.testFlag( flag );
2426 mGridFrameWidth = width;
2427 refreshDataDefinedProperties();
2432 mGridFrameMargin = margin;
2433 refreshDataDefinedProperties();
2438 mGridFramePenThickness = width;
2439 refreshDataDefinedProperties();
2444 mLeftGridAnnotationDirection = direction;
2445 mRightGridAnnotationDirection = direction;
2446 mTopGridAnnotationDirection = direction;
2447 mBottomGridAnnotationDirection = direction;
2455 mLeftGridAnnotationPosition = position;
2458 mRightGridAnnotationPosition = position;
2461 mTopGridAnnotationPosition = position;
2464 mBottomGridAnnotationPosition = position;
2480 return mLeftGridAnnotationPosition;
2482 return mRightGridAnnotationPosition;
2484 return mTopGridAnnotationPosition;
2486 return mBottomGridAnnotationPosition;
2488 return mLeftGridAnnotationPosition;
2493 mAnnotationFrameDistance = distance;
2494 refreshDataDefinedProperties();
2501 return mLeftGridAnnotationDirection;
2507 return mLeftGridAnnotationDirection;
2509 return mRightGridAnnotationDirection;
2511 return mTopGridAnnotationDirection;
2513 return mBottomGridAnnotationDirection;
2515 return mLeftGridAnnotationDirection;
2523 mLeftFrameDivisions = divisions;
2526 mRightFrameDivisions = divisions;
2529 mTopFrameDivisions = divisions;
2532 mBottomFrameDivisions = divisions;
2536 refreshDataDefinedProperties();
2549 return mLeftFrameDivisions;
2551 return mRightFrameDivisions;
2553 return mTopFrameDivisions;
2555 return mBottomFrameDivisions;
2557 return mLeftFrameDivisions;
2571 QRectF mbr = mapPolygon.boundingRect();
2572 QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2578 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2579 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2581 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2582 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2584 if ( lowerLeft.x() > upperRight.x() )
2592 crsRect = tr.transformBoundingBox( mapBoundingRect );
2597 crsRect = tr.transformBoundingBox( mapBoundingRect );
2605 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
2611 QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2619 QList<QPolygonF> trimmedLines;
2620 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2621 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2623 trimmedLines << ( *geomIt ).asQPolygonF();
2625 return trimmedLines;