49 #define MAX_GRID_LINES 1000 //maximum number of horizontal or vertical grid lines to draw
80 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
86 return qobject_cast<QgsLayoutItemMapGrid *>(
item );
91 QList< QgsLayoutItemMapGrid * > list;
114 const QDomNodeList mapGridNodeList = elem.elementsByTagName( QStringLiteral(
"ComposerMapGrid" ) );
115 for (
int i = 0; i < mapGridNodeList.size(); ++i )
117 const QDomElement mapGridElem = mapGridNodeList.at( i ).toElement();
119 mapGrid->
readXml( mapGridElem, doc, context );
133 return std::max( std::max( std::max( top, right ), bottom ), left );
147 double gridTop = 0.0;
148 double gridRight = 0.0;
149 double gridBottom = 0.0;
150 double gridLeft = 0.0;
152 top = std::max( top, gridTop );
153 right = std::max( right, gridRight );
154 bottom = std::max( bottom, gridBottom );
155 left = std::max( left, gridLeft );
171 return QVector2D( 0, 1 );
173 return QVector2D( -1, 0 );
175 return QVector2D( 0, -1 );
177 return QVector2D( 1, 0 );
185 return QVector2D( borderVector.y(), -borderVector.x() );
195 const QString defaultFontString = settings.
value( QStringLiteral(
"LayoutDesigner/defaultFont" ), QVariant(),
QgsSettings::Gui ).toString();
196 if ( !defaultFontString.isEmpty() )
199 font.setFamily( defaultFontString );
200 mAnnotationFormat.
setFont( font );
203 createDefaultGridLineSymbol();
204 createDefaultGridMarkerSymbol();
217 void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
219 QVariantMap properties;
220 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
221 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
222 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"flat" ) );
226 void QgsLayoutItemMapGrid::createDefaultGridMarkerSymbol()
228 QVariantMap properties;
229 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"circle" ) );
230 properties.insert( QStringLiteral(
"size" ), QStringLiteral(
"2.0" ) );
231 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
237 if ( mGridLineSymbol )
239 mGridLineSymbol->setWidth( width );
245 if ( mGridLineSymbol )
247 mGridLineSymbol->setColor(
c );
258 QDomElement mapGridElem = doc.createElement( QStringLiteral(
"ComposerMapGrid" ) );
259 mapGridElem.setAttribute( QStringLiteral(
"gridStyle" ), mGridStyle );
260 mapGridElem.setAttribute( QStringLiteral(
"intervalX" ),
qgsDoubleToString( mGridIntervalX ) );
261 mapGridElem.setAttribute( QStringLiteral(
"intervalY" ),
qgsDoubleToString( mGridIntervalY ) );
262 mapGridElem.setAttribute( QStringLiteral(
"offsetX" ),
qgsDoubleToString( mGridOffsetX ) );
263 mapGridElem.setAttribute( QStringLiteral(
"offsetY" ),
qgsDoubleToString( mGridOffsetY ) );
264 mapGridElem.setAttribute( QStringLiteral(
"crossLength" ),
qgsDoubleToString( mCrossLength ) );
266 QDomElement lineStyleElem = doc.createElement( QStringLiteral(
"lineStyle" ) );
268 lineStyleElem.appendChild( gridLineStyleElem );
269 mapGridElem.appendChild( lineStyleElem );
271 QDomElement markerStyleElem = doc.createElement( QStringLiteral(
"markerStyle" ) );
273 markerStyleElem.appendChild( gridMarkerStyleElem );
274 mapGridElem.appendChild( markerStyleElem );
276 mapGridElem.setAttribute( QStringLiteral(
"gridFrameStyle" ), mGridFrameStyle );
277 mapGridElem.setAttribute( QStringLiteral(
"gridFrameSideFlags" ), mGridFrameSides );
278 mapGridElem.setAttribute( QStringLiteral(
"gridFrameWidth" ),
qgsDoubleToString( mGridFrameWidth ) );
279 mapGridElem.setAttribute( QStringLiteral(
"gridFrameMargin" ),
qgsDoubleToString( mGridFrameMargin ) );
280 mapGridElem.setAttribute( QStringLiteral(
"gridFramePenThickness" ),
qgsDoubleToString( mGridFramePenThickness ) );
284 mapGridElem.setAttribute( QStringLiteral(
"leftFrameDivisions" ), mLeftFrameDivisions );
285 mapGridElem.setAttribute( QStringLiteral(
"rightFrameDivisions" ), mRightFrameDivisions );
286 mapGridElem.setAttribute( QStringLiteral(
"topFrameDivisions" ), mTopFrameDivisions );
287 mapGridElem.setAttribute( QStringLiteral(
"bottomFrameDivisions" ), mBottomFrameDivisions );
288 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksLengthMode" ), mRotatedTicksLengthMode );
289 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksEnabled" ), mRotatedTicksEnabled );
290 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksMinimumAngle" ), QString::number( mRotatedTicksMinimumAngle ) );
291 mapGridElem.setAttribute( QStringLiteral(
"rotatedTicksMarginToCorner" ), QString::number( mRotatedTicksMarginToCorner ) );
292 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsLengthMode" ), mRotatedAnnotationsLengthMode );
293 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsEnabled" ), mRotatedAnnotationsEnabled );
294 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsMinimumAngle" ), QString::number( mRotatedAnnotationsMinimumAngle ) );
295 mapGridElem.setAttribute( QStringLiteral(
"rotatedAnnotationsMarginToCorner" ), QString::number( mRotatedAnnotationsMarginToCorner ) );
301 mapGridElem.setAttribute( QStringLiteral(
"annotationFormat" ), mGridAnnotationFormat );
302 mapGridElem.setAttribute( QStringLiteral(
"showAnnotation" ), mShowGridAnnotation );
303 mapGridElem.setAttribute( QStringLiteral(
"annotationExpression" ), mGridAnnotationExpressionString );
304 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDisplay" ), mLeftGridAnnotationDisplay );
305 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDisplay" ), mRightGridAnnotationDisplay );
306 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDisplay" ), mTopGridAnnotationDisplay );
307 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDisplay" ), mBottomGridAnnotationDisplay );
308 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationPosition" ), mLeftGridAnnotationPosition );
309 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationPosition" ), mRightGridAnnotationPosition );
310 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationPosition" ), mTopGridAnnotationPosition );
311 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationPosition" ), mBottomGridAnnotationPosition );
312 mapGridElem.setAttribute( QStringLiteral(
"leftAnnotationDirection" ), mLeftGridAnnotationDirection );
313 mapGridElem.setAttribute( QStringLiteral(
"rightAnnotationDirection" ), mRightGridAnnotationDirection );
314 mapGridElem.setAttribute( QStringLiteral(
"topAnnotationDirection" ), mTopGridAnnotationDirection );
315 mapGridElem.setAttribute( QStringLiteral(
"bottomAnnotationDirection" ), mBottomGridAnnotationDirection );
316 mapGridElem.setAttribute( QStringLiteral(
"frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) );
317 mapGridElem.appendChild( mAnnotationFormat.
writeXml( doc, context ) );
318 mapGridElem.setAttribute( QStringLiteral(
"annotationPrecision" ), mGridAnnotationPrecision );
319 mapGridElem.setAttribute( QStringLiteral(
"unit" ), mGridUnit );
320 mapGridElem.setAttribute( QStringLiteral(
"blendMode" ), mBlendMode );
321 mapGridElem.setAttribute( QStringLiteral(
"minimumIntervalWidth" ), QString::number( mMinimumIntervalWidth ) );
322 mapGridElem.setAttribute( QStringLiteral(
"maximumIntervalWidth" ), QString::number( mMaximumIntervalWidth ) );
325 elem.appendChild( mapGridElem );
332 if ( itemElem.isNull() )
341 mGridIntervalX = itemElem.attribute( QStringLiteral(
"intervalX" ), QStringLiteral(
"0" ) ).toDouble();
342 mGridIntervalY = itemElem.attribute( QStringLiteral(
"intervalY" ), QStringLiteral(
"0" ) ).toDouble();
343 mGridOffsetX = itemElem.attribute( QStringLiteral(
"offsetX" ), QStringLiteral(
"0" ) ).toDouble();
344 mGridOffsetY = itemElem.attribute( QStringLiteral(
"offsetY" ), QStringLiteral(
"0" ) ).toDouble();
345 mCrossLength = itemElem.attribute( QStringLiteral(
"crossLength" ), QStringLiteral(
"3" ) ).toDouble();
346 mGridFrameStyle =
static_cast< QgsLayoutItemMapGrid::FrameStyle >( itemElem.attribute( QStringLiteral(
"gridFrameStyle" ), QStringLiteral(
"0" ) ).toInt() );
347 mGridFrameSides =
static_cast< QgsLayoutItemMapGrid::FrameSideFlags
>( itemElem.attribute( QStringLiteral(
"gridFrameSideFlags" ), QStringLiteral(
"15" ) ).toInt() );
348 mGridFrameWidth = itemElem.attribute( QStringLiteral(
"gridFrameWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
349 mGridFrameMargin = itemElem.attribute( QStringLiteral(
"gridFrameMargin" ), QStringLiteral(
"0.0" ) ).toDouble();
350 mGridFramePenThickness = itemElem.attribute( QStringLiteral(
"gridFramePenThickness" ), QStringLiteral(
"0.3" ) ).toDouble();
358 mRotatedTicksLengthMode =
TickLengthMode( itemElem.attribute( QStringLiteral(
"rotatedTicksLengthMode" ), QStringLiteral(
"0" ) ).toInt() );
359 mRotatedTicksEnabled = itemElem.attribute( QStringLiteral(
"rotatedTicksEnabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
360 mRotatedTicksMinimumAngle = itemElem.attribute( QStringLiteral(
"rotatedTicksMinimumAngle" ), QStringLiteral(
"0" ) ).toDouble();
361 mRotatedTicksMarginToCorner = itemElem.attribute( QStringLiteral(
"rotatedTicksMarginToCorner" ), QStringLiteral(
"0" ) ).toDouble();
362 mRotatedAnnotationsLengthMode =
TickLengthMode( itemElem.attribute( QStringLiteral(
"rotatedAnnotationsLengthMode" ), QStringLiteral(
"0" ) ).toInt() );
363 mRotatedAnnotationsEnabled = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsEnabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
364 mRotatedAnnotationsMinimumAngle = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsMinimumAngle" ), QStringLiteral(
"0" ) ).toDouble();
365 mRotatedAnnotationsMarginToCorner = itemElem.attribute( QStringLiteral(
"rotatedAnnotationsMarginToCorner" ), QStringLiteral(
"0" ) ).toDouble();
367 const QDomElement lineStyleElem = itemElem.firstChildElement( QStringLiteral(
"lineStyle" ) );
368 if ( !lineStyleElem.isNull() )
370 const QDomElement symbolElem = lineStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
371 if ( !symbolElem.isNull() )
373 mGridLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
380 mGridLineSymbol->setWidth( itemElem.attribute( QStringLiteral(
"penWidth" ), QStringLiteral(
"0" ) ).toDouble() );
381 mGridLineSymbol->setColor( QColor( itemElem.attribute( QStringLiteral(
"penColorRed" ), QStringLiteral(
"0" ) ).toInt(),
382 itemElem.attribute( QStringLiteral(
"penColorGreen" ), QStringLiteral(
"0" ) ).toInt(),
383 itemElem.attribute( QStringLiteral(
"penColorBlue" ), QStringLiteral(
"0" ) ).toInt() ) );
386 const QDomElement markerStyleElem = itemElem.firstChildElement( QStringLiteral(
"markerStyle" ) );
387 if ( !markerStyleElem.isNull() )
389 const QDomElement symbolElem = markerStyleElem.firstChildElement( QStringLiteral(
"symbol" ) );
390 if ( !symbolElem.isNull() )
392 mGridMarkerSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context ) );
396 if ( !mCRS.
readXml( itemElem ) )
399 mBlendMode =
static_cast< QPainter::CompositionMode
>( itemElem.attribute( QStringLiteral(
"blendMode" ), QStringLiteral(
"0" ) ).toUInt() );
402 mShowGridAnnotation = ( itemElem.attribute( QStringLiteral(
"showAnnotation" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
404 mGridAnnotationExpressionString = itemElem.attribute( QStringLiteral(
"annotationExpression" ) );
405 mGridAnnotationExpression.reset();
410 mLeftGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"leftAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
411 mRightGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"rightAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
413 mBottomGridAnnotationDisplay =
QgsLayoutItemMapGrid::DisplayMode( itemElem.attribute( QStringLiteral(
"bottomAnnotationDisplay" ), QStringLiteral(
"0" ) ).toInt() );
419 mAnnotationFrameDistance = itemElem.attribute( QStringLiteral(
"frameAnnotationDistance" ), QStringLiteral(
"0" ) ).toDouble();
421 if ( !itemElem.firstChildElement(
"text-style" ).isNull() )
423 mAnnotationFormat.
readXml( itemElem, context );
430 font.fromString( itemElem.attribute(
"annotationFont", QString() ) );
432 mAnnotationFormat.
setFont( font );
433 mAnnotationFormat.
setSize( font.pointSizeF() );
438 mGridAnnotationPrecision = itemElem.attribute( QStringLiteral(
"annotationPrecision" ), QStringLiteral(
"3" ) ).toInt();
439 const int gridUnitInt = itemElem.attribute( QStringLiteral(
"unit" ), QString::number(
MapUnit ) ).toInt();
441 mMinimumIntervalWidth = itemElem.attribute( QStringLiteral(
"minimumIntervalWidth" ), QStringLiteral(
"50" ) ).toDouble();
442 mMaximumIntervalWidth = itemElem.attribute( QStringLiteral(
"maximumIntervalWidth" ), QStringLiteral(
"100" ) ).toDouble();
444 refreshDataDefinedProperties();
454 mTransformDirty =
true;
460 return mBlendMode != QPainter::CompositionMode_SourceOver;
463 QPolygonF QgsLayoutItemMapGrid::scalePolygon(
const QPolygonF &polygon,
const double scale )
const
465 const QTransform t = QTransform::fromScale( scale, scale );
466 return t.map( polygon );
469 void QgsLayoutItemMapGrid::drawGridCrsTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
471 if ( !
mMap || !mEvaluatedEnabled )
478 if ( mapPolygon != mPrevMapPolygon )
480 mTransformDirty =
true;
481 mPrevMapPolygon = mapPolygon;
484 if ( mTransformDirty )
486 calculateCrsTransformLines();
490 if ( !calculateLinesOnly )
494 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
495 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
497 drawGridLine( scalePolygon( gridIt->line, dotsPerMM ), context );
502 const double maxX =
mMap->rect().width();
503 const double maxY =
mMap->rect().height();
505 QList< QgsPointXY >::const_iterator intersectionIt = mTransformedIntersections.constBegin();
506 for ( ; intersectionIt != mTransformedIntersections.constEnd(); ++intersectionIt )
508 const double x = intersectionIt->x();
509 const double y = intersectionIt->y();
513 const QLineF line1 = QLineF( x - mEvaluatedCrossLength, y, x + mEvaluatedCrossLength, y );
514 line1.p1().rx() = line1.p1().x() < 0 ? 0 : line1.p1().x();
515 line1.p2().rx() = line1.p2().x() > maxX ? maxX : line1.p2().x();
516 const QLineF line2 = QLineF( x, y - mEvaluatedCrossLength, x, y + mEvaluatedCrossLength );
517 line2.p1().ry() = line2.p1().y() < 0 ? 0 : line2.p1().y();
518 line2.p2().ry() = line2.p2().y() > maxY ? maxY : line2.p2().y();
521 drawGridLine( QLineF( line1.p1() * dotsPerMM, line1.p2() * dotsPerMM ), context );
522 drawGridLine( QLineF( line2.p1() * dotsPerMM, line2.p2() * dotsPerMM ), context );
526 drawGridMarker( QPointF( x, y ) * dotsPerMM, context );
533 void QgsLayoutItemMapGrid::calculateCrsTransformLines()
const
537 if ( crsGridParams( crsBoundingRect, inverseTr ) != 0 )
544 xGridLinesCrsTransform( crsBoundingRect, inverseTr );
545 yGridLinesCrsTransform( crsBoundingRect, inverseTr );
552 QList< QgsGeometry > xLines;
553 QList< QgsGeometry > yLines;
554 QList< GridLine >::const_iterator gridIt = mGridLines.constBegin();
555 for ( ; gridIt != mGridLines.constEnd(); ++gridIt )
559 for (
int i = 0; i < gridIt->line.size(); ++i )
561 line.append(
QgsPointXY( gridIt->line.at( i ).x(), gridIt->line.at( i ).y() ) );
563 if ( gridIt->coordinateType == AnnotationCoordinate::Longitude )
565 else if ( gridIt->coordinateType == AnnotationCoordinate::Latitude )
570 mTransformedIntersections.clear();
571 QList< QgsGeometry >::const_iterator yLineIt = yLines.constBegin();
572 for ( ; yLineIt != yLines.constEnd(); ++yLineIt )
574 QList< QgsGeometry >::const_iterator xLineIt = xLines.constBegin();
575 for ( ; xLineIt != xLines.constEnd(); ++xLineIt )
579 if ( intersects.
isNull() )
587 mTransformedIntersections << vertex;
595 mTransformDirty =
false;
600 if ( !
mMap || !mEvaluatedEnabled )
604 QPaintDevice *paintDevice = p->device();
611 p->setCompositionMode( mBlendMode );
614 const QRectF thisPaintRect = QRectF( 0, 0,
mMap->rect().width(),
mMap->rect().height() );
615 p->setClipRect( thisPaintRect );
616 if ( thisPaintRect != mPrevPaintRect )
619 mTransformDirty =
true;
620 mPrevPaintRect = thisPaintRect;
624 const double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
625 p->scale( 1 / dotsPerMM, 1 / dotsPerMM );
641 drawGridCrsTransform( context, dotsPerMM );
648 drawGridNoTransform( context, dotsPerMM );
653 p->setClipping(
false );
657 p->setClipRect(
mMap->mapRectFromScene(
mMap->sceneBoundingRect() ).adjusted( -10, -10, 10, 10 ) );
662 updateGridLinesAnnotationsPositions();
669 if ( mShowGridAnnotation )
675 void QgsLayoutItemMapGrid::updateGridLinesAnnotationsPositions()
const
677 QList< GridLine >::iterator it = mGridLines.begin();
678 for ( ; it != mGridLines.end(); ++it )
680 it->startAnnotation.border = borderForLineCoord( it->line.first(), it->coordinateType );
681 it->endAnnotation.border = borderForLineCoord( it->line.last(), it->coordinateType );
682 it->startAnnotation.position = QVector2D( it->line.first() );
683 it->endAnnotation.position = QVector2D( it->line.last() );
684 it->startAnnotation.vector = QVector2D( it->line.at( 1 ) - it->line.first() ).normalized();
685 it->endAnnotation.vector = QVector2D( it->line.at( it->line.count() - 2 ) - it->line.last() ).normalized();
687 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() );
689 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() );
693 void QgsLayoutItemMapGrid::drawGridNoTransform(
QgsRenderContext &context,
double dotsPerMM,
bool calculateLinesOnly )
const
700 if ( calculateLinesOnly )
703 QList< GridLine >::const_iterator vIt = mGridLines.constBegin();
704 QList< GridLine >::const_iterator hIt = mGridLines.constBegin();
712 for ( ; vIt != mGridLines.constEnd(); ++vIt )
714 if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
716 line = QLineF( vIt->line.first() * dotsPerMM, vIt->line.last() * dotsPerMM );
717 drawGridLine( line, context );
720 for ( ; hIt != mGridLines.constEnd(); ++hIt )
722 if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
724 line = QLineF( hIt->line.first() * dotsPerMM, hIt->line.last() * dotsPerMM );
725 drawGridLine( line, context );
731 QPointF intersectionPoint, crossEnd1, crossEnd2;
732 for ( ; vIt != mGridLines.constEnd(); ++vIt )
734 if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
737 l1 = QLineF( vIt->line.first(), vIt->line.last() );
740 hIt = mGridLines.constBegin();
741 for ( ; hIt != mGridLines.constEnd(); ++hIt )
743 if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
746 l2 = QLineF( hIt->line.first(), hIt->line.last() );
748 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
749 if ( l2.intersect( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
751 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
757 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
759 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
762 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
766 drawGridMarker( intersectionPoint * dotsPerMM, context );
778 hIt = mGridLines.constBegin();
779 for ( ; hIt != mGridLines.constEnd(); ++hIt )
781 if ( hIt->coordinateType != AnnotationCoordinate::Latitude )
784 l1 = QLineF( hIt->line.first(), hIt->line.last() );
786 vIt = mGridLines.constBegin();
787 for ( ; vIt != mGridLines.constEnd(); ++vIt )
789 if ( vIt->coordinateType != AnnotationCoordinate::Longitude )
792 l2 = QLineF( vIt->line.first(), vIt->line.last() );
794 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
795 if ( l2.intersect( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
797 if ( l2.intersects( l1, &intersectionPoint ) == QLineF::BoundedIntersection )
801 crossEnd1 = ( ( intersectionPoint - l1.p1() ).manhattanLength() > 0.01 ) ?
803 crossEnd2 = ( ( intersectionPoint - l1.p2() ).manhattanLength() > 0.01 ) ?
806 drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
813 void QgsLayoutItemMapGrid::drawGridFrame( QPainter *p, GridExtension *extension )
const
822 switch ( mGridFrameStyle )
826 drawGridFrameZebra( p, extension );
831 drawGridFrameTicks( p, extension );
836 drawGridFrameLine( p, extension );
847 void QgsLayoutItemMapGrid::drawGridLine(
const QLineF &line,
QgsRenderContext &context )
const
850 poly << line.p1() << line.p2();
851 drawGridLine( poly, context );
854 void QgsLayoutItemMapGrid::drawGridLine(
const QPolygonF &line,
QgsRenderContext &context )
const
861 mGridLineSymbol->startRender( context );
862 mGridLineSymbol->renderPolyline( line,
nullptr, context );
863 mGridLineSymbol->stopRender( context );
866 void QgsLayoutItemMapGrid::drawGridMarker( QPointF point,
QgsRenderContext &context )
const
873 mGridMarkerSymbol->startRender( context );
874 mGridMarkerSymbol->renderPoint( point,
nullptr, context );
875 mGridMarkerSymbol->stopRender( context );
878 void QgsLayoutItemMapGrid::drawGridFrameZebra( QPainter *p, GridExtension *extension )
const
898 void QgsLayoutItemMapGrid::drawGridFrameZebraBorder( QPainter *p, BorderSide border,
double *extension )
const
907 *extension = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth + mEvaluatedGridFrameLineThickness / 2.0;
911 double currentCoord = 0.0;
918 bool drawTLBox =
false;
919 bool drawTRBox =
false;
920 bool drawBLBox =
false;
921 bool drawBRBox =
false;
923 QMap< double, double > pos = QMap< double, double >();
924 QList< GridLine >::const_iterator it = mGridLines.constBegin();
925 for ( ; it != mGridLines.constEnd(); ++it )
928 for (
int i = 0 ; i < 2 ; ++i )
930 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
933 if ( annot.border != border )
936 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
940 pos.insert( annot.position.y(), it->coordinate );
942 pos.insert( annot.position.x(), it->coordinate );
949 pos.insert(
mMap->rect().height(),
mMap->rect().height() );
965 pos.insert(
mMap->rect().width(),
mMap->rect().width() );
969 QPen framePen = QPen( mGridFramePenColor );
970 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
971 framePen.setJoinStyle( Qt::MiterJoin );
972 p->setPen( framePen );
974 QMap< double, double >::const_iterator posIt = pos.constBegin();
975 for ( ; posIt != pos.constEnd(); ++posIt )
977 p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
980 height = posIt.key() - currentCoord;
981 width = mEvaluatedGridFrameWidth;
982 x = ( border ==
QgsLayoutItemMapGrid::Left ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().width() + mEvaluatedGridFrameMargin;
987 height = mEvaluatedGridFrameWidth;
988 width = posIt.key() - currentCoord;
990 y = ( border ==
QgsLayoutItemMapGrid::Top ) ? -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) :
mMap->rect().height() + mEvaluatedGridFrameMargin;
992 p->drawRect( QRectF( x, y, width, height ) );
993 currentCoord = posIt.key();
1000 width = height = ( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ) ;
1001 p->setBrush( QBrush( mGridFrameFillColor1 ) );
1003 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1005 p->drawRect( QRectF(
mMap->rect().width(), -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ), width, height ) );
1007 p->drawRect( QRectF( -( mEvaluatedGridFrameWidth + mEvaluatedGridFrameMargin ),
mMap->rect().height(), width, height ) );
1009 p->drawRect( QRectF(
mMap->rect().width(),
mMap->rect().height(), width, height ) );
1013 void QgsLayoutItemMapGrid::drawGridFrameTicks( QPainter *p, GridExtension *extension )
const
1023 QPen framePen = QPen( mGridFramePenColor );
1024 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1025 framePen.setCapStyle( Qt::FlatCap );
1026 p->setBrush( Qt::NoBrush );
1027 p->setPen( framePen );
1030 QList< GridLine >::iterator it = mGridLines.begin();
1031 for ( ; it != mGridLines.end(); ++it )
1034 for (
int i = 0 ; i < 2 ; ++i )
1036 const GridLineAnnotation annot = ( i == 0 ) ? it->startAnnotation : it->endAnnotation;
1038 if ( ! shouldShowDivisionForSide( it->coordinateType, annot.border ) )
1042 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedTicksMinimumAngle + 0.0001 )
1050 facingLeft = ( annot.angle != 0 );
1051 facingRight = ( annot.angle != 0 );
1055 facingLeft = ( annot.angle > 0 );
1056 facingRight = ( annot.angle < 0 );
1060 facingLeft = ( annot.angle < 0 );
1061 facingRight = ( annot.angle > 0 );
1064 if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedTicksMarginToCorner ) ||
1065 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ) )
1067 if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedTicksMarginToCorner ) ||
1068 ( facingRight && annot.position.x() < mRotatedTicksMarginToCorner ) ) )
1070 if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ||
1071 ( facingRight && annot.position.y() < mRotatedTicksMarginToCorner ) ) )
1073 if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedTicksMarginToCorner ) ||
1074 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedTicksMarginToCorner ) ) )
1078 const QVector2D vector = ( mRotatedTicksEnabled ) ? annot.vector : normalVector;
1080 double fA = mEvaluatedGridFrameMargin;
1081 double fB = mEvaluatedGridFrameMargin + mEvaluatedGridFrameWidth;
1083 if ( mRotatedTicksEnabled && mRotatedTicksLengthMode ==
OrthogonalTicks )
1085 fA /= QVector2D::dotProduct( vector, normalVector );
1086 fB /= QVector2D::dotProduct( vector, normalVector );
1093 extension->UpdateBorder( annot.border, fB );
1101 pA = annot.position + fA * vector;
1102 pB = annot.position + fB * vector;
1106 pA = annot.position - fA * vector;
1107 pB = annot.position - fB * vector;
1111 pA = annot.position - fB * vector;
1112 pB = annot.position + ( fB - 2.0 * mEvaluatedGridFrameMargin ) * vector;
1114 p->drawLine( QLineF( pA.toPointF(), pB.toPointF() ) );
1120 void QgsLayoutItemMapGrid::drawGridFrameLine( QPainter *p, GridExtension *extension )
const
1130 QPen framePen = QPen( mGridFramePenColor );
1131 framePen.setWidthF( mEvaluatedGridFrameLineThickness );
1132 framePen.setCapStyle( Qt::SquareCap );
1133 p->setBrush( Qt::NoBrush );
1134 p->setPen( framePen );
1144 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1152 p->drawLine( QLineF(
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1158 extension->UpdateBorder(
QgsLayoutItemMapGrid::Top, mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 );
1160 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin, 0 - mEvaluatedGridFrameMargin ) );
1168 p->drawLine( QLineF( 0 - mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin,
mMap->rect().width() + mEvaluatedGridFrameMargin,
mMap->rect().height() + mEvaluatedGridFrameMargin ) );
1171 if ( ! extension && drawDiagonals )
1176 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1177 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0;
1178 p->drawLine( QLineF( 0, 0, X1, Y1 ) );
1183 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1184 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1185 p->drawLine( QLineF(
mMap->rect().width(),
mMap->rect().height(), X1, Y1 ) );
1190 const double X1 =
mMap->rect().width() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1191 const double Y1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1192 p->drawLine( QLineF(
mMap->rect().width(), 0, X1, Y1 ) );
1197 const double X1 = 0 - mEvaluatedGridFrameMargin + mEvaluatedGridFrameLineThickness / 2.0 ;
1198 const double Y1 =
mMap->rect().height() + mEvaluatedGridFrameMargin - mEvaluatedGridFrameLineThickness / 2.0 ;
1199 p->drawLine( QLineF( 0,
mMap->rect().height(), X1, Y1 ) );
1205 GridExtension *extension )
const
1207 QString currentAnnotationString;
1208 QList< GridLine >::const_iterator it = mGridLines.constBegin();
1209 for ( ; it != mGridLines.constEnd(); ++it )
1211 currentAnnotationString = gridAnnotationString( it->coordinate, it->coordinateType, expressionContext );
1212 drawCoordinateAnnotation( context, it->startAnnotation, currentAnnotationString, it->coordinateType, extension );
1213 drawCoordinateAnnotation( context, it->endAnnotation, currentAnnotationString, it->coordinateType, extension );
1217 void QgsLayoutItemMapGrid::drawCoordinateAnnotation(
QgsRenderContext &context, GridLineAnnotation annot,
const QString &annotationString,
const AnnotationCoordinate coordinateType, GridExtension *extension )
const
1224 if ( ! shouldShowAnnotationForSide( coordinateType, annot.border ) )
1236 double xpos = annot.position.x();
1237 double ypos = annot.position.y();
1238 QPointF anchor = QPointF();
1245 if ( abs( annot.angle ) / M_PI * 180.0 > 90.0 - mRotatedAnnotationsMinimumAngle + 0.0001 )
1249 const QVector2D vector = ( mRotatedAnnotationsEnabled ) ? annot.vector : normalVector;
1252 double f = mEvaluatedAnnotationFrameDistance;
1260 f += mEvaluatedGridFrameWidth;
1261 if ( hasBorderWidth )
1262 f += mEvaluatedGridFrameLineThickness / 2.0;
1267 if ( mRotatedAnnotationsEnabled && mRotatedAnnotationsLengthMode ==
OrthogonalTicks )
1269 f /= QVector2D::dotProduct( vector, normalVector );
1272 const QVector2D pos = annot.position + f * vector;
1285 rotation = atan2( vector.y(), vector.x() ) / M_PI * 180;
1287 if ( rotation <= -90 || rotation > 90 )
1290 anchor.setX( outside ? 0 : textWidth );
1294 anchor.setX( outside ? textWidth : 0 );
1298 anchor.setY( 0.5 * textHeight );
1300 anchor.setY( -1.5 * textHeight );
1302 anchor.setY( -0.5 * textHeight );
1308 anchor.setX( 0.5 * textWidth );
1309 anchor.setY( -0.5 * textHeight );
1311 anchor.setY( outside ? 0 : -textHeight );
1313 anchor.setX( outside ? 0 : textWidth );
1315 anchor.setY( outside ? -textHeight : 0 );
1317 anchor.setX( outside ? textWidth : 0 );
1322 anchor.setX( 0.5 * textWidth );
1323 anchor.setY( -0.5 * textHeight );
1325 anchor.setX( outside ? 0 : textWidth );
1327 anchor.setY( outside ? -textHeight : 0 );
1329 anchor.setX( outside ? textWidth : 0 );
1331 anchor.setY( outside ? 0 : -textHeight );
1336 anchor.setX( 0.5 * textWidth );
1337 anchor.setY( -0.5 * textHeight );
1339 anchor.setX( outside ? textWidth : 0 );
1341 anchor.setY( outside ? 0 : -textHeight );
1343 anchor.setX( outside ? 0 : textWidth );
1345 anchor.setY( outside ? -textHeight : 0 );
1350 rotation = atan2( borderVector.y(), borderVector.x() ) / M_PI * 180;
1351 anchor.setX( 0.5 * textWidth );
1353 anchor.setY( -textHeight );
1361 extension->UpdateBorder( frameBorder, -f + textWidth );
1363 extension->UpdateAll( textWidth / 2.0 );
1366 if ( extension || !context.
painter() )
1370 bool facingLeft = ( annot.angle < 0 );
1371 bool facingRight = ( annot.angle > 0 );
1374 facingLeft = !facingLeft;
1375 facingRight = !facingRight;
1377 if ( annot.border == BorderSide::Top && ( ( facingLeft && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ||
1378 ( facingRight && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ) )
1380 if ( annot.border == BorderSide::Bottom && ( ( facingLeft && annot.position.x() >
mMap->rect().width() - mRotatedAnnotationsMarginToCorner ) ||
1381 ( facingRight && annot.position.x() < mRotatedAnnotationsMarginToCorner ) ) )
1383 if ( annot.border == BorderSide::Left && ( ( facingLeft && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ||
1384 ( facingRight && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ) )
1386 if ( annot.border == BorderSide::Right && ( ( facingLeft && annot.position.y() < mRotatedAnnotationsMarginToCorner ) ||
1387 ( facingRight && annot.position.y() >
mMap->rect().height() - mRotatedAnnotationsMarginToCorner ) ) )
1391 context.
painter()->translate( QPointF( xpos, ypos ) );
1392 context.
painter()->rotate( rotation );
1393 context.
painter()->translate( -anchor );
1401 bool geographic =
false;
1415 const double wrappedX = std::fmod( value, 360.0 );
1416 if ( wrappedX > 180.0 )
1418 value = wrappedX - 360.0;
1420 else if ( wrappedX < -180.0 )
1422 value = wrappedX + 360.0;
1428 return QString::number( value,
'f', mGridAnnotationPrecision );
1434 const double coordRounded =
qgsRound( value, mGridAnnotationPrecision );
1438 if ( !geographic || ( coordRounded != 180.0 && coordRounded != 0.0 ) )
1440 hemisphere = value < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
1446 if ( !geographic || coordRounded != 0.0 )
1448 hemisphere = value < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
1454 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + QChar( 176 ) + hemisphere;
1458 return QString::number( std::fabs( value ),
'f', mGridAnnotationPrecision ) + hemisphere;
1465 if ( !mGridAnnotationExpression )
1467 mGridAnnotationExpression.reset(
new QgsExpression( mGridAnnotationExpressionString ) );
1468 mGridAnnotationExpression->prepare( &expressionContext );
1470 return mGridAnnotationExpression->evaluate( &expressionContext ).toString();
1474 QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FormatFlags();
1475 switch ( mGridAnnotationFormat )
1494 flags = QgsCoordinateFormatter::FormatFlags();
1504 flags = QgsCoordinateFormatter::FormatFlags();
1525 int QgsLayoutItemMapGrid::xGridLines()
const
1527 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1534 QRectF mapBoundingRect = mapPolygon.boundingRect();
1535 double gridIntervalY = mEvaluatedIntervalY;
1536 double gridOffsetY = mEvaluatedOffsetY;
1537 double annotationScale = 1.0;
1538 switch ( mGridUnit )
1543 mapBoundingRect =
mMap->rect();
1544 mapPolygon = QPolygonF(
mMap->rect() );
1545 if ( mGridUnit ==
CM )
1547 annotationScale = 0.1;
1548 gridIntervalY *= 10;
1560 const double roundCorrection = mapBoundingRect.top() > 0 ? 1.0 : 0.0;
1561 double currentLevel =
static_cast< int >( ( mapBoundingRect.top() - gridOffsetY ) / gridIntervalY + roundCorrection ) * gridIntervalY + gridOffsetY;
1563 int gridLineCount = 0;
1568 double yCanvasCoord;
1569 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1571 yCanvasCoord =
mMap->rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1573 newLine.coordinate = currentLevel * annotationScale;
1574 newLine.coordinateType = AnnotationCoordinate::Latitude;
1575 newLine.line = QPolygonF() << QPointF( 0, yCanvasCoord ) << QPointF(
mMap->rect().width(), yCanvasCoord );
1576 mGridLines.append( newLine );
1577 currentLevel += gridIntervalY;
1584 QVector<QLineF> borderLines;
1585 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1586 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1587 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1588 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1590 QVector<QPointF> intersectionList;
1592 while ( currentLevel <= mapBoundingRect.bottom() && gridLineCount <
MAX_GRID_LINES )
1594 intersectionList.clear();
1595 const QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1597 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1598 for ( ; it != borderLines.constEnd(); ++it )
1600 QPointF intersectionPoint;
1601 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1602 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1604 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1607 intersectionList.push_back( intersectionPoint );
1608 if ( intersectionList.size() >= 2 )
1615 if ( intersectionList.size() >= 2 )
1618 newLine.coordinate = currentLevel;
1619 newLine.coordinateType = AnnotationCoordinate::Latitude;
1621 mGridLines.append( newLine );
1624 currentLevel += gridIntervalY;
1631 int QgsLayoutItemMapGrid::yGridLines()
const
1633 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1639 QRectF mapBoundingRect = mapPolygon.boundingRect();
1640 double gridIntervalX = mEvaluatedIntervalX;
1641 double gridOffsetX = mEvaluatedOffsetX;
1642 double annotationScale = 1.0;
1643 switch ( mGridUnit )
1648 mapBoundingRect =
mMap->rect();
1649 mapPolygon = QPolygonF(
mMap->rect() );
1650 if ( mGridUnit ==
CM )
1652 annotationScale = 0.1;
1653 gridIntervalX *= 10;
1665 const double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0;
1666 double currentLevel =
static_cast< int >( ( mapBoundingRect.left() - gridOffsetX ) / gridIntervalX + roundCorrection ) * gridIntervalX + gridOffsetX;
1668 int gridLineCount = 0;
1672 double xCanvasCoord;
1673 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1675 xCanvasCoord =
mMap->rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1678 newLine.coordinate = currentLevel * annotationScale;
1679 newLine.coordinateType = AnnotationCoordinate::Longitude;
1680 newLine.line = QPolygonF() << QPointF( xCanvasCoord, 0 ) << QPointF( xCanvasCoord,
mMap->rect().height() );
1681 mGridLines.append( newLine );
1682 currentLevel += gridIntervalX;
1689 QVector<QLineF> borderLines;
1690 borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1691 borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1692 borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1693 borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1695 QVector<QPointF> intersectionList;
1697 while ( currentLevel <= mapBoundingRect.right() && gridLineCount <
MAX_GRID_LINES )
1699 intersectionList.clear();
1700 const QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1702 QVector<QLineF>::const_iterator it = borderLines.constBegin();
1703 for ( ; it != borderLines.constEnd(); ++it )
1705 QPointF intersectionPoint;
1706 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1707 if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1709 if ( it->intersects( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1712 intersectionList.push_back( intersectionPoint );
1713 if ( intersectionList.size() >= 2 )
1720 if ( intersectionList.size() >= 2 )
1723 newLine.coordinate = currentLevel;
1724 newLine.coordinateType = AnnotationCoordinate::Longitude;
1726 mGridLines.append( newLine );
1729 currentLevel += gridIntervalX;
1737 if ( !
mMap || mEvaluatedIntervalY <= 0.0 )
1742 const double roundCorrection = bbox.
yMaximum() > 0 ? 1.0 : 0.0;
1743 double currentLevel =
static_cast< int >( ( bbox.
yMaximum() - mEvaluatedOffsetY ) / mEvaluatedIntervalY + roundCorrection ) * mEvaluatedIntervalY + mEvaluatedOffsetY;
1745 const double minX = bbox.
xMinimum();
1746 const double maxX = bbox.
xMaximum();
1747 double step = ( maxX - minX ) / 20;
1749 bool crosses180 =
false;
1750 bool crossed180 =
false;
1755 step = ( maxX + 360.0 - minX ) / 20;
1761 int gridLineCount = 0;
1765 double currentX = minX;
1769 if ( ( !crosses180 || crossed180 ) && ( currentX > maxX ) )
1782 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1786 if ( crosses180 && currentX > 180.0 )
1794 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1795 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1796 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1798 if ( !( *lineIt ).isEmpty() )
1801 newLine.coordinate = currentLevel;
1802 newLine.coordinateType = AnnotationCoordinate::Latitude;
1803 newLine.line = QPolygonF( *lineIt );
1804 mGridLines.append( newLine );
1808 currentLevel -= mEvaluatedIntervalY;
1816 if ( !
mMap || mEvaluatedIntervalX <= 0.0 )
1821 const double roundCorrection = bbox.
xMinimum() > 0 ? 1.0 : 0.0;
1822 double currentLevel =
static_cast< int >( ( bbox.
xMinimum() - mEvaluatedOffsetX ) / mEvaluatedIntervalX + roundCorrection ) * mEvaluatedIntervalX + mEvaluatedOffsetX;
1824 const double minY = bbox.
yMinimum();
1825 const double maxY = bbox.
yMaximum();
1826 const double step = ( maxY - minY ) / 20;
1831 bool crosses180 =
false;
1832 bool crossed180 =
false;
1839 int gridLineCount = 0;
1840 while ( ( currentLevel <= bbox.
xMaximum() || ( crosses180 && !crossed180 ) ) && gridLineCount <
MAX_GRID_LINES )
1843 double currentY = minY;
1847 if ( currentY > maxY )
1861 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
1867 const QList<QPolygonF> lineSegments = trimLinesToMap( gridLine,
QgsRectangle(
mMap->rect() ) );
1868 QList<QPolygonF>::const_iterator lineIt = lineSegments.constBegin();
1869 for ( ; lineIt != lineSegments.constEnd(); ++lineIt )
1871 if ( !( *lineIt ).isEmpty() )
1874 newLine.coordinate = currentLevel;
1875 newLine.coordinateType = AnnotationCoordinate::Longitude;
1876 newLine.line = QPolygonF( *lineIt );
1877 mGridLines.append( newLine );
1881 currentLevel += mEvaluatedIntervalX;
1882 if ( crosses180 && currentLevel > 180.0 )
1884 currentLevel -= 360.0;
1913 return shouldShowForDisplayMode( coordinate, mEvaluatedLeftGridAnnotationDisplay );
1915 return shouldShowForDisplayMode( coordinate, mEvaluatedRightGridAnnotationDisplay );
1917 return shouldShowForDisplayMode( coordinate, mEvaluatedTopGridAnnotationDisplay );
1919 return shouldShowForDisplayMode( coordinate, mEvaluatedBottomGridAnnotationDisplay );
1934 if ( ddValue.compare( QLatin1String(
"x_only" ), Qt::CaseInsensitive ) == 0 )
1936 else if ( ddValue.compare( QLatin1String(
"y_only" ), Qt::CaseInsensitive ) == 0 )
1938 else if ( ddValue.compare( QLatin1String(
"disabled" ), Qt::CaseInsensitive ) == 0 )
1940 else if ( ddValue.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
1947 void QgsLayoutItemMapGrid::refreshDataDefinedProperties()
1952 mTransformDirty = mTransformDirty
1959 switch ( mGridUnit )
1972 if ( mMaximumIntervalWidth < mMinimumIntervalWidth )
1974 mEvaluatedEnabled =
false;
1979 const double mapWidthMapUnits = mapWidth();
1980 const double minUnitsPerSeg = ( mMinimumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
1981 const double maxUnitsPerSeg = ( mMaximumIntervalWidth * mapWidthMapUnits ) / mapWidthMm;
1983 mEvaluatedIntervalX = interval;
1984 mEvaluatedIntervalY = interval;
1985 mTransformDirty =
true;
2008 double QgsLayoutItemMapGrid::mapWidth()
const
2019 return mapExtent.
width();
2036 bool sortByDistance( QPair<qreal, QgsLayoutItemMapGrid::BorderSide> a, QPair<qreal, QgsLayoutItemMapGrid::BorderSide> b )
2038 return a.first < b.first;
2051 if ( ( p.y() <= tolerance && p.x() <= tolerance )
2052 || ( p.y() <= tolerance && p.x() >= (
mMap->rect().width() - tolerance ) )
2053 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() <= tolerance )
2054 || ( p.y() >= (
mMap->rect().height() - tolerance ) && p.x() >= (
mMap->rect().width() - tolerance ) )
2060 if ( p.x() <= tolerance )
2071 if ( p.y() <= tolerance )
2083 QList< QPair<qreal, QgsLayoutItemMapGrid::BorderSide > > distanceToSide;
2089 std::sort( distanceToSide.begin(), distanceToSide.end(),
sortByDistance );
2090 return distanceToSide.at( 0 ).second;
2095 mGridLineSymbol.reset( symbol );
2100 return mGridLineSymbol.get();
2105 return mGridLineSymbol.get();
2110 mGridMarkerSymbol.reset( symbol );
2115 return mGridMarkerSymbol.get();
2120 return mGridMarkerSymbol.get();
2125 mAnnotationFormat.
setFont( font );
2126 if ( font.pointSizeF() > 0 )
2128 mAnnotationFormat.
setSize( font.pointSizeF() );
2131 else if ( font.pixelSize() > 0 )
2133 mAnnotationFormat.
setSize( font.pixelSize() );
2140 return mAnnotationFormat.
toQFont();
2145 mAnnotationFormat.
setColor( color );
2150 return mAnnotationFormat.
color();
2158 mLeftGridAnnotationDisplay = display;
2161 mRightGridAnnotationDisplay = display;
2164 mTopGridAnnotationDisplay = display;
2167 mBottomGridAnnotationDisplay = display;
2171 refreshDataDefinedProperties();
2185 return mLeftGridAnnotationDisplay;
2187 return mRightGridAnnotationDisplay;
2189 return mTopGridAnnotationDisplay;
2191 return mBottomGridAnnotationDisplay;
2193 return mBottomGridAnnotationDisplay;
2200 double bottom = 0.0;
2203 return std::max( std::max( std::max( top, right ), bottom ), left );
2213 if ( !
mMap || !mEvaluatedEnabled )
2223 GridExtension extension;
2226 switch ( mGridUnit )
2233 drawGridCrsTransform( context, 0,
true );
2240 drawGridNoTransform( context, 0,
true );
2245 updateGridLinesAnnotationsPositions();
2249 drawGridFrame(
nullptr, &extension );
2252 if ( mShowGridAnnotation )
2257 top = extension.top;
2258 right = extension.right;
2259 bottom = extension.bottom;
2260 left = extension.left;
2266 refreshDataDefinedProperties();
2271 if ( unit == mGridUnit )
2276 mTransformDirty =
true;
2285 mGridIntervalX = interval;
2286 mTransformDirty =
true;
2287 refreshDataDefinedProperties();
2296 mGridIntervalY = interval;
2297 mTransformDirty =
true;
2298 refreshDataDefinedProperties();
2307 mGridOffsetX = offset;
2308 mTransformDirty =
true;
2309 refreshDataDefinedProperties();
2318 mGridOffsetY = offset;
2319 mTransformDirty =
true;
2320 refreshDataDefinedProperties();
2329 mMinimumIntervalWidth = minWidth;
2330 mTransformDirty =
true;
2331 refreshDataDefinedProperties();
2340 mMaximumIntervalWidth = maxWidth;
2341 mTransformDirty =
true;
2342 refreshDataDefinedProperties();
2347 if (
style == mGridStyle )
2352 mTransformDirty =
true;
2357 mCrossLength = length;
2358 refreshDataDefinedProperties();
2366 mLeftGridAnnotationDirection = direction;
2369 mRightGridAnnotationDirection = direction;
2372 mTopGridAnnotationDirection = direction;
2375 mBottomGridAnnotationDirection = direction;
2388 mGridFrameSides = flags;
2394 mGridFrameSides |= flag;
2396 mGridFrameSides &= ~flag;
2401 return mGridFrameSides;
2410 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"grid_number" ) << QStringLiteral(
"grid_axis" ) );
2416 if ( mGridLineSymbol )
2422 if ( mGridMarkerSymbol )
2434 mTransformDirty =
true;
2435 refreshDataDefinedProperties();
2442 return mGridFrameSides.testFlag( flag );
2447 mGridFrameWidth = width;
2448 refreshDataDefinedProperties();
2453 mGridFrameMargin = margin;
2454 refreshDataDefinedProperties();
2459 mGridFramePenThickness = width;
2460 refreshDataDefinedProperties();
2465 mLeftGridAnnotationDirection = direction;
2466 mRightGridAnnotationDirection = direction;
2467 mTopGridAnnotationDirection = direction;
2468 mBottomGridAnnotationDirection = direction;
2476 mLeftGridAnnotationPosition = position;
2479 mRightGridAnnotationPosition = position;
2482 mTopGridAnnotationPosition = position;
2485 mBottomGridAnnotationPosition = position;
2501 return mLeftGridAnnotationPosition;
2503 return mRightGridAnnotationPosition;
2505 return mTopGridAnnotationPosition;
2507 return mBottomGridAnnotationPosition;
2509 return mLeftGridAnnotationPosition;
2514 mAnnotationFrameDistance = distance;
2515 refreshDataDefinedProperties();
2522 return mLeftGridAnnotationDirection;
2528 return mLeftGridAnnotationDirection;
2530 return mRightGridAnnotationDirection;
2532 return mTopGridAnnotationDirection;
2534 return mBottomGridAnnotationDirection;
2536 return mLeftGridAnnotationDirection;
2544 mLeftFrameDivisions = divisions;
2547 mRightFrameDivisions = divisions;
2550 mTopFrameDivisions = divisions;
2553 mBottomFrameDivisions = divisions;
2557 refreshDataDefinedProperties();
2570 return mLeftFrameDivisions;
2572 return mRightFrameDivisions;
2574 return mTopFrameDivisions;
2576 return mBottomFrameDivisions;
2578 return mLeftFrameDivisions;
2594 const QRectF mbr = mapPolygon.boundingRect();
2595 const QgsRectangle mapBoundingRect( mbr.left(), mbr.bottom(), mbr.right(), mbr.top() );
2601 QgsPointXY lowerLeft( mapBoundingRect.xMinimum(), mapBoundingRect.yMinimum() );
2602 QgsPointXY upperRight( mapBoundingRect.xMaximum(), mapBoundingRect.yMaximum() );
2604 lowerLeft = tr.transform( lowerLeft.x(), lowerLeft.y() );
2605 upperRight = tr.transform( upperRight.x(), upperRight.y() );
2607 if ( lowerLeft.x() > upperRight.x() )
2610 crsRect = extentTransform.
transformBoundingBox( mapBoundingRect, Qgis::TransformDirection::Forward,
true );
2628 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
2634 QList<QPolygonF> QgsLayoutItemMapGrid::trimLinesToMap(
const QPolygonF &line,
const QgsRectangle &rect )
2642 QList<QPolygonF> trimmedLines;
2643 QVector<QgsGeometry>::const_iterator geomIt = intersectedParts.constBegin();
2644 for ( ; geomIt != intersectedParts.constEnd(); ++geomIt )
2646 trimmedLines << ( *geomIt ).asQPolygonF();
2648 return trimmedLines;