47#include "moc_qgselevationprofilecanvas.cpp"
49using namespace Qt::StringLiterals;
55 QgsElevationProfilePlotItem( QgsElevationProfileCanvas *canvas )
56 : QgsPlotCanvasItem( canvas )
64 void setRenderer( QgsProfilePlotRenderer *renderer )
71 mRect = mCanvas->rect();
74 prepareGeometryChange();
75 setPos( mRect.topLeft() );
78 mCachedImages.clear();
86 mCachedImages.clear();
91 bool redrawResults(
const QString &sourceId )
93 auto it = mCachedImages.find( sourceId );
94 if ( it == mCachedImages.end() )
97 mCachedImages.erase( it );
102 QRectF boundingRect()
const override
107 QString distanceSuffix()
const
109 switch ( mDistanceUnit )
162 return QObject::tr(
"°" );
171 mDistanceUnit = unit;
178 if ( !mPlotArea.isNull() )
182 QgsRenderContext context;
183 if ( !scene()->views().isEmpty() )
184 context.
setScaleFactor( scene()->views().at( 0 )->logicalDpiX() / 25.4 );
186 QgsPlotRenderContext plotContext;
192 QgsProfilePoint canvasPointToPlotPoint( QPointF point )
194 const QRectF area = plotArea();
195 if ( !area.contains( point.x(), point.y() ) )
196 return QgsProfilePoint();
198 const double distance = ( point.x() - area.left() ) / area.width() * (
xMaximum() -
xMinimum() ) * mXScaleFactor +
xMinimum() * mXScaleFactor;
200 return QgsProfilePoint( distance, elevation );
203 QgsPointXY plotPointToCanvasPoint(
const QgsProfilePoint &point )
205 if ( point.
distance() < xMinimum() * mXScaleFactor || point.
distance() > xMaximum() * mXScaleFactor || point.
elevation() < yMinimum() || point.
elevation() > yMaximum() )
208 const QRectF area = plotArea();
212 return QgsPointXY( x, y );
215 void renderContent( QgsRenderContext &rc, QgsPlotRenderContext &,
const QRectF &plotArea,
const QgsPlotData & )
override
217 mPlotArea = plotArea;
222 const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
224 const QStringList sourceIds = mRenderer->sourceIds();
225 for (
const QString &source : sourceIds )
228 auto it = mCachedImages.constFind( source );
229 if ( it != mCachedImages.constEnd() )
235 plot = mRenderer->renderToImage( plotArea.width() * pixelRatio, plotArea.height() * pixelRatio, xMinimum() * mXScaleFactor,
xMaximum() * mXScaleFactor,
yMinimum(),
yMaximum(), source, pixelRatio );
236 plot.setDevicePixelRatio( pixelRatio );
237 mCachedImages.insert( source, plot );
239 rc.
painter()->drawImage( QPointF( plotArea.left(), plotArea.top() ), plot );
244 void paint( QPainter *painter )
override
247 if ( !mImage.isNull() )
249 painter->drawImage( QPointF( 0, 0 ), mImage );
253 const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
254 mImage = QImage( mRect.width() * pixelRatio, mRect.height() * pixelRatio, QImage::Format_ARGB32_Premultiplied );
255 mImage.setDevicePixelRatio( pixelRatio );
256 mImage.fill( Qt::transparent );
258 QPainter imagePainter( &mImage );
259 imagePainter.setRenderHint( QPainter::Antialiasing,
true );
263 const double mapUnitsPerPixel = (
xMaximum() -
xMinimum() ) * mXScaleFactor / plotArea().width();
269 QgsPlotRenderContext plotContext;
271 render( rc, plotContext );
274 painter->drawImage( QPointF( 0, 0 ), mImage );
278 void setSubsectionsSymbol( QgsLineSymbol *symbol )
282 mRenderer->setSubsectionsSymbol( symbol );
287 QgsProject *mProject =
nullptr;
288 double mXScaleFactor = 1.0;
295 QMap<QString, QImage> mCachedImages;
299 QgsProfilePlotRenderer *mRenderer =
nullptr;
305 QgsElevationProfileCrossHairsItem( QgsElevationProfileCanvas *canvas, QgsElevationProfilePlotItem *plotItem )
306 : QgsPlotCanvasItem( canvas )
307 , mPlotItem( plotItem )
313 mRect = mCanvas->rect();
315 prepareGeometryChange();
316 setPos( mRect.topLeft() );
320 void setPoint(
const QgsProfilePoint &point )
326 QRectF boundingRect()
const override
332 void paint( QPainter *painter )
override
334 const QgsPointXY crossHairPlotPoint = mPlotItem->plotPointToCanvasPoint( mPoint );
335 if ( crossHairPlotPoint.
isEmpty() )
339 painter->setBrush( Qt::NoBrush );
341 crossHairPen.setCosmetic(
true );
342 crossHairPen.setWidthF( 1 );
343 crossHairPen.setStyle( Qt::DashLine );
344 crossHairPen.setCapStyle( Qt::FlatCap );
345 const QPalette scenePalette = mPlotItem->scene()->palette();
346 QColor penColor = scenePalette.color( QPalette::ColorGroup::Active, QPalette::Text );
347 penColor.setAlpha( 150 );
348 crossHairPen.setColor( penColor );
349 painter->setPen( crossHairPen );
350 painter->drawLine( QPointF( mPlotItem->plotArea().left(), crossHairPlotPoint.
y() ), QPointF( mPlotItem->plotArea().right(), crossHairPlotPoint.
y() ) );
351 painter->drawLine( QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().top() ), QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().bottom() ) );
354 QgsNumericFormatContext numericContext;
356 const QString xCoordinateText = mPlotItem->xAxis().numericFormat()->formatDouble( mPoint.distance() / mPlotItem->mXScaleFactor, numericContext )
357 + mPlotItem->distanceSuffix();
359 const QString yCoordinateText = mPlotItem->yAxis().numericFormat()->formatDouble( mPoint.elevation(), numericContext );
362 const QFontMetrics fm( font );
363 const double height = fm.capHeight();
364 const double xWidth = fm.horizontalAdvance( xCoordinateText );
365 const double yWidth = fm.horizontalAdvance( yCoordinateText );
366 const double textAxisMargin = fm.horizontalAdvance(
' ' );
368 QPointF xCoordOrigin;
369 QPointF yCoordOrigin;
371 if ( mPoint.distance() < ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5 * mPlotItem->mXScaleFactor )
373 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
376 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
378 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
383 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
385 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
390 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
393 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
395 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
400 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
402 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
407 QColor backgroundColor = mPlotItem->chartBackgroundSymbol()->color();
408 backgroundColor.setAlpha( 220 );
409 painter->setBrush( QBrush( backgroundColor ) );
410 painter->setPen( Qt::NoPen );
411 painter->drawRect( QRectF( xCoordOrigin.x() - textAxisMargin + 1, xCoordOrigin.y() - textAxisMargin - height + 1, xWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
412 painter->drawRect( QRectF( yCoordOrigin.x() - textAxisMargin + 1, yCoordOrigin.y() - textAxisMargin - height + 1, yWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
414 painter->setBrush( Qt::NoBrush );
415 painter->setPen( scenePalette.color( QPalette::ColorGroup::Active, QPalette::Text ) );
417 painter->drawText( xCoordOrigin, xCoordinateText );
418 painter->drawText( yCoordOrigin, yCoordinateText );
424 QgsProfilePoint mPoint;
425 QgsElevationProfilePlotItem *mPlotItem =
nullptr;
435 mPlotItem =
new QgsElevationProfilePlotItem(
this );
440 mCrossHairsItem =
new QgsElevationProfileCrossHairsItem(
this, mPlotItem );
441 mCrossHairsItem->setZValue( 100 );
442 mCrossHairsItem->hide();
445 mDeferredRegenerationTimer =
new QTimer(
this );
446 mDeferredRegenerationTimer->setSingleShot(
true );
447 mDeferredRegenerationTimer->stop();
448 connect( mDeferredRegenerationTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRegeneration );
450 mDeferredRedrawTimer =
new QTimer(
this );
451 mDeferredRedrawTimer->setSingleShot(
true );
452 mDeferredRedrawTimer->stop();
453 connect( mDeferredRedrawTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRedraw );
465 mPlotItem->setRenderer(
nullptr );
466 mCurrentJob->deleteLater();
467 mCurrentJob =
nullptr;
475 mPlotItem->setRenderer(
nullptr );
477 mCurrentJob->cancelGeneration();
478 mCurrentJob->deleteLater();
479 mCurrentJob =
nullptr;
485 const double dxPercent = dx / mPlotItem->plotArea().width();
486 const double dyPercent = dy / mPlotItem->plotArea().height();
489 const double dxPlot = -dxPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
490 const double dyPlot = dyPercent * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
493 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
494 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
495 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
496 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
500 mPlotItem->updatePlot();
506 if ( !mPlotItem->plotArea().contains( x, y ) )
509 const double newCenterX = mPlotItem->xMinimum() + ( x - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
510 const double newCenterY = mPlotItem->yMinimum() + ( mPlotItem->plotArea().bottom() - y ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
512 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
513 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
516 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
517 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
518 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
519 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
523 mPlotItem->updatePlot();
535 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
536 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
537 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
545 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) );
552 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
553 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
554 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
556 QgsProfileIdentifyContext context;
562 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) );
569void QgsElevationProfileCanvas::setupLayerConnections(
QgsMapLayer *layer,
bool isDisconnect )
584 switch ( layer->
type() )
588 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
617void QgsElevationProfileCanvas::adjustRangeForAxisScaleLock(
double &xMinimum,
double &xMaximum,
double &yMinimum,
double &yMaximum )
const
620 const double horizontalScale = ( xMaximum - xMinimum ) / mPlotItem->plotArea().width();
621 const double verticalScale = ( yMaximum - yMinimum ) / mPlotItem->plotArea().height();
623 const double currentRatio = horizontalScale / verticalScale;
625 if ( currentRatio <= mLockedAxisScale )
627 const double height = horizontalScale * mPlotItem->plotArea().height() / mLockedAxisScale;
628 const double deltaHeight = ( yMaximum - yMinimum ) - height;
629 yMinimum += deltaHeight / 2;
630 yMaximum -= deltaHeight / 2;
634 const double width = verticalScale * mPlotItem->plotArea().width() * mLockedAxisScale;
635 const double deltaWidth = ( ( xMaximum - xMinimum ) - width );
636 xMinimum += deltaWidth / 2;
637 xMaximum -= deltaWidth / 2;
643 return mDistanceUnit;
648 mDistanceUnit = unit;
649 const double oldMin = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
650 const double oldMax = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
652 mPlotItem->setXAxisUnits( mDistanceUnit );
653 mPlotItem->setXMinimum( oldMin / mPlotItem->mXScaleFactor );
654 mPlotItem->setXMaximum( oldMax / mPlotItem->mXScaleFactor );
655 mPlotItem->updatePlot();
661 if ( !color.isValid() )
663 QPalette customPalette = qApp->palette();
664 const QColor baseColor = qApp->palette().color( QPalette::ColorRole::Base );
665 const QColor windowColor = qApp->palette().color( QPalette::ColorRole::Window );
666 customPalette.setColor( QPalette::ColorRole::Base, windowColor );
667 customPalette.setColor( QPalette::ColorRole::Window, baseColor );
668 setPalette( customPalette );
669 scene()->setPalette( customPalette );
674 const bool isDarkTheme = color.lightnessF() < 0.5;
675 QPalette customPalette = qApp->palette();
676 customPalette.setColor( QPalette::ColorRole::Window, color );
679 customPalette.setColor( QPalette::ColorRole::Text, QColor( 255, 255, 255 ) );
680 customPalette.setColor( QPalette::ColorRole::Base, color.lighter( 120 ) );
684 customPalette.setColor( QPalette::ColorRole::Text, QColor( 0, 0, 0 ) );
685 customPalette.setColor( QPalette::ColorRole::Base, color.darker( 120 ) );
688 setPalette( customPalette );
689 scene()->setPalette( customPalette );
692 updateChartFromPalette();
697 return mLockAxisScales;
702 mLockAxisScales = lock;
703 if ( mLockAxisScales )
705 double xMinimum = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
706 double xMaximum = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
707 double yMinimum = mPlotItem->yMinimum();
708 double yMaximum = mPlotItem->yMaximum();
709 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
710 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
711 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
712 mPlotItem->setYMinimum( yMinimum );
713 mPlotItem->setYMaximum( yMaximum );
716 mPlotItem->updatePlot();
724 const double horizontalScale = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / mPlotItem->plotArea().width();
725 const double verticalScale = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / mPlotItem->plotArea().height();
726 return horizontalScale / verticalScale;
731 mLockedAxisScale = scale;
733 double xMinimum = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
734 double xMaximum = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
735 double yMinimum = mPlotItem->yMinimum();
736 double yMaximum = mPlotItem->yMaximum();
737 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
738 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
739 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
740 mPlotItem->setYMinimum( yMinimum );
741 mPlotItem->setYMaximum( yMaximum );
744 mPlotItem->updatePlot();
751 if ( !mCurrentJob || !mSnappingEnabled )
765 if ( mLockAxisScales )
768 const double currentWidth = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor;
769 const double currentHeight = mPlotItem->yMaximum() - mPlotItem->yMinimum();
771 const double newWidth = currentWidth / xFactor;
772 const double newHeight = currentHeight / yFactor;
774 const double currentCenterX = ( mPlotItem->xMinimum() + mPlotItem->xMaximum() ) * 0.5 * mPlotItem->mXScaleFactor;
775 const double currentCenterY = ( mPlotItem->yMinimum() + mPlotItem->yMaximum() ) * 0.5;
777 double xMinimum = currentCenterX - newWidth * 0.5;
778 double xMaximum = currentCenterX + newWidth * 0.5;
779 double yMinimum = currentCenterY - newHeight * 0.5;
780 double yMaximum = currentCenterY + newHeight * 0.5;
781 if ( mLockAxisScales )
783 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
786 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
787 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
788 mPlotItem->setYMinimum( yMinimum );
789 mPlotItem->setYMaximum( yMaximum );
792 mPlotItem->updatePlot();
799 const QRectF intersected = rect.intersected( mPlotItem->plotArea() );
801 double minX = ( intersected.left() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
802 double maxX = ( intersected.right() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
803 double minY = ( mPlotItem->plotArea().bottom() - intersected.bottom() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
804 double maxY = ( mPlotItem->plotArea().bottom() - intersected.top() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
806 if ( mLockAxisScales )
808 adjustRangeForAxisScaleLock( minX, maxX, minY, maxY );
811 mPlotItem->setXMinimum( minX / mPlotItem->mXScaleFactor );
812 mPlotItem->setXMaximum( maxX / mPlotItem->mXScaleFactor );
813 mPlotItem->setYMinimum( minY );
814 mPlotItem->setYMaximum( maxY );
817 mPlotItem->updatePlot();
826 double zoomFactor = settings.
value( u
"qgis/zoom_factor"_s, 2 ).toDouble();
827 bool reverseZoom = settings.
value( u
"qgis/reverse_wheel_zoom"_s,
false ).toBool();
828 bool zoomIn = reverseZoom ?
event->angleDelta().y() < 0 :
event->angleDelta().y() > 0;
831 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs(
event->angleDelta().y() );
833 if (
event->modifiers() & Qt::ControlModifier )
836 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
840 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
842 QRectF viewportRect = mPlotItem->plotArea();
844 if ( viewportRect.contains(
event->position() ) )
847 const double oldCenterX = 0.5 * ( mPlotItem->xMaximum() + mPlotItem->xMinimum() );
848 const double oldCenterY = 0.5 * ( mPlotItem->yMaximum() + mPlotItem->yMinimum() );
850 const double eventPosX = (
event->position().x() - viewportRect.left() ) / viewportRect.width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
851 const double eventPosY = ( viewportRect.bottom() -
event->position().y() ) / viewportRect.height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
853 const double newCenterX = eventPosX + ( ( oldCenterX - eventPosX ) * scaleFactor );
854 const double newCenterY = eventPosY + ( ( oldCenterY - eventPosY ) * scaleFactor );
856 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
857 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
860 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
861 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
862 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
863 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
882 if ( e->isAccepted() )
884 mCrossHairsItem->hide();
889 if ( mCurrentJob && mSnappingEnabled && !plotPoint.
isEmpty() )
898 mCrossHairsItem->hide();
902 mCrossHairsItem->setPoint( plotPoint );
903 mCrossHairsItem->show();
910 return mPlotItem->plotArea();
924 request.
setTerrainProvider( mProject->elevationProperties()->terrainProvider() ? mProject->elevationProperties()->terrainProvider()->clone() :
nullptr );
930 QList< QgsAbstractProfileSource *> sourcesToRender =
sources();
931 std::reverse( sourcesToRender.begin(), sourcesToRender.end() );
937 generationContext.
setDpi( mScreenHelper->screenDpi() );
938 generationContext.
setMaximumErrorMapUnits( MAX_ERROR_PIXELS * ( mProfileCurve->length() ) / mPlotItem->plotArea().width() );
940 mCurrentJob->setContext( generationContext );
942 if ( mSubsectionsSymbol )
944 mCurrentJob->setSubsectionsSymbol( mSubsectionsSymbol->clone() );
947 mCurrentJob->startGeneration();
948 mPlotItem->setRenderer( mCurrentJob );
955 mZoomFullWhenJobFinished =
true;
958void QgsElevationProfileCanvas::generationFinished()
965 if ( mZoomFullWhenJobFinished )
968 mZoomFullWhenJobFinished =
false;
977 mPlotItem->updatePlot();
980 if ( mForceRegenerationAfterCurrentJobCompletes )
982 mForceRegenerationAfterCurrentJobCompletes =
false;
983 mCurrentJob->invalidateAllRefinableSources();
984 scheduleDeferredRegeneration();
988void QgsElevationProfileCanvas::onLayerProfileGenerationPropertyChanged()
991 if ( !mCurrentJob || mCurrentJob->isActive() )
994 QgsMapLayerElevationProperties *properties = qobject_cast<QgsMapLayerElevationProperties *>( sender() );
998 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( properties->parent() ) )
1000 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1002 if ( mCurrentJob->invalidateResults( source ) )
1003 scheduleDeferredRegeneration();
1008void QgsElevationProfileCanvas::onLayerProfileRendererPropertyChanged()
1011 if ( !mCurrentJob || mCurrentJob->isActive() )
1014 QgsMapLayerElevationProperties *properties = qobject_cast<QgsMapLayerElevationProperties *>( sender() );
1018 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( properties->parent() ) )
1020 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1022 mCurrentJob->replaceSource( source );
1024 if ( mPlotItem->redrawResults( layer->
id() ) )
1025 scheduleDeferredRedraw();
1029void QgsElevationProfileCanvas::regenerateResultsForLayer()
1034 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() ) )
1036 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1038 if ( mCurrentJob->invalidateResults( source ) )
1039 scheduleDeferredRegeneration();
1044void QgsElevationProfileCanvas::scheduleDeferredRegeneration()
1046 if ( !mDeferredRegenerationScheduled )
1048 mDeferredRegenerationTimer->start( 1 );
1049 mDeferredRegenerationScheduled =
true;
1053void QgsElevationProfileCanvas::scheduleDeferredRedraw()
1055 if ( !mDeferredRedrawScheduled )
1057 mDeferredRedrawTimer->start( 1 );
1058 mDeferredRedrawScheduled =
true;
1062void QgsElevationProfileCanvas::startDeferredRegeneration()
1064 if ( mCurrentJob && !mCurrentJob->isActive() )
1067 mCurrentJob->regenerateInvalidatedResults();
1069 else if ( mCurrentJob )
1071 mForceRegenerationAfterCurrentJobCompletes =
true;
1074 mDeferredRegenerationScheduled =
false;
1077void QgsElevationProfileCanvas::startDeferredRedraw()
1079 mPlotItem->update();
1080 mDeferredRedrawScheduled =
false;
1083void QgsElevationProfileCanvas::refineResults()
1087 QgsProfileGenerationContext context;
1088 context.
setDpi( mScreenHelper->screenDpi() );
1089 const double plotDistanceRange = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor;
1090 const double plotElevationRange = mPlotItem->yMaximum() - mPlotItem->yMinimum();
1091 const double plotDistanceUnitsPerPixel = plotDistanceRange / mPlotItem->plotArea().width();
1095 const double targetMaxErrorInMapUnits = MAX_ERROR_PIXELS * plotDistanceUnitsPerPixel;
1096 const double factor = std::pow( 10.0, 1 - std::ceil( std::log10( std::fabs( targetMaxErrorInMapUnits ) ) ) );
1097 const double roundedErrorInMapUnits = std::floor( targetMaxErrorInMapUnits * factor ) / factor;
1104 context.
setDistanceRange( QgsDoubleRange( std::max( 0.0, distanceMin ), mPlotItem->xMaximum() * mPlotItem->mXScaleFactor + plotDistanceRange * 0.05 ) );
1106 context.
setElevationRange( QgsDoubleRange( mPlotItem->yMinimum() - plotElevationRange * 0.05, mPlotItem->yMaximum() + plotElevationRange * 0.05 ) );
1107 mCurrentJob->setContext( context );
1109 scheduleDeferredRegeneration();
1112void QgsElevationProfileCanvas::updateChartFromPalette()
1114 const QPalette chartPalette = palette();
1115 setBackgroundBrush( QBrush( chartPalette.color( QPalette::ColorRole::Base ) ) );
1117 QgsTextFormat textFormat = mPlotItem->xAxis().textFormat();
1118 textFormat.
setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::Text ) );
1119 mPlotItem->xAxis().setTextFormat( textFormat );
1120 mPlotItem->yAxis().setTextFormat( textFormat );
1123 std::unique_ptr<QgsFillSymbol> chartFill( mPlotItem->chartBackgroundSymbol()->clone() );
1124 chartFill->setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Window ) );
1125 mPlotItem->setChartBackgroundSymbol( chartFill.release() );
1128 std::unique_ptr<QgsFillSymbol> chartBorder( mPlotItem->chartBorderSymbol()->clone() );
1129 chartBorder->setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text ) );
1130 mPlotItem->setChartBorderSymbol( chartBorder.release() );
1133 std::unique_ptr<QgsLineSymbol> chartMajorSymbol( mPlotItem->xAxis().gridMajorSymbol()->clone() );
1134 QColor
c = chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text );
1136 chartMajorSymbol->setColor(
c );
1137 mPlotItem->xAxis().setGridMajorSymbol( chartMajorSymbol->clone() );
1138 mPlotItem->yAxis().setGridMajorSymbol( chartMajorSymbol.release() );
1141 std::unique_ptr<QgsLineSymbol> chartMinorSymbol( mPlotItem->xAxis().gridMinorSymbol()->clone() );
1142 QColor
c = chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text );
1144 chartMinorSymbol->setColor(
c );
1145 mPlotItem->xAxis().setGridMinorSymbol( chartMinorSymbol->clone() );
1146 mPlotItem->yAxis().setGridMinorSymbol( chartMinorSymbol.release() );
1148 mPlotItem->updatePlot();
1153 if ( !mPlotItem->plotArea().contains( point.x(), point.y() ) )
1156 return mPlotItem->canvasPointToPlotPoint( point );
1161 return mPlotItem->plotPointToCanvasPoint( point );
1167 mPlotItem->mProject = project;
1177 mProfileCurve.reset( curve );
1182 return mProfileCurve.get();
1197 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
1199 setupLayerConnections( layer,
true );
1203 auto filteredList =
layers;
1204 filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(), [](
QgsMapLayer *layer ) {
1205 return !layer || !layer->isValid();
1207 filteredList.end() );
1209 mLayers = _qgis_listRawToQPointer( filteredList );
1210 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
1212 setupLayerConnections( layer,
false );
1218 return _qgis_listQPointerToRaw( mLayers );
1228 if ( mSources.isEmpty() && !mLayers.isEmpty() )
1234 QList< QgsAbstractProfileSource * >
sources;
1235 const QList<QgsMapLayer *> layersToGenerate =
layers();
1236 sources.reserve( layersToGenerate.size() );
1258 if ( mLockAxisScales )
1260 double xMinimum = mPlotItem->xMinimum();
1261 double xMaximum = mPlotItem->xMaximum();
1262 double yMinimum = mPlotItem->yMinimum();
1263 double yMaximum = mPlotItem->yMaximum();
1264 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
1265 mPlotItem->setXMinimum( xMinimum );
1266 mPlotItem->setXMaximum( xMaximum );
1267 mPlotItem->setYMinimum( yMinimum );
1268 mPlotItem->setYMaximum( yMaximum );
1271 mPlotItem->updateRect();
1272 mCrossHairsItem->updateRect();
1279 QgsPlotCanvas::paintEvent(
event );
1281 if ( !mFirstDrawOccurred )
1284 mFirstDrawOccurred =
true;
1285 mPlotItem->updateRect();
1286 mCrossHairsItem->updateRect();
1292 if ( !mPlotItem->plotArea().contains( point.
x(), point.
y() ) )
1295 if ( !mProfileCurve )
1298 const double dx = point.
x() - mPlotItem->plotArea().left();
1300 const double distanceAlongPlotPercent = dx / mPlotItem->plotArea().width();
1301 double distanceAlongCurveLength = distanceAlongPlotPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
1303 std::unique_ptr<QgsPoint> mapXyPoint( mProfileCurve->interpolatePoint( distanceAlongCurveLength ) );
1307 const double mapZ = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * ( mPlotItem->plotArea().bottom() - point.
y() ) + mPlotItem->yMinimum();
1309 return QgsPoint( mapXyPoint->x(), mapXyPoint->y(), mapZ );
1314 if ( !mProfileCurve )
1319 const double distanceAlongCurve =
geos.lineLocatePoint( point, &error );
1321 const double distanceAlongCurveOnPlot = distanceAlongCurve - mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
1322 const double distanceAlongCurvePercent = distanceAlongCurveOnPlot / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor );
1323 const double distanceAlongPlotRect = distanceAlongCurvePercent * mPlotItem->plotArea().width();
1325 const double canvasX = mPlotItem->plotArea().left() + distanceAlongPlotRect;
1328 if ( std::isnan( point.
z() ) || point.
z() < mPlotItem->yMinimum() )
1330 canvasY = mPlotItem->plotArea().top();
1332 else if ( point.
z() > mPlotItem->yMaximum() )
1334 canvasY = mPlotItem->plotArea().bottom();
1338 const double yPercent = ( point.
z() - mPlotItem->yMinimum() ) / ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
1339 canvasY = mPlotItem->plotArea().bottom() - mPlotItem->plotArea().height() * yPercent;
1352 double yMinimum = 0;
1353 double yMaximum = 0;
1364 yMinimum = zRange.
lower() - 5;
1365 yMaximum = zRange.
lower() + 5;
1370 const double margin = ( zRange.
upper() - zRange.
lower() ) * 0.05;
1371 yMinimum = zRange.
lower() - margin;
1372 yMaximum = zRange.
upper() + margin;
1376 double xMinimum = 0;
1378 double xMaximum = profileLength * 1.02;
1380 if ( mLockAxisScales )
1382 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
1385 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
1386 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
1387 mPlotItem->setYMinimum( yMinimum );
1388 mPlotItem->setYMaximum( yMaximum );
1391 mPlotItem->updatePlot();
1398 if ( mLockAxisScales )
1400 adjustRangeForAxisScaleLock( minimumDistance, maximumDistance, minimumElevation, maximumElevation );
1403 mPlotItem->setYMinimum( minimumElevation );
1404 mPlotItem->setYMaximum( maximumElevation );
1405 mPlotItem->setXMinimum( minimumDistance / mPlotItem->mXScaleFactor );
1406 mPlotItem->setXMaximum( maximumDistance / mPlotItem->mXScaleFactor );
1408 mPlotItem->updatePlot();
1415 return QgsDoubleRange( mPlotItem->xMinimum() * mPlotItem->mXScaleFactor, mPlotItem->xMaximum() * mPlotItem->mXScaleFactor );
1420 return QgsDoubleRange( mPlotItem->yMinimum(), mPlotItem->yMaximum() );
1433 : mRenderer( renderer )
1437 void renderContent( QgsRenderContext &rc, QgsPlotRenderContext &,
const QRectF &plotArea,
const QgsPlotData & )
override
1442 rc.
painter()->translate( plotArea.left(), plotArea.top() );
1443 mRenderer->render( rc, plotArea.width(), plotArea.height(), xMinimum() * mXScale,
xMaximum() * mXScale,
yMinimum(),
yMaximum() );
1444 rc.
painter()->translate( -plotArea.left(), -plotArea.top() );
1450 QgsProfilePlotRenderer *mRenderer =
nullptr;
1462 QgsElevationProfilePlot profilePlot( mCurrentJob );
1466 QDomElement elem = doc.createElement( u
"plot"_s );
1468 plotSettings.
writeXml( elem, doc, rwContext );
1469 profilePlot.readXml( elem, rwContext );
1471 profilePlot.mXScale = mPlotItem->mXScaleFactor;
1472 profilePlot.xAxis().setLabelSuffix( mPlotItem->xAxis().labelSuffix() );
1473 profilePlot.xAxis().setLabelSuffixPlacement( mPlotItem->xAxis().labelSuffixPlacement() );
1475 profilePlot.setSize( QSizeF( width, height ) );
1477 profilePlot.render( context, plotContext );
1487 return mCurrentJob->identify( plotPoint, identifyContext() );
1498 double distance1 = topLeftPlotPoint.
distance();
1499 double distance2 = bottomRightPlotPoint.
distance();
1500 if ( distance2 < distance1 )
1501 std::swap( distance1, distance2 );
1503 double elevation1 = topLeftPlotPoint.
elevation();
1504 double elevation2 = bottomRightPlotPoint.
elevation();
1505 if ( elevation2 < elevation1 )
1506 std::swap( elevation1, elevation2 );
1515 mPlotItem->updatePlot();
1520 mSnappingEnabled = enabled;
1525 mSubsectionsSymbol.reset( symbol );
1526 std::unique_ptr<QgsLineSymbol> plotItemSymbol( mSubsectionsSymbol ? mSubsectionsSymbol->clone() :
nullptr );
1527 mPlotItem->setSubsectionsSymbol( plotItemSymbol.release() );
1530void QgsElevationProfileCanvas::setSourcesPrivate()
@ FirstAndLastLabels
Place suffix after the first and last label values only.
DistanceUnit
Units of distance.
@ YardsBritishSears1922Truncated
British yards (Sears 1922 truncated).
@ MilesUSSurvey
US Survey miles.
@ LinksBritishSears1922
British links (Sears 1922).
@ YardsBritishBenoit1895A
British yards (Benoit 1895 A).
@ LinksBritishBenoit1895A
British links (Benoit 1895 A).
@ Centimeters
Centimeters.
@ YardsIndian1975
Indian yards (1975).
@ FeetUSSurvey
US Survey feet.
@ Millimeters
Millimeters.
@ FeetBritishSears1922
British feet (Sears 1922).
@ YardsClarkes
Clarke's yards.
@ YardsIndian
Indian yards.
@ FeetBritishBenoit1895B
British feet (Benoit 1895 B).
@ Miles
Terrestrial miles.
@ LinksUSSurvey
US Survey links.
@ ChainsUSSurvey
US Survey chains.
@ FeetClarkes
Clarke's feet.
@ Unknown
Unknown distance unit.
@ FeetBritish1936
British feet (1936).
@ FeetIndian1962
Indian feet (1962).
@ YardsBritishSears1922
British yards (Sears 1922).
@ FeetIndian1937
Indian feet (1937).
@ YardsIndian1937
Indian yards (1937).
@ Degrees
Degrees, for planar geographic CRS distance measurements.
@ ChainsBritishBenoit1895B
British chains (Benoit 1895 B).
@ LinksBritishSears1922Truncated
British links (Sears 1922 truncated).
@ ChainsBritishBenoit1895A
British chains (Benoit 1895 A).
@ YardsBritishBenoit1895B
British yards (Benoit 1895 B).
@ FeetBritish1865
British feet (1865).
@ YardsIndian1962
Indian yards (1962).
@ FeetBritishSears1922Truncated
British feet (Sears 1922 truncated).
@ MetersGermanLegal
German legal meter.
@ LinksBritishBenoit1895B
British links (Benoit 1895 B).
@ ChainsInternational
International chains.
@ LinksInternational
International links.
@ ChainsBritishSears1922Truncated
British chains (Sears 1922 truncated).
@ FeetIndian
Indian (geodetic) feet.
@ NauticalMiles
Nautical miles.
@ ChainsClarkes
Clarke's chains.
@ LinksClarkes
Clarke's links.
@ ChainsBritishSears1922
British chains (Sears 1922).
@ FeetIndian1975
Indian feet (1975).
@ FeetGoldCoast
Gold Coast feet.
@ FeetBritishBenoit1895A
British feet (Benoit 1895 A).
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
virtual void renderContent(QgsRenderContext &context, QgsPlotRenderContext &plotContext, const QRectF &plotArea, const QgsPlotData &plotData=QgsPlotData())
Renders the plot content.
void setSize(QSizeF size)
Sets the overall size of the plot (including titles and over components which sit outside the plot ar...
Base class for 2-dimensional plot/chart/graphs with an X and Y axes.
double yMaximum() const
Returns the maximum value of the y axis.
void setYMinimum(double minimum)
Sets the minimum value of the y axis.
double xMinimum() const
Returns the minimum value of the x axis.
void render(QgsRenderContext &context, QgsPlotRenderContext &plotContext, const QgsPlotData &plotData=QgsPlotData()) override
Renders the plot.
void calculateOptimisedIntervals(QgsRenderContext &context, QgsPlotRenderContext &plotContext)
Automatically sets the grid and label intervals to optimal values for display in the given render con...
QgsPlotAxis & xAxis()
Returns a reference to the plot's x axis.
double yMinimum() const
Returns the minimum value of the y axis.
QRectF interiorPlotArea(QgsRenderContext &context, QgsPlotRenderContext &plotContext) const override
Returns the area of the plot which corresponds to the actual plot content (excluding all titles and o...
void setYMaximum(double maximum)
Sets the maximum value of the y axis.
bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Writes the plot's properties into an XML element.
double xMaximum() const
Returns the maximum value of the x axis.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
Interface for classes which can generate elevation profiles.
static QgsProfileSourceRegistry * profileSourceRegistry()
Returns registry of available profile source implementations.
Represents a coordinate reference system (CRS).
Abstract base class for curved geometry type.
QgsRange which stores a range of double values.
QgsDoubleRange visibleElevationRange() const
Returns the elevation range currently visible in the plot.
QgsCurve * profileCurve() const
Returns the profile curve.
void setTolerance(double tolerance)
Sets the profile tolerance (in crs() units).
void setSources(const QList< QgsAbstractProfileSource * > &sources)
Sets the list of sources to include in the profile.
void setLockAxisScales(bool lock)
Sets whether the distance and elevation scales are locked to each other.
void setProfileCurve(QgsCurve *curve)
Sets the profile curve.
void zoomToRect(const QRectF &rect) override
Zooms the plot to the specified rect in canvas units.
void activeJobCountChanged(int count)
Emitted when the number of active background jobs changes.
QgsElevationProfileCanvas(QWidget *parent=nullptr)
Constructor for QgsElevationProfileCanvas, with the specified parent widget.
void scalePlot(double factor) override
Scales the plot by a specified scale factor.
void paintEvent(QPaintEvent *event) override
QgsDoubleRange visibleDistanceRange() const
Returns the distance range currently visible in the plot.
void cancelJobs() override
Cancel any rendering job, in a blocking way.
QgsCoordinateReferenceSystem crs() const override
Returns the coordinate reference system (CRS) for map coordinates used by the canvas.
void clear()
Clears the current profile.
void setDistanceUnit(Qgis::DistanceUnit unit)
Sets the distance unit used by the canvas.
QgsProfilePoint canvasPointToPlotPoint(QPointF point) const
Converts a canvas point to the equivalent plot point.
void setBackgroundColor(const QColor &color)
Sets the background color to use for the profile canvas.
void render(QgsRenderContext &context, double width, double height, const Qgs2DXyPlot &plotSettings)
Renders a portion of the profile using the specified render context.
QgsPointXY plotPointToCanvasPoint(const QgsProfilePoint &point) const
Converts a plot point to the equivalent canvas point.
QgsPoint toMapCoordinates(const QgsPointXY &point) const override
Converts a point on the canvas to the associated map coordinate.
bool lockAxisScales() const
Returns true if the distance and elevation scales are locked to each other.
void setAxisScaleRatio(double scale)
Sets the ratio of horizontal (distance) to vertical (elevation) scale for the plot.
void setVisiblePlotRange(double minimumDistance, double maximumDistance, double minimumElevation, double maximumElevation)
Sets the visible area of the plot.
void canvasPointHovered(const QgsPointXY &point, const QgsProfilePoint &profilePoint)
Emitted when the mouse hovers over the specified point (in canvas coordinates).
const Qgs2DXyPlot & plot() const
Returns a reference to the 2D plot used by the widget.
void setSubsectionsSymbol(QgsLineSymbol *symbol)
Sets the symbol used to draw the subsections.
QgsPointXY snapToPlot(QPoint point) override
Snap a canvas point to the plot.
void setProject(QgsProject *project)
Sets the project associated with the profile.
QList< QgsMapLayer * > layers() const
Returns the list of layers included in the profile.
void resizeEvent(QResizeEvent *event) override
void centerPlotOn(double x, double y) override
Centers the plot on the plot point corresponding to x, y in canvas units.
void wheelZoom(QWheelEvent *event) override
Zoom plot from a mouse wheel event.
void refresh() override
Triggers a complete regeneration of the profile, causing the profile extraction to perform in the bac...
Qgis::DistanceUnit distanceUnit() const
Returns the distance unit used by the canvas.
double tolerance() const
Returns the tolerance of the profile (in crs() units).
void mouseMoveEvent(QMouseEvent *e) override
void panContentsBy(double dx, double dy) override
Pans the plot contents by dx, dy in canvas units.
void invalidateCurrentPlotExtent()
Invalidates the current plot extent, which means that the visible plot area will be recalculated and ...
QgsPointXY toCanvasCoordinates(const QgsPoint &point) const override
Converts a point in map coordinates to the associated canvas point.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs associated with the canvas' map coordinates.
QList< QgsAbstractProfileSource * > sources() const
Returns the list of sources included in the profile.
~QgsElevationProfileCanvas() override
double axisScaleRatio() const
Returns the current ratio of horizontal (distance) to vertical (elevation) scale for the plot.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to include in the profile.
void zoomFull()
Zooms to the full extent of the profile.
void scaleChanged()
Emitted when the plot scale is changed.
void setSnappingEnabled(bool enabled)
Sets whether snapping of cursor points is enabled.
QVector< QgsProfileIdentifyResults > identify(QPointF point)
Identify results visible at the specified plot point.
QRectF plotArea() const
Returns the interior rectangle representing the surface of the plot, in canvas coordinates.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
A line symbol type, for rendering LineString and MultiLineString geometries.
void profileGenerationPropertyChanged()
Emitted when any of the elevation properties which relate solely to generation of elevation profiles ...
void profileRenderingPropertyChanged()
Emitted when any of the elevation properties which relate solely to presentation of elevation results...
Base class for all map layer types.
virtual QgsAbstractProfileSource * profileSource()
Returns the layer's profile source if it has profile capabilities.
void dataChanged()
Data of layer changed.
virtual QgsMapLayerElevationProperties * elevationProperties()
Returns the layer's elevation properties.
void setLabelSuffixPlacement(Qgis::PlotAxisSuffixPlacement placement)
Sets the placement for the axis label suffixes.
void setLabelSuffix(const QString &suffix)
Sets the axis label suffix.
An abstract class for items that can be placed on a QgsPlotCanvas.
virtual void paint(QPainter *painter)=0
Paints the item.
bool event(QEvent *e) override
QgsPlotCanvas(QWidget *parent=nullptr)
Constructor for QgsPlotCanvas, with the specified parent widget.
void plotAreaChanged()
Emitted whenever the visible area of the plot is changed.
void mouseMoveEvent(QMouseEvent *e) override
void resizeEvent(QResizeEvent *e) override
Contains information about the context of a plot rendering operation.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type, with support for z-dimension and m-values.
Encapsulates the context in which an elevation profile is to be generated.
double maximumErrorMapUnits() const
Returns the maximum allowed error in the generated result, in profile curve map units.
void setDpi(double dpi)
Sets the dpi (dots per inch) for the profie, to be used in size conversions.
void setMaximumErrorMapUnits(double error)
Sets the maximum allowed error in the generated result, in profile curve map units.
void setDistanceRange(const QgsDoubleRange &range)
Sets the range of distances to include in the generation.
void setElevationRange(const QgsDoubleRange &range)
Sets the range of elevations to include in the generation.
void setMapUnitsPerDistancePixel(double units)
Sets the number of map units per pixel in the distance dimension.
Encapsulates the context of identifying profile results.
double maximumPointElevationDelta
Maximum allowed snapping delta for the elevation values when identifying a point.
double maximumPointDistanceDelta
Maximum allowed snapping delta for the distance values when identifying a point.
QgsProject * project
Associated project.
double displayRatioElevationVsDistance
Display ratio of elevation vs distance units.
double maximumSurfaceDistanceDelta
Maximum allowed snapping delta for the distance values when identifying a continuous elevation surfac...
double maximumSurfaceElevationDelta
Maximum allowed snapping delta for the elevation values when identifying a continuous elevation surfa...
Generates and renders elevation profile plots.
void generationFinished()
Emitted when the profile generation is finished (or canceled).
Encapsulates a point on a distance-elevation profile.
double elevation() const
Returns the elevation of the point.
double distance() const
Returns the distance of the point.
bool isEmpty() const
Returns true if the point is empty.
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
QgsProfileRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate expressions.
QgsProfileRequest & setTransformContext(const QgsCoordinateTransformContext &context)
Sets the transform context, for use when transforming coordinates from a source to the request's crs(...
QgsProfileRequest & setTerrainProvider(QgsAbstractTerrainProvider *provider)
Sets the terrain provider.
QgsProfileRequest & setTolerance(double tolerance)
Sets the tolerance of the request (in crs() units).
QgsProfileRequest & setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the desired Coordinate Reference System (crs) for the profile.
Encapsulates the context of snapping a profile point.
double maximumPointDistanceDelta
Maximum allowed snapping delta for the distance values when snapping to a point.
double maximumSurfaceElevationDelta
Maximum allowed snapping delta for the elevation values when snapping to a continuous elevation surfa...
double maximumPointElevationDelta
Maximum allowed snapping delta for the elevation values when snapping to a point.
double maximumSurfaceDistanceDelta
Maximum allowed snapping delta for the distance values when snapping to a continuous elevation surfac...
double displayRatioElevationVsDistance
Display ratio of elevation vs distance units.
Encapsulates results of snapping a profile point.
bool isValid() const
Returns true if the result is a valid point.
QgsProfilePoint snappedPoint
Snapped point.
void profileSourceUnregistered(const QString &sourceId)
Signal emitted once a profile source is unregistered.
QList< QgsAbstractProfileSource * > profileSources() const
Returns a list of registered profile sources.
void profileSourceRegistered(const QString &sourceId, const QString &sourceName)
Signal emitted once a profile source is registered.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
A utility class for dynamic handling of changes to screen properties.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
static Q_INVOKABLE QString toAbbreviatedString(Qgis::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
Contains geos related utilities and functions.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define BUILTIN_UNREACHABLE
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).