46#include "moc_qgselevationprofilecanvas.cpp"
52 QgsElevationProfilePlotItem( QgsElevationProfileCanvas *canvas )
53 : QgsPlotCanvasItem( canvas )
61 void setRenderer( QgsProfilePlotRenderer *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
104 QString distanceSuffix()
const
106 switch ( mDistanceUnit )
159 return QObject::tr(
"°" );
168 mDistanceUnit = unit;
175 if ( !mPlotArea.isNull() )
179 QgsRenderContext context;
180 if ( !scene()->views().isEmpty() )
181 context.
setScaleFactor( scene()->views().at( 0 )->logicalDpiX() / 25.4 );
183 QgsPlotRenderContext plotContext;
189 QgsProfilePoint canvasPointToPlotPoint( QPointF point )
191 const QRectF area = plotArea();
192 if ( !area.contains( point.x(), point.y() ) )
193 return QgsProfilePoint();
195 const double distance = ( point.x() - area.left() ) / area.width() * (
xMaximum() -
xMinimum() ) * mXScaleFactor +
xMinimum() * mXScaleFactor;
197 return QgsProfilePoint( distance, elevation );
200 QgsPointXY plotPointToCanvasPoint(
const QgsProfilePoint &point )
202 if ( point.
distance() < xMinimum() * mXScaleFactor || point.
distance() > xMaximum() * mXScaleFactor || point.
elevation() < yMinimum() || point.
elevation() > yMaximum() )
205 const QRectF area = plotArea();
209 return QgsPointXY( x, y );
212 void renderContent( QgsRenderContext &rc, QgsPlotRenderContext &,
const QRectF &plotArea,
const QgsPlotData & )
override
214 mPlotArea = plotArea;
219 const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
221 const QStringList sourceIds = mRenderer->sourceIds();
222 for (
const QString &source : sourceIds )
225 auto it = mCachedImages.constFind( source );
226 if ( it != mCachedImages.constEnd() )
232 plot = mRenderer->renderToImage( plotArea.width() * pixelRatio, plotArea.height() * pixelRatio, xMinimum() * mXScaleFactor,
xMaximum() * mXScaleFactor,
yMinimum(),
yMaximum(), source, pixelRatio );
233 plot.setDevicePixelRatio( pixelRatio );
234 mCachedImages.insert( source, plot );
236 rc.
painter()->drawImage( QPointF( plotArea.left(), plotArea.top() ), plot );
240 void paint( QPainter *painter )
override
243 if ( !mImage.isNull() )
245 painter->drawImage( QPointF( 0, 0 ), mImage );
249 const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
250 mImage = QImage( mRect.width() * pixelRatio, mRect.height() * pixelRatio, QImage::Format_ARGB32_Premultiplied );
251 mImage.setDevicePixelRatio( pixelRatio );
252 mImage.fill( Qt::transparent );
254 QPainter imagePainter( &mImage );
255 imagePainter.setRenderHint( QPainter::Antialiasing,
true );
259 const double mapUnitsPerPixel = (
xMaximum() -
xMinimum() ) * mXScaleFactor / plotArea().width();
265 QgsPlotRenderContext plotContext;
267 render( rc, plotContext );
270 painter->drawImage( QPointF( 0, 0 ), mImage );
274 void setSubsectionsSymbol( QgsLineSymbol *symbol )
278 mRenderer->setSubsectionsSymbol( symbol );
283 QgsProject *mProject =
nullptr;
284 double mXScaleFactor = 1.0;
291 QMap<QString, QImage> mCachedImages;
295 QgsProfilePlotRenderer *mRenderer =
nullptr;
301 QgsElevationProfileCrossHairsItem( QgsElevationProfileCanvas *canvas, QgsElevationProfilePlotItem *plotItem )
302 : QgsPlotCanvasItem( canvas )
303 , mPlotItem( plotItem )
309 mRect = mCanvas->rect();
311 prepareGeometryChange();
312 setPos( mRect.topLeft() );
316 void setPoint(
const QgsProfilePoint &point )
322 QRectF boundingRect()
const override
327 void paint( QPainter *painter )
override
329 const QgsPointXY crossHairPlotPoint = mPlotItem->plotPointToCanvasPoint( mPoint );
330 if ( crossHairPlotPoint.
isEmpty() )
334 painter->setBrush( Qt::NoBrush );
336 crossHairPen.setCosmetic(
true );
337 crossHairPen.setWidthF( 1 );
338 crossHairPen.setStyle( Qt::DashLine );
339 crossHairPen.setCapStyle( Qt::FlatCap );
340 const QPalette scenePalette = mPlotItem->scene()->palette();
341 QColor penColor = scenePalette.color( QPalette::ColorGroup::Active, QPalette::Text );
342 penColor.setAlpha( 150 );
343 crossHairPen.setColor( penColor );
344 painter->setPen( crossHairPen );
345 painter->drawLine( QPointF( mPlotItem->plotArea().left(), crossHairPlotPoint.
y() ), QPointF( mPlotItem->plotArea().right(), crossHairPlotPoint.
y() ) );
346 painter->drawLine( QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().top() ), QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().bottom() ) );
349 QgsNumericFormatContext numericContext;
351 const QString xCoordinateText = mPlotItem->xAxis().numericFormat()->formatDouble( mPoint.distance() / mPlotItem->mXScaleFactor, numericContext )
352 + mPlotItem->distanceSuffix();
354 const QString yCoordinateText = mPlotItem->yAxis().numericFormat()->formatDouble( mPoint.elevation(), numericContext );
357 const QFontMetrics fm( font );
358 const double height = fm.capHeight();
359 const double xWidth = fm.horizontalAdvance( xCoordinateText );
360 const double yWidth = fm.horizontalAdvance( yCoordinateText );
361 const double textAxisMargin = fm.horizontalAdvance(
' ' );
363 QPointF xCoordOrigin;
364 QPointF yCoordOrigin;
366 if ( mPoint.distance() < ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5 * mPlotItem->mXScaleFactor )
368 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
371 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
373 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
378 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
380 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
385 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
388 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
390 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
395 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
397 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
402 QColor backgroundColor = mPlotItem->chartBackgroundSymbol()->color();
403 backgroundColor.setAlpha( 220 );
404 painter->setBrush( QBrush( backgroundColor ) );
405 painter->setPen( Qt::NoPen );
406 painter->drawRect( QRectF( xCoordOrigin.x() - textAxisMargin + 1, xCoordOrigin.y() - textAxisMargin - height + 1, xWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
407 painter->drawRect( QRectF( yCoordOrigin.x() - textAxisMargin + 1, yCoordOrigin.y() - textAxisMargin - height + 1, yWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
409 painter->setBrush( Qt::NoBrush );
410 painter->setPen( scenePalette.color( QPalette::ColorGroup::Active, QPalette::Text ) );
412 painter->drawText( xCoordOrigin, xCoordinateText );
413 painter->drawText( yCoordOrigin, yCoordinateText );
419 QgsProfilePoint mPoint;
420 QgsElevationProfilePlotItem *mPlotItem =
nullptr;
430 mPlotItem =
new QgsElevationProfilePlotItem(
this );
435 mCrossHairsItem =
new QgsElevationProfileCrossHairsItem(
this, mPlotItem );
436 mCrossHairsItem->setZValue( 100 );
437 mCrossHairsItem->hide();
440 mDeferredRegenerationTimer =
new QTimer(
this );
441 mDeferredRegenerationTimer->setSingleShot(
true );
442 mDeferredRegenerationTimer->stop();
443 connect( mDeferredRegenerationTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRegeneration );
445 mDeferredRedrawTimer =
new QTimer(
this );
446 mDeferredRedrawTimer->setSingleShot(
true );
447 mDeferredRedrawTimer->stop();
448 connect( mDeferredRedrawTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRedraw );
460 mPlotItem->setRenderer(
nullptr );
461 mCurrentJob->deleteLater();
462 mCurrentJob =
nullptr;
470 mPlotItem->setRenderer(
nullptr );
472 mCurrentJob->cancelGeneration();
473 mCurrentJob->deleteLater();
474 mCurrentJob =
nullptr;
480 const double dxPercent = dx / mPlotItem->plotArea().width();
481 const double dyPercent = dy / mPlotItem->plotArea().height();
484 const double dxPlot = -dxPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
485 const double dyPlot = dyPercent * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
488 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
489 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
490 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
491 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
495 mPlotItem->updatePlot();
501 if ( !mPlotItem->plotArea().contains( x, y ) )
504 const double newCenterX = mPlotItem->xMinimum() + ( x - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
505 const double newCenterY = mPlotItem->yMinimum() + ( mPlotItem->plotArea().bottom() - y ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
507 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
508 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
511 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
512 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
513 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
514 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
518 mPlotItem->updatePlot();
530 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
531 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
532 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
540 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) );
547 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
548 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
549 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
551 QgsProfileIdentifyContext context;
557 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / ( mPlotItem->plotArea().width() ) );
564void QgsElevationProfileCanvas::setupLayerConnections(
QgsMapLayer *layer,
bool isDisconnect )
579 switch ( layer->
type() )
583 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
612void QgsElevationProfileCanvas::adjustRangeForAxisScaleLock(
double &xMinimum,
double &xMaximum,
double &yMinimum,
double &yMaximum )
const
615 const double horizontalScale = ( xMaximum - xMinimum ) / mPlotItem->plotArea().width();
616 const double verticalScale = ( yMaximum - yMinimum ) / mPlotItem->plotArea().height();
618 const double currentRatio = horizontalScale / verticalScale;
620 if ( currentRatio <= mLockedAxisScale )
622 const double height = horizontalScale * mPlotItem->plotArea().height() / mLockedAxisScale;
623 const double deltaHeight = ( yMaximum - yMinimum ) - height;
624 yMinimum += deltaHeight / 2;
625 yMaximum -= deltaHeight / 2;
629 const double width = verticalScale * mPlotItem->plotArea().width() * mLockedAxisScale;
630 const double deltaWidth = ( ( xMaximum - xMinimum ) - width );
631 xMinimum += deltaWidth / 2;
632 xMaximum -= deltaWidth / 2;
638 return mDistanceUnit;
643 mDistanceUnit = unit;
644 const double oldMin = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
645 const double oldMax = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
647 mPlotItem->setXAxisUnits( mDistanceUnit );
648 mPlotItem->setXMinimum( oldMin / mPlotItem->mXScaleFactor );
649 mPlotItem->setXMaximum( oldMax / mPlotItem->mXScaleFactor );
650 mPlotItem->updatePlot();
656 if ( !color.isValid() )
658 QPalette customPalette = qApp->palette();
659 const QColor baseColor = qApp->palette().color( QPalette::ColorRole::Base );
660 const QColor windowColor = qApp->palette().color( QPalette::ColorRole::Window );
661 customPalette.setColor( QPalette::ColorRole::Base, windowColor );
662 customPalette.setColor( QPalette::ColorRole::Window, baseColor );
663 setPalette( customPalette );
664 scene()->setPalette( customPalette );
669 const bool isDarkTheme = color.lightnessF() < 0.5;
670 QPalette customPalette = qApp->palette();
671 customPalette.setColor( QPalette::ColorRole::Window, color );
674 customPalette.setColor( QPalette::ColorRole::Text, QColor( 255, 255, 255 ) );
675 customPalette.setColor( QPalette::ColorRole::Base, color.lighter( 120 ) );
679 customPalette.setColor( QPalette::ColorRole::Text, QColor( 0, 0, 0 ) );
680 customPalette.setColor( QPalette::ColorRole::Base, color.darker( 120 ) );
683 setPalette( customPalette );
684 scene()->setPalette( customPalette );
687 updateChartFromPalette();
692 return mLockAxisScales;
697 mLockAxisScales = lock;
698 if ( mLockAxisScales )
700 double xMinimum = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
701 double xMaximum = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
702 double yMinimum = mPlotItem->yMinimum();
703 double yMaximum = mPlotItem->yMaximum();
704 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
705 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
706 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
707 mPlotItem->setYMinimum( yMinimum );
708 mPlotItem->setYMaximum( yMaximum );
711 mPlotItem->updatePlot();
719 const double horizontalScale = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor / mPlotItem->plotArea().width();
720 const double verticalScale = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / mPlotItem->plotArea().height();
721 return horizontalScale / verticalScale;
726 mLockedAxisScale = scale;
728 double xMinimum = mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
729 double xMaximum = mPlotItem->xMaximum() * mPlotItem->mXScaleFactor;
730 double yMinimum = mPlotItem->yMinimum();
731 double yMaximum = mPlotItem->yMaximum();
732 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
733 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
734 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
735 mPlotItem->setYMinimum( yMinimum );
736 mPlotItem->setYMaximum( yMaximum );
739 mPlotItem->updatePlot();
746 if ( !mCurrentJob || !mSnappingEnabled )
760 if ( mLockAxisScales )
763 const double currentWidth = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor;
764 const double currentHeight = mPlotItem->yMaximum() - mPlotItem->yMinimum();
766 const double newWidth = currentWidth / xFactor;
767 const double newHeight = currentHeight / yFactor;
769 const double currentCenterX = ( mPlotItem->xMinimum() + mPlotItem->xMaximum() ) * 0.5 * mPlotItem->mXScaleFactor;
770 const double currentCenterY = ( mPlotItem->yMinimum() + mPlotItem->yMaximum() ) * 0.5;
772 double xMinimum = currentCenterX - newWidth * 0.5;
773 double xMaximum = currentCenterX + newWidth * 0.5;
774 double yMinimum = currentCenterY - newHeight * 0.5;
775 double yMaximum = currentCenterY + newHeight * 0.5;
776 if ( mLockAxisScales )
778 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
781 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
782 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
783 mPlotItem->setYMinimum( yMinimum );
784 mPlotItem->setYMaximum( yMaximum );
787 mPlotItem->updatePlot();
794 const QRectF intersected = rect.intersected( mPlotItem->plotArea() );
796 double minX = ( intersected.left() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
797 double maxX = ( intersected.right() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
798 double minY = ( mPlotItem->plotArea().bottom() - intersected.bottom() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
799 double maxY = ( mPlotItem->plotArea().bottom() - intersected.top() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
801 if ( mLockAxisScales )
803 adjustRangeForAxisScaleLock( minX, maxX, minY, maxY );
806 mPlotItem->setXMinimum( minX / mPlotItem->mXScaleFactor );
807 mPlotItem->setXMaximum( maxX / mPlotItem->mXScaleFactor );
808 mPlotItem->setYMinimum( minY );
809 mPlotItem->setYMaximum( maxY );
812 mPlotItem->updatePlot();
821 double zoomFactor = settings.
value( QStringLiteral(
"qgis/zoom_factor" ), 2 ).toDouble();
822 bool reverseZoom = settings.
value( QStringLiteral(
"qgis/reverse_wheel_zoom" ),
false ).toBool();
823 bool zoomIn = reverseZoom ?
event->angleDelta().y() < 0 :
event->angleDelta().y() > 0;
826 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs(
event->angleDelta().y() );
828 if (
event->modifiers() & Qt::ControlModifier )
831 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
835 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
837 QRectF viewportRect = mPlotItem->plotArea();
839 if ( viewportRect.contains(
event->position() ) )
842 const double oldCenterX = 0.5 * ( mPlotItem->xMaximum() + mPlotItem->xMinimum() );
843 const double oldCenterY = 0.5 * ( mPlotItem->yMaximum() + mPlotItem->yMinimum() );
845 const double eventPosX = (
event->position().x() - viewportRect.left() ) / viewportRect.width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
846 const double eventPosY = ( viewportRect.bottom() -
event->position().y() ) / viewportRect.height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
848 const double newCenterX = eventPosX + ( ( oldCenterX - eventPosX ) * scaleFactor );
849 const double newCenterY = eventPosY + ( ( oldCenterY - eventPosY ) * scaleFactor );
851 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
852 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
855 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
856 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
857 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
858 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
877 if ( e->isAccepted() )
879 mCrossHairsItem->hide();
884 if ( mCurrentJob && mSnappingEnabled && !plotPoint.
isEmpty() )
893 mCrossHairsItem->hide();
897 mCrossHairsItem->setPoint( plotPoint );
898 mCrossHairsItem->show();
905 return mPlotItem->plotArea();
919 request.
setTerrainProvider( mProject->elevationProperties()->terrainProvider() ? mProject->elevationProperties()->terrainProvider()->clone() :
nullptr );
925 QList< QgsAbstractProfileSource *> sourcesToRender =
sources();
926 std::reverse( sourcesToRender.begin(), sourcesToRender.end() );
932 generationContext.
setDpi( mScreenHelper->screenDpi() );
933 generationContext.
setMaximumErrorMapUnits( MAX_ERROR_PIXELS * ( mProfileCurve->length() ) / mPlotItem->plotArea().width() );
935 mCurrentJob->setContext( generationContext );
937 if ( mSubsectionsSymbol )
939 mCurrentJob->setSubsectionsSymbol( mSubsectionsSymbol->clone() );
942 mCurrentJob->startGeneration();
943 mPlotItem->setRenderer( mCurrentJob );
950 mZoomFullWhenJobFinished =
true;
953void QgsElevationProfileCanvas::generationFinished()
960 if ( mZoomFullWhenJobFinished )
963 mZoomFullWhenJobFinished =
false;
972 mPlotItem->updatePlot();
975 if ( mForceRegenerationAfterCurrentJobCompletes )
977 mForceRegenerationAfterCurrentJobCompletes =
false;
978 mCurrentJob->invalidateAllRefinableSources();
979 scheduleDeferredRegeneration();
983void QgsElevationProfileCanvas::onLayerProfileGenerationPropertyChanged()
986 if ( !mCurrentJob || mCurrentJob->isActive() )
989 QgsMapLayerElevationProperties *properties = qobject_cast<QgsMapLayerElevationProperties *>( sender() );
993 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( properties->parent() ) )
995 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
997 if ( mCurrentJob->invalidateResults( source ) )
998 scheduleDeferredRegeneration();
1003void QgsElevationProfileCanvas::onLayerProfileRendererPropertyChanged()
1006 if ( !mCurrentJob || mCurrentJob->isActive() )
1009 QgsMapLayerElevationProperties *properties = qobject_cast<QgsMapLayerElevationProperties *>( sender() );
1013 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( properties->parent() ) )
1015 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1017 mCurrentJob->replaceSource( source );
1019 if ( mPlotItem->redrawResults( layer->
id() ) )
1020 scheduleDeferredRedraw();
1024void QgsElevationProfileCanvas::regenerateResultsForLayer()
1029 if ( QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() ) )
1031 if ( QgsAbstractProfileSource *source = layer->
profileSource() )
1033 if ( mCurrentJob->invalidateResults( source ) )
1034 scheduleDeferredRegeneration();
1039void QgsElevationProfileCanvas::scheduleDeferredRegeneration()
1041 if ( !mDeferredRegenerationScheduled )
1043 mDeferredRegenerationTimer->start( 1 );
1044 mDeferredRegenerationScheduled =
true;
1048void QgsElevationProfileCanvas::scheduleDeferredRedraw()
1050 if ( !mDeferredRedrawScheduled )
1052 mDeferredRedrawTimer->start( 1 );
1053 mDeferredRedrawScheduled =
true;
1057void QgsElevationProfileCanvas::startDeferredRegeneration()
1059 if ( mCurrentJob && !mCurrentJob->isActive() )
1062 mCurrentJob->regenerateInvalidatedResults();
1064 else if ( mCurrentJob )
1066 mForceRegenerationAfterCurrentJobCompletes =
true;
1069 mDeferredRegenerationScheduled =
false;
1072void QgsElevationProfileCanvas::startDeferredRedraw()
1074 mPlotItem->update();
1075 mDeferredRedrawScheduled =
false;
1078void QgsElevationProfileCanvas::refineResults()
1082 QgsProfileGenerationContext context;
1083 context.
setDpi( mScreenHelper->screenDpi() );
1084 const double plotDistanceRange = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor;
1085 const double plotElevationRange = mPlotItem->yMaximum() - mPlotItem->yMinimum();
1086 const double plotDistanceUnitsPerPixel = plotDistanceRange / mPlotItem->plotArea().width();
1090 const double targetMaxErrorInMapUnits = MAX_ERROR_PIXELS * plotDistanceUnitsPerPixel;
1091 const double factor = std::pow( 10.0, 1 - std::ceil( std::log10( std::fabs( targetMaxErrorInMapUnits ) ) ) );
1092 const double roundedErrorInMapUnits = std::floor( targetMaxErrorInMapUnits * factor ) / factor;
1099 context.
setDistanceRange( QgsDoubleRange( std::max( 0.0, distanceMin ), mPlotItem->xMaximum() * mPlotItem->mXScaleFactor + plotDistanceRange * 0.05 ) );
1101 context.
setElevationRange( QgsDoubleRange( mPlotItem->yMinimum() - plotElevationRange * 0.05, mPlotItem->yMaximum() + plotElevationRange * 0.05 ) );
1102 mCurrentJob->setContext( context );
1104 scheduleDeferredRegeneration();
1107void QgsElevationProfileCanvas::updateChartFromPalette()
1109 const QPalette chartPalette = palette();
1110 setBackgroundBrush( QBrush( chartPalette.color( QPalette::ColorRole::Base ) ) );
1112 QgsTextFormat textFormat = mPlotItem->xAxis().textFormat();
1113 textFormat.
setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::Text ) );
1114 mPlotItem->xAxis().setTextFormat( textFormat );
1115 mPlotItem->yAxis().setTextFormat( textFormat );
1118 std::unique_ptr<QgsFillSymbol> chartFill( mPlotItem->chartBackgroundSymbol()->clone() );
1119 chartFill->setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Window ) );
1120 mPlotItem->setChartBackgroundSymbol( chartFill.release() );
1123 std::unique_ptr<QgsFillSymbol> chartBorder( mPlotItem->chartBorderSymbol()->clone() );
1124 chartBorder->setColor( chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text ) );
1125 mPlotItem->setChartBorderSymbol( chartBorder.release() );
1128 std::unique_ptr<QgsLineSymbol> chartMajorSymbol( mPlotItem->xAxis().gridMajorSymbol()->clone() );
1129 QColor
c = chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text );
1131 chartMajorSymbol->setColor(
c );
1132 mPlotItem->xAxis().setGridMajorSymbol( chartMajorSymbol->clone() );
1133 mPlotItem->yAxis().setGridMajorSymbol( chartMajorSymbol.release() );
1136 std::unique_ptr<QgsLineSymbol> chartMinorSymbol( mPlotItem->xAxis().gridMinorSymbol()->clone() );
1137 QColor
c = chartPalette.color( QPalette::ColorGroup::Active, QPalette::ColorRole::Text );
1139 chartMinorSymbol->setColor(
c );
1140 mPlotItem->xAxis().setGridMinorSymbol( chartMinorSymbol->clone() );
1141 mPlotItem->yAxis().setGridMinorSymbol( chartMinorSymbol.release() );
1143 mPlotItem->updatePlot();
1148 if ( !mPlotItem->plotArea().contains( point.x(), point.y() ) )
1151 return mPlotItem->canvasPointToPlotPoint( point );
1156 return mPlotItem->plotPointToCanvasPoint( point );
1162 mPlotItem->mProject = project;
1172 mProfileCurve.reset( curve );
1177 return mProfileCurve.get();
1192 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
1194 setupLayerConnections( layer,
true );
1198 auto filteredList =
layers;
1199 filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(), [](
QgsMapLayer *layer ) {
1200 return !layer || !layer->isValid();
1202 filteredList.end() );
1204 mLayers = _qgis_listRawToQPointer( filteredList );
1205 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
1207 setupLayerConnections( layer,
false );
1213 return _qgis_listQPointerToRaw( mLayers );
1223 if ( mSources.isEmpty() && !mLayers.isEmpty() )
1229 QList< QgsAbstractProfileSource * >
sources;
1230 const QList<QgsMapLayer *> layersToGenerate =
layers();
1231 sources.reserve( layersToGenerate.size() );
1253 if ( mLockAxisScales )
1255 double xMinimum = mPlotItem->xMinimum();
1256 double xMaximum = mPlotItem->xMaximum();
1257 double yMinimum = mPlotItem->yMinimum();
1258 double yMaximum = mPlotItem->yMaximum();
1259 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
1260 mPlotItem->setXMinimum( xMinimum );
1261 mPlotItem->setXMaximum( xMaximum );
1262 mPlotItem->setYMinimum( yMinimum );
1263 mPlotItem->setYMaximum( yMaximum );
1266 mPlotItem->updateRect();
1267 mCrossHairsItem->updateRect();
1274 QgsPlotCanvas::paintEvent(
event );
1276 if ( !mFirstDrawOccurred )
1279 mFirstDrawOccurred =
true;
1280 mPlotItem->updateRect();
1281 mCrossHairsItem->updateRect();
1287 if ( !mPlotItem->plotArea().contains( point.
x(), point.
y() ) )
1290 if ( !mProfileCurve )
1293 const double dx = point.
x() - mPlotItem->plotArea().left();
1295 const double distanceAlongPlotPercent = dx / mPlotItem->plotArea().width();
1296 double distanceAlongCurveLength = distanceAlongPlotPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor + mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
1298 std::unique_ptr<QgsPoint> mapXyPoint( mProfileCurve->interpolatePoint( distanceAlongCurveLength ) );
1302 const double mapZ = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * ( mPlotItem->plotArea().bottom() - point.
y() ) + mPlotItem->yMinimum();
1304 return QgsPoint( mapXyPoint->x(), mapXyPoint->y(), mapZ );
1309 if ( !mProfileCurve )
1314 const double distanceAlongCurve =
geos.lineLocatePoint( point, &error );
1316 const double distanceAlongCurveOnPlot = distanceAlongCurve - mPlotItem->xMinimum() * mPlotItem->mXScaleFactor;
1317 const double distanceAlongCurvePercent = distanceAlongCurveOnPlot / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) * mPlotItem->mXScaleFactor );
1318 const double distanceAlongPlotRect = distanceAlongCurvePercent * mPlotItem->plotArea().width();
1320 const double canvasX = mPlotItem->plotArea().left() + distanceAlongPlotRect;
1323 if ( std::isnan( point.
z() ) || point.
z() < mPlotItem->yMinimum() )
1325 canvasY = mPlotItem->plotArea().top();
1327 else if ( point.
z() > mPlotItem->yMaximum() )
1329 canvasY = mPlotItem->plotArea().bottom();
1333 const double yPercent = ( point.
z() - mPlotItem->yMinimum() ) / ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
1334 canvasY = mPlotItem->plotArea().bottom() - mPlotItem->plotArea().height() * yPercent;
1347 double yMinimum = 0;
1348 double yMaximum = 0;
1359 yMinimum = zRange.
lower() - 5;
1360 yMaximum = zRange.
lower() + 5;
1365 const double margin = ( zRange.
upper() - zRange.
lower() ) * 0.05;
1366 yMinimum = zRange.
lower() - margin;
1367 yMaximum = zRange.
upper() + margin;
1371 double xMinimum = 0;
1373 double xMaximum = profileLength * 1.02;
1375 if ( mLockAxisScales )
1377 adjustRangeForAxisScaleLock( xMinimum, xMaximum, yMinimum, yMaximum );
1380 mPlotItem->setXMinimum( xMinimum / mPlotItem->mXScaleFactor );
1381 mPlotItem->setXMaximum( xMaximum / mPlotItem->mXScaleFactor );
1382 mPlotItem->setYMinimum( yMinimum );
1383 mPlotItem->setYMaximum( yMaximum );
1386 mPlotItem->updatePlot();
1393 if ( mLockAxisScales )
1395 adjustRangeForAxisScaleLock( minimumDistance, maximumDistance, minimumElevation, maximumElevation );
1398 mPlotItem->setYMinimum( minimumElevation );
1399 mPlotItem->setYMaximum( maximumElevation );
1400 mPlotItem->setXMinimum( minimumDistance / mPlotItem->mXScaleFactor );
1401 mPlotItem->setXMaximum( maximumDistance / mPlotItem->mXScaleFactor );
1403 mPlotItem->updatePlot();
1410 return QgsDoubleRange( mPlotItem->xMinimum() * mPlotItem->mXScaleFactor, mPlotItem->xMaximum() * mPlotItem->mXScaleFactor );
1415 return QgsDoubleRange( mPlotItem->yMinimum(), mPlotItem->yMaximum() );
1428 : mRenderer( renderer )
1432 void renderContent( QgsRenderContext &rc, QgsPlotRenderContext &,
const QRectF &plotArea,
const QgsPlotData & )
override
1437 rc.
painter()->translate( plotArea.left(), plotArea.top() );
1438 mRenderer->render( rc, plotArea.width(), plotArea.height(), xMinimum() * mXScale,
xMaximum() * mXScale,
yMinimum(),
yMaximum() );
1439 rc.
painter()->translate( -plotArea.left(), -plotArea.top() );
1445 QgsProfilePlotRenderer *mRenderer =
nullptr;
1457 QgsElevationProfilePlot profilePlot( mCurrentJob );
1461 QDomElement elem = doc.createElement( QStringLiteral(
"plot" ) );
1463 plotSettings.
writeXml( elem, doc, rwContext );
1464 profilePlot.readXml( elem, rwContext );
1466 profilePlot.mXScale = mPlotItem->mXScaleFactor;
1467 profilePlot.xAxis().setLabelSuffix( mPlotItem->xAxis().labelSuffix() );
1468 profilePlot.xAxis().setLabelSuffixPlacement( mPlotItem->xAxis().labelSuffixPlacement() );
1470 profilePlot.setSize( QSizeF( width, height ) );
1472 profilePlot.render( context, plotContext );
1482 return mCurrentJob->identify( plotPoint, identifyContext() );
1493 double distance1 = topLeftPlotPoint.
distance();
1494 double distance2 = bottomRightPlotPoint.
distance();
1495 if ( distance2 < distance1 )
1496 std::swap( distance1, distance2 );
1498 double elevation1 = topLeftPlotPoint.
elevation();
1499 double elevation2 = bottomRightPlotPoint.
elevation();
1500 if ( elevation2 < elevation1 )
1501 std::swap( elevation1, elevation2 );
1510 mPlotItem->updatePlot();
1515 mSnappingEnabled = enabled;
1520 mSubsectionsSymbol.reset( symbol );
1521 std::unique_ptr<QgsLineSymbol> plotItemSymbol( mSubsectionsSymbol ? mSubsectionsSymbol->clone() :
nullptr );
1522 mPlotItem->setSubsectionsSymbol( plotItemSymbol.release() );
1525void 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).