47#include "moc_qgselevationprofilecanvas.cpp"
49using namespace Qt::StringLiterals;
55 QgsElevationProfilePlotItem( QgsElevationProfileCanvas *canvas )
56 : QgsPlotCanvasItem( canvas )
64 void setRenderer( QgsProfilePlotRenderer *renderer ) { mRenderer = renderer; }
68 mRect = mCanvas->rect();
71 prepareGeometryChange();
72 setPos( mRect.topLeft() );
75 mCachedImages.clear();
83 mCachedImages.clear();
88 bool redrawResults(
const QString &sourceId )
90 auto it = mCachedImages.find( sourceId );
91 if ( it == mCachedImages.end() )
94 mCachedImages.erase( it );
99 QRectF boundingRect()
const override {
return mRect; }
101 QString distanceSuffix()
const
103 switch ( mDistanceUnit )
156 return QObject::tr(
"°" );
165 mDistanceUnit = unit;
172 if ( !mPlotArea.isNull() )
176 QgsRenderContext context;
177 if ( !scene()->views().isEmpty() )
178 context.
setScaleFactor( scene()->views().at( 0 )->logicalDpiX() / 25.4 );
180 QgsPlotRenderContext plotContext;
186 QgsProfilePoint canvasPointToPlotPoint( QPointF point )
188 const QRectF area = plotArea();
189 if ( !area.contains( point.x(), point.y() ) )
190 return QgsProfilePoint();
192 const double distance = ( point.x() - area.left() ) / area.width() * (
xMaximum() -
xMinimum() ) * mXScaleFactor +
xMinimum() * mXScaleFactor;
194 return QgsProfilePoint( distance, elevation );
197 QgsPointXY plotPointToCanvasPoint(
const QgsProfilePoint &point )
199 if ( point.
distance() < xMinimum() * mXScaleFactor || point.
distance() > xMaximum() * mXScaleFactor || point.
elevation() < yMinimum() || point.
elevation() > yMaximum() )
202 const QRectF area = plotArea();
206 return QgsPointXY( x, y );
209 void renderContent( QgsRenderContext &rc, QgsPlotRenderContext &,
const QRectF &plotArea,
const QgsPlotData & )
override
211 mPlotArea = plotArea;
216 const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
218 const QStringList sourceIds = mRenderer->sourceIds();
219 for (
const QString &source : sourceIds )
222 auto it = mCachedImages.constFind( source );
223 if ( it != mCachedImages.constEnd() )
229 plot = mRenderer->renderToImage( plotArea.width() * pixelRatio, plotArea.height() * pixelRatio, xMinimum() * mXScaleFactor,
xMaximum() * mXScaleFactor,
yMinimum(),
yMaximum(), source, pixelRatio );
230 plot.setDevicePixelRatio( pixelRatio );
231 mCachedImages.insert( source, plot );
233 rc.
painter()->drawImage( QPointF( plotArea.left(), plotArea.top() ), plot );
238 void paint( QPainter *painter )
override
241 if ( !mImage.isNull() )
243 painter->drawImage( QPointF( 0, 0 ), mImage );
247 const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
248 mImage = QImage( mRect.width() * pixelRatio, mRect.height() * pixelRatio, QImage::Format_ARGB32_Premultiplied );
249 mImage.setDevicePixelRatio( pixelRatio );
250 mImage.fill( Qt::transparent );
252 QPainter imagePainter( &mImage );
253 imagePainter.setRenderHint( QPainter::Antialiasing,
true );
257 const double mapUnitsPerPixel = (
xMaximum() -
xMinimum() ) * mXScaleFactor / plotArea().width();
263 QgsPlotRenderContext plotContext;
265 render( rc, plotContext );
268 painter->drawImage( QPointF( 0, 0 ), mImage );
272 void setSubsectionsSymbol( QgsLineSymbol *symbol )
276 mRenderer->setSubsectionsSymbol( symbol );
281 QgsProject *mProject =
nullptr;
282 double mXScaleFactor = 1.0;
289 QMap<QString, QImage> mCachedImages;
293 QgsProfilePlotRenderer *mRenderer =
nullptr;
299 QgsElevationProfileCrossHairsItem( QgsElevationProfileCanvas *canvas, QgsElevationProfilePlotItem *plotItem )
300 : QgsPlotCanvasItem( canvas )
301 , mPlotItem( plotItem )
306 mRect = mCanvas->rect();
308 prepareGeometryChange();
309 setPos( mRect.topLeft() );
313 void setPoint(
const QgsProfilePoint &point )
319 QRectF boundingRect()
const override {
return mRect; }
322 void paint( QPainter *painter )
override
324 const QgsPointXY crossHairPlotPoint = mPlotItem->plotPointToCanvasPoint( mPoint );
325 if ( crossHairPlotPoint.
isEmpty() )
329 painter->setBrush( Qt::NoBrush );
331 crossHairPen.setCosmetic(
true );
332 crossHairPen.setWidthF( 1 );
333 crossHairPen.setStyle( Qt::DashLine );
334 crossHairPen.setCapStyle( Qt::FlatCap );
335 const QPalette scenePalette = mPlotItem->scene()->palette();
336 QColor penColor = scenePalette.color( QPalette::ColorGroup::Active, QPalette::Text );
337 penColor.setAlpha( 150 );
338 crossHairPen.setColor( penColor );
339 painter->setPen( crossHairPen );
340 painter->drawLine( QPointF( mPlotItem->plotArea().left(), crossHairPlotPoint.
y() ), QPointF( mPlotItem->plotArea().right(), crossHairPlotPoint.
y() ) );
341 painter->drawLine( QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().top() ), QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().bottom() ) );
344 QgsNumericFormatContext numericContext;
346 const QString xCoordinateText = mPlotItem->xAxis().numericFormat()->formatDouble( mPoint.distance() / mPlotItem->mXScaleFactor, numericContext ) + mPlotItem->distanceSuffix();
348 const QString yCoordinateText = mPlotItem->yAxis().numericFormat()->formatDouble( mPoint.elevation(), numericContext );
351 const QFontMetrics fm( font );
352 const double height = fm.capHeight();
353 const double xWidth = fm.horizontalAdvance( xCoordinateText );
354 const double yWidth = fm.horizontalAdvance( yCoordinateText );
355 const double textAxisMargin = fm.horizontalAdvance(
' ' );
357 QPointF xCoordOrigin;
358 QPointF yCoordOrigin;
360 if ( mPoint.distance() < ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5 * mPlotItem->mXScaleFactor )
362 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
365 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
367 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
372 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
374 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
379 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
382 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
384 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
389 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
391 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
396 QColor backgroundColor = mPlotItem->chartBackgroundSymbol()->color();
397 backgroundColor.setAlpha( 220 );
398 painter->setBrush( QBrush( backgroundColor ) );
399 painter->setPen( Qt::NoPen );
400 painter->drawRect( QRectF( xCoordOrigin.x() - textAxisMargin + 1, xCoordOrigin.y() - textAxisMargin - height + 1, xWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
401 painter->drawRect( QRectF( yCoordOrigin.x() - textAxisMargin + 1, yCoordOrigin.y() - textAxisMargin - height + 1, yWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
403 painter->setBrush( Qt::NoBrush );
404 painter->setPen( scenePalette.color( QPalette::ColorGroup::Active, QPalette::Text ) );
406 painter->drawText( xCoordOrigin, xCoordinateText );
407 painter->drawText( yCoordOrigin, yCoordinateText );
413 QgsProfilePoint mPoint;
414 QgsElevationProfilePlotItem *mPlotItem =
nullptr;
424 mPlotItem =
new QgsElevationProfilePlotItem(
this );
429 mCrossHairsItem =
new QgsElevationProfileCrossHairsItem(
this, mPlotItem );
430 mCrossHairsItem->setZValue( 100 );
431 mCrossHairsItem->hide();
434 mDeferredRegenerationTimer =
new QTimer(
this );
435 mDeferredRegenerationTimer->setSingleShot(
true );
436 mDeferredRegenerationTimer->stop();
437 connect( mDeferredRegenerationTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRegeneration );
439 mDeferredRedrawTimer =
new QTimer(
this );
440 mDeferredRedrawTimer->setSingleShot(
true );
441 mDeferredRedrawTimer->stop();
442 connect( mDeferredRedrawTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRedraw );
454 mPlotItem->setRenderer(
nullptr );
455 mCurrentJob->deleteLater();
456 mCurrentJob =
nullptr;
464 mPlotItem->setRenderer(
nullptr );
466 mCurrentJob->cancelGeneration();
467 mCurrentJob->deleteLater();
468 mCurrentJob =
nullptr;
474 const double dxPercent = dx / mPlotItem->plotArea().width();
475 const double dyPercent = dy / mPlotItem->plotArea().height();
478 const double dxPlot = -dxPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
479 const double dyPlot = dyPercent * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
482 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
483 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
484 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
485 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
489 mPlotItem->updatePlot();
495 if ( !mPlotItem->plotArea().contains( x, y ) )
498 const double newCenterX = mPlotItem->xMinimum() + ( x - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
499 const double newCenterY = mPlotItem->yMinimum() + ( mPlotItem->plotArea().bottom() - y ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
501 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
502 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
505 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
506 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
507 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
508 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
512 mPlotItem->updatePlot();
524 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
525 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
526 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
534 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) );
541 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
542 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
543 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
545 QgsProfileIdentifyContext context;
551 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) );
558void QgsElevationProfileCanvas::setupLayerConnections(
QgsMapLayer *layer,
bool isDisconnect )
573 switch ( layer->
type() )
577 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
606void QgsElevationProfileCanvas::adjustRangeForAxisScaleLock(
double &xMinimum,
double &xMaximum,
double &yMinimum,
double &yMaximum )
const
609 const double horizontalScale = ( xMaximum - xMinimum ) / mPlotItem->plotArea().width();
610 const double verticalScale = ( yMaximum - yMinimum ) / mPlotItem->plotArea().height();
612 const double currentRatio = horizontalScale / verticalScale;
614 if ( currentRatio <= mLockedAxisScale )
616 const double height = horizontalScale * mPlotItem->plotArea().height() / mLockedAxisScale;
617 const double deltaHeight = ( yMaximum - yMinimum ) - height;
618 yMinimum += deltaHeight / 2;
619 yMaximum -= deltaHeight / 2;
623 const double width = verticalScale * mPlotItem->plotArea().width() * mLockedAxisScale;
624 const double deltaWidth = ( ( xMaximum - xMinimum ) - width );
625 xMinimum += deltaWidth / 2;
626 xMaximum -= deltaWidth / 2;
632 return mDistanceUnit;
637 mDistanceUnit = unit;
638 const double oldMin = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
639 const double oldMax = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
641 mPlotItem->setXAxisUnits( mDistanceUnit );
642 mPlotItem->setXMinimum( oldMin / mPlotItem->mXScaleFactor );
643 mPlotItem->setXMaximum( oldMax / mPlotItem->mXScaleFactor );
644 mPlotItem->updatePlot();
650 if ( !color.isValid() )
652 QPalette customPalette = qApp->palette();
653 const QColor baseColor = qApp->palette().color( QPalette::ColorRole::Base );
654 const QColor windowColor = qApp->palette().color( QPalette::ColorRole::Window );
655 customPalette.setColor( QPalette::ColorRole::Base, windowColor );
656 customPalette.setColor( QPalette::ColorRole::Window, baseColor );
657 setPalette( customPalette );
658 scene()->setPalette( customPalette );
663 const bool isDarkTheme = color.lightnessF() < 0.5;
664 QPalette customPalette = qApp->palette();
665 customPalette.setColor( QPalette::ColorRole::Window, color );
668 customPalette.setColor( QPalette::ColorRole::Text, QColor( 255, 255, 255 ) );
669 customPalette.setColor( QPalette::ColorRole::Base, color.lighter( 120 ) );
673 customPalette.setColor( QPalette::ColorRole::Text, QColor( 0, 0, 0 ) );
674 customPalette.setColor( QPalette::ColorRole::Base, color.darker( 120 ) );
677 setPalette( customPalette );
678 scene()->setPalette( customPalette );
681 updateChartFromPalette();
686 return mLockAxisScales;
691 mLockAxisScales = lock;
692 if ( mLockAxisScales )
694 double xMinimum = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
695 double xMaximum = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
696 double yMinimum = mPlotItem->yMinimum();
697 double yMaximum = mPlotItem->yMaximum();
698 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
699 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
700 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
701 mPlotItem->setYMinimum( yMinimum );
702 mPlotItem->setYMaximum( yMaximum );
705 mPlotItem->updatePlot();
713 const double horizontalScale = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / mPlotItem->plotArea().width();
714 const double verticalScale = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / mPlotItem->plotArea().height();
715 return horizontalScale / verticalScale;
720 mLockedAxisScale = scale;
722 double xMinimum = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
723 double xMaximum = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
724 double yMinimum = mPlotItem->yMinimum();
725 double yMaximum = mPlotItem->yMaximum();
726 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
727 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
728 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
729 mPlotItem->setYMinimum( yMinimum );
730 mPlotItem->setYMaximum( yMaximum );
733 mPlotItem->updatePlot();
740 if ( !mCurrentJob || !mSnappingEnabled )
754 if ( mLockAxisScales )
757 const double currentWidth = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor;
758 const double currentHeight = mPlotItem->yMaximum() - mPlotItem->yMinimum();
760 const double newWidth = currentWidth / xFactor;
761 const double newHeight = currentHeight / yFactor;
763 const double currentCenterX = ( mPlotItem->xMinimum() + mPlotItem->xMaximum() ) * 0.5 * mPlotItem->mXScaleFactor;
764 const double currentCenterY = ( mPlotItem->yMinimum() + mPlotItem->yMaximum() ) * 0.5;
766 double xMinimum = currentCenterX - newWidth * 0.5;
767 double xMaximum = currentCenterX + newWidth * 0.5;
768 double yMinimum = currentCenterY - newHeight * 0.5;
769 double yMaximum = currentCenterY + newHeight * 0.5;
770 if ( mLockAxisScales )
772 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
775 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
776 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
777 mPlotItem->setYMinimum( yMinimum );
778 mPlotItem->setYMaximum( yMaximum );
781 mPlotItem->updatePlot();
788 const QRectF intersected = rect.intersected( mPlotItem->plotArea() );
790 double minX = ( intersected.left() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor
791 + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
792 double maxX = ( intersected.right() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor
793 + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
794 double minY = ( mPlotItem->plotArea().bottom() - intersected.bottom() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
795 double maxY = ( mPlotItem->plotArea().bottom() - intersected.top() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
797 if ( mLockAxisScales )
799 adjustRangeForAxisScaleLock( minX, maxX, minY, maxY );
802 mPlotItem->setXMinimum( minX / mPlotItem->mXScaleFactor );
803 mPlotItem->setXMaximum( maxX / mPlotItem->mXScaleFactor );
804 mPlotItem->setYMinimum( minY );
805 mPlotItem->setYMaximum( maxY );
808 mPlotItem->updatePlot();
817 double zoomFactor = settings.
value( u
"qgis/zoom_factor"_s, 2 ).toDouble();
818 bool reverseZoom = settings.
value( u
"qgis/reverse_wheel_zoom"_s,
false ).toBool();
819 bool zoomIn = reverseZoom ?
event->angleDelta().y() < 0 :
event->angleDelta().y() > 0;
822 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs(
event->angleDelta().y() );
824 if (
event->modifiers() & Qt::ControlModifier )
827 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
831 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
833 QRectF viewportRect = mPlotItem->plotArea();
835 if ( viewportRect.contains(
event->position() ) )
838 const double oldCenterX = 0.5 * ( mPlotItem->xMaximum() + mPlotItem->xMinimum() );
839 const double oldCenterY = 0.5 * ( mPlotItem->yMaximum() + mPlotItem->yMinimum() );
841 const double eventPosX = (
event->position().x() - viewportRect.left() ) / viewportRect.width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
842 const double eventPosY = ( viewportRect.bottom() -
event->position().y() ) / viewportRect.height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
844 const double newCenterX = eventPosX + ( ( oldCenterX - eventPosX ) * scaleFactor );
845 const double newCenterY = eventPosY + ( ( oldCenterY - eventPosY ) * scaleFactor );
847 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
848 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
851 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
852 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
853 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
854 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
873 if ( e->isAccepted() )
875 mCrossHairsItem->hide();
880 if ( mCurrentJob && mSnappingEnabled && !plotPoint.
isEmpty() )
889 mCrossHairsItem->hide();
893 mCrossHairsItem->setPoint( plotPoint );
894 mCrossHairsItem->show();
901 return mPlotItem->plotArea();
915 request.
setTerrainProvider( mProject->elevationProperties()->terrainProvider() ? mProject->elevationProperties()->terrainProvider()->clone() :
nullptr );
921 QList< QgsAbstractProfileSource *> sourcesToRender =
sources();
922 std::reverse( sourcesToRender.begin(), sourcesToRender.end() );
928 generationContext.
setDpi( mScreenHelper->screenDpi() );
929 generationContext.
setMaximumErrorMapUnits( MAX_ERROR_PIXELS * ( mProfileCurve->length() ) / mPlotItem->plotArea().width() );
931 mCurrentJob->setContext( generationContext );
933 if ( mSubsectionsSymbol )
935 mCurrentJob->setSubsectionsSymbol( mSubsectionsSymbol->clone() );
938 mCurrentJob->startGeneration();
939 mPlotItem->setRenderer( mCurrentJob );
946 mZoomFullWhenJobFinished =
true;
949void QgsElevationProfileCanvas::generationFinished()
956 if ( mZoomFullWhenJobFinished )
959 mZoomFullWhenJobFinished =
false;
968 mPlotItem->updatePlot();
971 if ( mForceRegenerationAfterCurrentJobCompletes )
973 mForceRegenerationAfterCurrentJobCompletes =
false;
974 mCurrentJob->invalidateAllRefinableSources();
975 scheduleDeferredRegeneration();
979void QgsElevationProfileCanvas::onLayerProfileGenerationPropertyChanged()
982 if ( !mCurrentJob || mCurrentJob->isActive() )
985 QgsMapLayerElevationProperties *properties = qobject_cast<QgsMapLayerElevationProperties *>( sender() );
989 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( properties->parent() ) )
991 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
993 if ( mCurrentJob->invalidateResults( source ) )
994 scheduleDeferredRegeneration();
999void QgsElevationProfileCanvas::onLayerProfileRendererPropertyChanged()
1002 if ( !mCurrentJob || mCurrentJob->isActive() )
1005 QgsMapLayerElevationProperties *properties = qobject_cast<QgsMapLayerElevationProperties *>( sender() );
1009 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( properties->parent() ) )
1011 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1013 mCurrentJob->replaceSource( source );
1015 if ( mPlotItem->redrawResults( layer->
id() ) )
1016 scheduleDeferredRedraw();
1020void QgsElevationProfileCanvas::regenerateResultsForLayer()
1025 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() ) )
1027 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1029 if ( mCurrentJob->invalidateResults( source ) )
1030 scheduleDeferredRegeneration();
1035void QgsElevationProfileCanvas::scheduleDeferredRegeneration()
1037 if ( !mDeferredRegenerationScheduled )
1039 mDeferredRegenerationTimer->start( 1 );
1040 mDeferredRegenerationScheduled =
true;
1044void QgsElevationProfileCanvas::scheduleDeferredRedraw()
1046 if ( !mDeferredRedrawScheduled )
1048 mDeferredRedrawTimer->start( 1 );
1049 mDeferredRedrawScheduled =
true;
1053void QgsElevationProfileCanvas::startDeferredRegeneration()
1055 if ( mCurrentJob && !mCurrentJob->isActive() )
1058 mCurrentJob->regenerateInvalidatedResults();
1060 else if ( mCurrentJob )
1062 mForceRegenerationAfterCurrentJobCompletes =
true;
1065 mDeferredRegenerationScheduled =
false;
1068void QgsElevationProfileCanvas::startDeferredRedraw()
1070 mPlotItem->update();
1071 mDeferredRedrawScheduled =
false;
1074void QgsElevationProfileCanvas::refineResults()
1078 QgsProfileGenerationContext context;
1079 context.
setDpi( mScreenHelper->screenDpi() );
1080 const double plotDistanceRange = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor;
1081 const double plotElevationRange = mPlotItem->yMaximum() - mPlotItem->yMinimum();
1082 const double plotDistanceUnitsPerPixel = plotDistanceRange / mPlotItem->plotArea().width();
1086 const double targetMaxErrorInMapUnits = MAX_ERROR_PIXELS * plotDistanceUnitsPerPixel;
1087 const double factor = std::pow( 10.0, 1 - std::ceil( std::log10( std::fabs( targetMaxErrorInMapUnits ) ) ) );
1088 const double roundedErrorInMapUnits = std::floor( targetMaxErrorInMapUnits * factor ) / factor;
1095 context.
setDistanceRange( QgsDoubleRange( std::max( 0.0, distanceMin ), mPlotItem->xMaximum() * mPlotItem->mXScaleFactor + plotDistanceRange * 0.05 ) );
1097 context.
setElevationRange( QgsDoubleRange( mPlotItem->yMinimum() - plotElevationRange * 0.05, mPlotItem->yMaximum() + plotElevationRange * 0.05 ) );
1098 mCurrentJob->setContext( context );
1100 scheduleDeferredRegeneration();
1103void QgsElevationProfileCanvas::updateChartFromPalette()
1105 const QPalette chartPalette = palette();
1106 setBackgroundBrush( QBrush( chartPalette.color( QPalette::ColorRole::Base ) ) );
1108 QgsTextFormat textFormat = mPlotItem->xAxis().textFormat();
1109 textFormat.
setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::Text ) );
1110 mPlotItem->xAxis().setTextFormat( textFormat );
1111 mPlotItem->yAxis().setTextFormat( textFormat );
1114 std::unique_ptr<QgsFillSymbol> chartFill( mPlotItem->chartBackgroundSymbol()->clone() );
1115 chartFill->setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Window ) );
1116 mPlotItem->setChartBackgroundSymbol( chartFill.release() );
1119 std::unique_ptr<QgsFillSymbol> chartBorder( mPlotItem->chartBorderSymbol()->clone() );
1120 chartBorder->setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text ) );
1121 mPlotItem->setChartBorderSymbol( chartBorder.release() );
1124 std::unique_ptr<QgsLineSymbol> chartMajorSymbol( mPlotItem->xAxis().gridMajorSymbol()->clone() );
1125 QColor
c = chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text );
1127 chartMajorSymbol->setColor(
c );
1128 mPlotItem->xAxis().setGridMajorSymbol( chartMajorSymbol->clone() );
1129 mPlotItem->yAxis().setGridMajorSymbol( chartMajorSymbol.release() );
1132 std::unique_ptr<QgsLineSymbol> chartMinorSymbol( mPlotItem->xAxis().gridMinorSymbol()->clone() );
1133 QColor
c = chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text );
1135 chartMinorSymbol->setColor(
c );
1136 mPlotItem->xAxis().setGridMinorSymbol( chartMinorSymbol->clone() );
1137 mPlotItem->yAxis().setGridMinorSymbol( chartMinorSymbol.release() );
1139 mPlotItem->updatePlot();
1144 if ( !mPlotItem->plotArea().contains( point.x(), point.y() ) )
1147 return mPlotItem->canvasPointToPlotPoint( point );
1152 return mPlotItem->plotPointToCanvasPoint( point );
1158 mPlotItem->mProject = project;
1168 mProfileCurve.reset( curve );
1173 return mProfileCurve.get();
1188 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
1190 setupLayerConnections( layer,
true );
1194 auto filteredList =
layers;
1195 filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(), [](
QgsMapLayer *layer ) { return !layer || !layer->isValid(); } ), filteredList.end() );
1197 mLayers = _qgis_listRawToQPointer( filteredList );
1198 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
1200 setupLayerConnections( layer,
false );
1206 return _qgis_listQPointerToRaw( mLayers );
1212 mSources.reserve(
sources.count() );
1215 if (
auto layer =
dynamic_cast<QgsMapLayer *
>( profileSource ) )
1221 mSources << profileSource;
1228 if ( mSources.isEmpty() && !mLayers.isEmpty() )
1234 QList< QgsAbstractProfileSource * >
sources;
1235 const QList<QgsMapLayer *> layersToGenerate =
layers();
1236 sources.reserve( layersToGenerate.size() );
1251 QList< QgsAbstractProfileSource * >
sources;
1252 sources.reserve( mSources.count() );
1253 for (
const auto &source : mSources )
1257 if (
QgsMapLayer *layer = weakLayerPointer->data() )
1262 else if (
auto profileSource = std::get_if< QgsAbstractProfileSource * >( &source ) )
1278 if ( mLockAxisScales )
1280 double xMinimum = mPlotItem->xMinimum();
1281 double xMaximum = mPlotItem->xMaximum();
1282 double yMinimum = mPlotItem->yMinimum();
1283 double yMaximum = mPlotItem->yMaximum();
1284 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
1285 mPlotItem->setXMinimum( xMinimum );
1286 mPlotItem->setXMaximum( xMaximum );
1287 mPlotItem->setYMinimum( yMinimum );
1288 mPlotItem->setYMaximum( yMaximum );
1291 mPlotItem->updateRect();
1292 mCrossHairsItem->updateRect();
1299 QgsPlotCanvas::paintEvent(
event );
1301 if ( !mFirstDrawOccurred )
1304 mFirstDrawOccurred =
true;
1305 mPlotItem->updateRect();
1306 mCrossHairsItem->updateRect();
1312 if ( !mPlotItem->plotArea().contains( point.
x(), point.
y() ) )
1315 if ( !mProfileCurve )
1318 const double dx = point.
x() - mPlotItem->plotArea().left();
1320 const double distanceAlongPlotPercent = dx / mPlotItem->plotArea().width();
1321 double distanceAlongCurveLength = distanceAlongPlotPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
1323 std::unique_ptr<QgsPoint> mapXyPoint( mProfileCurve->interpolatePoint( distanceAlongCurveLength ) );
1327 const double mapZ = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * ( mPlotItem->plotArea().bottom() - point.
y() ) + mPlotItem->yMinimum();
1329 return QgsPoint( mapXyPoint->x(), mapXyPoint->y(), mapZ );
1334 if ( !mProfileCurve )
1339 const double distanceAlongCurve =
geos.lineLocatePoint( point, &error );
1341 const double distanceAlongCurveOnPlot = distanceAlongCurve - mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
1342 const double distanceAlongCurvePercent = distanceAlongCurveOnPlot / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor );
1343 const double distanceAlongPlotRect = distanceAlongCurvePercent * mPlotItem->plotArea().width();
1345 const double canvasX = mPlotItem->plotArea().left() + distanceAlongPlotRect;
1348 if ( std::isnan( point.
z() ) || point.
z() < mPlotItem->yMinimum() )
1350 canvasY = mPlotItem->plotArea().top();
1352 else if ( point.
z() > mPlotItem->yMaximum() )
1354 canvasY = mPlotItem->plotArea().bottom();
1358 const double yPercent = ( point.
z() - mPlotItem->yMinimum() ) / ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
1359 canvasY = mPlotItem->plotArea().bottom() - mPlotItem->plotArea().height() * yPercent;
1372 double yMinimum = 0;
1373 double yMaximum = 0;
1384 yMinimum = zRange.
lower() - 5;
1385 yMaximum = zRange.
lower() + 5;
1390 const double margin = ( zRange.
upper() - zRange.
lower() ) * 0.05;
1391 yMinimum = zRange.
lower() - margin;
1392 yMaximum = zRange.
upper() + margin;
1396 double xMinimum = 0;
1398 double xMaximum = profileLength * 1.02;
1400 if ( mLockAxisScales )
1402 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
1405 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
1406 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
1407 mPlotItem->setYMinimum( yMinimum );
1408 mPlotItem->setYMaximum( yMaximum );
1411 mPlotItem->updatePlot();
1418 if ( mLockAxisScales )
1420 adjustRangeForAxisScaleLock( minimumDistance, maximumDistance, minimumElevation, maximumElevation );
1423 mPlotItem->setYMinimum( minimumElevation );
1424 mPlotItem->setYMaximum( maximumElevation );
1425 mPlotItem->setXMinimum( minimumDistance / mPlotItem->mXScaleFactor );
1426 mPlotItem->setXMaximum( maximumDistance / mPlotItem->mXScaleFactor );
1428 mPlotItem->updatePlot();
1435 return QgsDoubleRange( mPlotItem->xMinimum() * mPlotItem->mXScaleFactor, mPlotItem->xMaximum() * mPlotItem->mXScaleFactor );
1440 return QgsDoubleRange( mPlotItem->yMinimum(), mPlotItem->yMaximum() );
1453 : mRenderer( renderer )
1456 void renderContent( QgsRenderContext &rc, QgsPlotRenderContext &,
const QRectF &plotArea,
const QgsPlotData & )
override
1461 rc.
painter()->translate( plotArea.left(), plotArea.top() );
1462 mRenderer->render( rc, plotArea.width(), plotArea.height(), xMinimum() * mXScale,
xMaximum() * mXScale,
yMinimum(),
yMaximum() );
1463 rc.
painter()->translate( -plotArea.left(), -plotArea.top() );
1469 QgsProfilePlotRenderer *mRenderer =
nullptr;
1481 QgsElevationProfilePlot profilePlot( mCurrentJob );
1485 QDomElement elem = doc.createElement( u
"plot"_s );
1487 plotSettings.
writeXml( elem, doc, rwContext );
1488 profilePlot.readXml( elem, rwContext );
1490 profilePlot.mXScale = mPlotItem->mXScaleFactor;
1491 profilePlot.xAxis().setLabelSuffix( mPlotItem->xAxis().labelSuffix() );
1492 profilePlot.xAxis().setLabelSuffixPlacement( mPlotItem->xAxis().labelSuffixPlacement() );
1494 profilePlot.setSize( QSizeF( width, height ) );
1496 profilePlot.render( context, plotContext );
1506 return mCurrentJob->identify( plotPoint, identifyContext() );
1517 double distance1 = topLeftPlotPoint.
distance();
1518 double distance2 = bottomRightPlotPoint.
distance();
1519 if ( distance2 < distance1 )
1520 std::swap( distance1, distance2 );
1522 double elevation1 = topLeftPlotPoint.
elevation();
1523 double elevation2 = bottomRightPlotPoint.
elevation();
1524 if ( elevation2 < elevation1 )
1525 std::swap( elevation1, elevation2 );
1534 mPlotItem->updatePlot();
1539 mSnappingEnabled = enabled;
1544 mSubsectionsSymbol.reset( symbol );
1545 std::unique_ptr<QgsLineSymbol> plotItemSymbol( mSubsectionsSymbol ? mSubsectionsSymbol->clone() :
nullptr );
1546 mPlotItem->setSubsectionsSymbol( plotItemSymbol.release() );
1549void 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 QgsPlotData &plotData=QgsPlotData()) 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.
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).
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.