39 #include <QWheelEvent>
41 #include <QDesktopWidget>
62 mRect = mCanvas->rect();
65 prepareGeometryChange();
66 setPos( mRect.topLeft() );
69 mCachedImages.clear();
77 mCachedImages.clear();
82 bool redrawResults(
const QString &sourceId )
84 auto it = mCachedImages.find( sourceId );
85 if ( it == mCachedImages.end() )
88 mCachedImages.erase( it );
93 QRectF boundingRect()
const override
100 if ( !mPlotArea.isNull() )
105 if ( !scene()->views().isEmpty() )
106 context.
setScaleFactor( scene()->views().at( 0 )->logicalDpiX() / 25.4 );
115 const QRectF area = plotArea();
116 if ( !area.contains( point.x(), point.y() ) )
129 const QRectF area = plotArea();
138 mPlotArea = plotArea;
143 const QStringList sourceIds = mRenderer->sourceIds();
144 for (
const QString &source : sourceIds )
147 auto it = mCachedImages.constFind( source );
148 if ( it != mCachedImages.constEnd() )
154 plot = mRenderer->renderToImage( plotArea.width(), plotArea.height(), xMinimum(),
xMaximum(),
yMinimum(),
yMaximum(), source );
155 mCachedImages.insert( source, plot );
157 rc.
painter()->drawImage( plotArea.left(), plotArea.top(), plot );
161 void paint( QPainter *painter )
override
164 if ( !mImage.isNull() )
166 painter->drawImage( 0, 0, mImage );
170 mImage = QImage( mRect.width(), mRect.height(), QImage::Format_ARGB32_Premultiplied );
171 mImage.fill( Qt::transparent );
173 QPainter imagePainter( &mImage );
174 imagePainter.setRenderHint( QPainter::Antialiasing,
true );
184 painter->drawImage( 0, 0, mImage );
194 QMap< QString, QImage > mCachedImages;
207 , mPlotItem( plotItem )
213 mRect = mCanvas->rect();
215 prepareGeometryChange();
216 setPos( mRect.topLeft() );
226 QRectF boundingRect()
const override
231 void paint( QPainter *painter )
override
233 const QgsPointXY crossHairPlotPoint = mPlotItem->plotPointToCanvasPoint( mPoint );
234 if ( crossHairPlotPoint.
isEmpty() )
238 painter->setBrush( Qt::NoBrush );
240 crossHairPen.setCosmetic(
true );
241 crossHairPen.setWidthF( 1 );
242 crossHairPen.setStyle( Qt::DashLine );
243 crossHairPen.setCapStyle( Qt::FlatCap );
244 crossHairPen.setColor( QColor( 0, 0, 0, 150 ) );
245 painter->setPen( crossHairPen );
246 painter->drawLine( QPointF( mPlotItem->plotArea().left(), crossHairPlotPoint.
y() ), QPointF( mPlotItem->plotArea().right(), crossHairPlotPoint.
y() ) );
247 painter->drawLine( QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().top() ), QPointF( crossHairPlotPoint.
x(), mPlotItem->plotArea().bottom() ) );
252 const QString xCoordinateText = mPlotItem->xAxis().numericFormat()->formatDouble( mPoint.distance(), numericContext );
253 const QString yCoordinateText = mPlotItem->yAxis().numericFormat()->formatDouble( mPoint.elevation(), numericContext );
256 const QFontMetrics fm( font );
257 const double height = fm.capHeight();
258 const double xWidth = fm.horizontalAdvance( xCoordinateText );
259 const double yWidth = fm.horizontalAdvance( yCoordinateText );
260 const double textAxisMargin = fm.horizontalAdvance(
' ' );
262 QPointF xCoordOrigin;
263 QPointF yCoordOrigin;
265 if ( mPoint.distance() < ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5 )
267 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
270 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
272 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
277 xCoordOrigin = QPointF( crossHairPlotPoint.
x() + textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
279 yCoordOrigin = QPointF( mPlotItem->plotArea().right() - yWidth - textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
284 if ( mPoint.elevation() < ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5 )
287 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().top() + height + textAxisMargin );
289 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() - textAxisMargin );
294 xCoordOrigin = QPointF( crossHairPlotPoint.
x() - xWidth - textAxisMargin, mPlotItem->plotArea().bottom() - textAxisMargin );
296 yCoordOrigin = QPointF( mPlotItem->plotArea().left() + textAxisMargin, crossHairPlotPoint.
y() + height + textAxisMargin );
301 painter->setBrush( QBrush( QColor( 255, 255, 255, 220 ) ) );
302 painter->setPen( Qt::NoPen );
303 painter->drawRect( QRectF( xCoordOrigin.x() - textAxisMargin + 1, xCoordOrigin.y() - textAxisMargin - height + 1, xWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
304 painter->drawRect( QRectF( yCoordOrigin.x() - textAxisMargin + 1, yCoordOrigin.y() - textAxisMargin - height + 1, yWidth + 2 * textAxisMargin - 2, height + 2 * textAxisMargin - 2 ) );
306 painter->setBrush( Qt::NoBrush );
307 painter->setPen( Qt::black );
309 painter->drawText( xCoordOrigin, xCoordinateText );
310 painter->drawText( yCoordOrigin, yCoordinateText );
318 QgsElevationProfilePlotItem *mPlotItem =
nullptr;
326 mPlotItem =
new QgsElevationProfilePlotItem(
this );
327 mCrossHairsItem =
new QgsElevationProfileCrossHairsItem(
this, mPlotItem );
328 mCrossHairsItem->setZValue( 100 );
329 mCrossHairsItem->hide();
332 mDeferredRegenerationTimer =
new QTimer(
this );
333 mDeferredRegenerationTimer->setSingleShot(
true );
334 mDeferredRegenerationTimer->stop();
335 connect( mDeferredRegenerationTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRegeneration );
337 mDeferredRedrawTimer =
new QTimer(
this );
338 mDeferredRedrawTimer->setSingleShot(
true );
339 mDeferredRedrawTimer->stop();
340 connect( mDeferredRedrawTimer, &QTimer::timeout,
this, &QgsElevationProfileCanvas::startDeferredRedraw );
348 mPlotItem->setRenderer(
nullptr );
349 mCurrentJob->deleteLater();
350 mCurrentJob =
nullptr;
358 mPlotItem->setRenderer(
nullptr );
361 mCurrentJob->deleteLater();
362 mCurrentJob =
nullptr;
368 const double dxPercent = dx / mPlotItem->plotArea().width();
369 const double dyPercent = dy / mPlotItem->plotArea().height();
372 const double dxPlot = - dxPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
373 const double dyPlot = dyPercent * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
375 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
376 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
377 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
378 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
382 mPlotItem->updatePlot();
388 if ( !mPlotItem->plotArea().contains( x, y ) )
391 const double newCenterX = mPlotItem->xMinimum() + ( x - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
392 const double newCenterY = mPlotItem->yMinimum() + ( mPlotItem->plotArea().bottom() - y ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
394 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
395 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
397 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
398 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
399 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
400 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
404 mPlotItem->updatePlot();
416 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
417 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
418 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
426 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) / ( mPlotItem->plotArea().width() ) );
433 const double toleranceInPixels = QFontMetrics( font() ).horizontalAdvance(
' ' );
434 const double xToleranceInPlotUnits = ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) / ( mPlotItem->plotArea().width() ) * toleranceInPixels;
435 const double yToleranceInPlotUnits = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * toleranceInPixels;
443 / ( ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) / ( mPlotItem->plotArea().width() ) );
450 void QgsElevationProfileCanvas::setupLayerConnections(
QgsMapLayer *layer,
bool isDisconnect )
465 switch ( layer->
type() )
499 if ( !mCurrentJob || !mSnappingEnabled )
513 const double currentWidth = mPlotItem->xMaximum() - mPlotItem->xMinimum();
514 const double currentHeight = mPlotItem->yMaximum() - mPlotItem->yMinimum();
516 const double newWidth = currentWidth / xFactor;
517 const double newHeight = currentHeight / yFactor;
519 const double currentCenterX = ( mPlotItem->xMinimum() + mPlotItem->xMaximum() ) * 0.5;
520 const double currentCenterY = ( mPlotItem->yMinimum() + mPlotItem->yMaximum() ) * 0.5;
522 mPlotItem->setXMinimum( currentCenterX - newWidth * 0.5 );
523 mPlotItem->setXMaximum( currentCenterX + newWidth * 0.5 );
524 mPlotItem->setYMinimum( currentCenterY - newHeight * 0.5 );
525 mPlotItem->setYMaximum( currentCenterY + newHeight * 0.5 );
528 mPlotItem->updatePlot();
534 const QRectF intersected = rect.intersected( mPlotItem->plotArea() );
536 const double minX = ( intersected.left() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
537 const double maxX = ( intersected.right() - mPlotItem->plotArea().left() ) / mPlotItem->plotArea().width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
538 const double minY = ( mPlotItem->plotArea().bottom() - intersected.bottom() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
539 const double maxY = ( mPlotItem->plotArea().bottom() - intersected.top() ) / mPlotItem->plotArea().height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
541 mPlotItem->setXMinimum( minX );
542 mPlotItem->setXMaximum( maxX );
543 mPlotItem->setYMinimum( minY );
544 mPlotItem->setYMaximum( maxY );
547 mPlotItem->updatePlot();
555 double zoomFactor = settings.
value( QStringLiteral(
"qgis/zoom_factor" ), 2 ).toDouble();
558 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs(
event->angleDelta().y() );
560 if (
event->modifiers() & Qt::ControlModifier )
563 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
567 bool zoomIn =
event->angleDelta().y() > 0;
568 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
570 QRectF viewportRect = mPlotItem->plotArea();
571 if ( viewportRect.contains(
event->pos() ) )
574 const double oldCenterX = 0.5 * ( mPlotItem->xMaximum() + mPlotItem->xMinimum() );
575 const double oldCenterY = 0.5 * ( mPlotItem->yMaximum() + mPlotItem->yMinimum() );
577 const double eventPosX = (
event->pos().x() - viewportRect.left() ) / viewportRect.width() * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
578 const double eventPosY = ( viewportRect.bottom() -
event->pos().y() ) / viewportRect.height() * ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) + mPlotItem->yMinimum();
580 const double newCenterX = eventPosX + ( ( oldCenterX - eventPosX ) * scaleFactor );
581 const double newCenterY = eventPosY + ( ( oldCenterY - eventPosY ) * scaleFactor );
583 const double dxPlot = newCenterX - ( mPlotItem->xMaximum() + mPlotItem->xMinimum() ) * 0.5;
584 const double dyPlot = newCenterY - ( mPlotItem->yMaximum() + mPlotItem->yMinimum() ) * 0.5;
586 mPlotItem->setXMinimum( mPlotItem->xMinimum() + dxPlot );
587 mPlotItem->setXMaximum( mPlotItem->xMaximum() + dxPlot );
588 mPlotItem->setYMinimum( mPlotItem->yMinimum() + dyPlot );
589 mPlotItem->setYMaximum( mPlotItem->yMaximum() + dyPlot );
607 if ( e->isAccepted() )
609 mCrossHairsItem->hide();
614 if ( mCurrentJob && mSnappingEnabled && !plotPoint.
isEmpty() )
623 mCrossHairsItem->hide();
627 mCrossHairsItem->setPoint( plotPoint );
628 mCrossHairsItem->show();
635 return mPlotItem->plotArea();
645 mPlotItem->setRenderer(
nullptr );
647 mCurrentJob->deleteLater();
648 mCurrentJob =
nullptr;
661 const QList< QgsMapLayer * > layersToGenerate =
layers();
662 QList< QgsAbstractProfileSource * > sources;
663 sources.reserve( layersToGenerate .size() );
667 sources.append( source );
674 generationContext.
setDpi( QgsApplication::desktop()->logicalDpiX() );
675 generationContext.
setMaximumErrorMapUnits( MAX_ERROR_PIXELS * ( mProfileCurve->length() ) / mPlotItem->plotArea().width() );
680 mPlotItem->setRenderer( mCurrentJob );
687 mZoomFullWhenJobFinished =
true;
690 void QgsElevationProfileCanvas::generationFinished()
697 if ( mZoomFullWhenJobFinished )
700 mZoomFullWhenJobFinished =
false;
709 mPlotItem->updatePlot();
712 if ( mForceRegenerationAfterCurrentJobCompletes )
714 mForceRegenerationAfterCurrentJobCompletes =
false;
716 scheduleDeferredRegeneration();
720 void QgsElevationProfileCanvas::onLayerProfileGenerationPropertyChanged()
723 if ( !mCurrentJob || mCurrentJob->
isActive() )
730 if (
QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( properties->parent() ) )
735 scheduleDeferredRegeneration();
740 void QgsElevationProfileCanvas::onLayerProfileRendererPropertyChanged()
743 if ( !mCurrentJob || mCurrentJob->
isActive() )
750 if (
QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( properties->parent() ) )
756 if ( mPlotItem->redrawResults( layer->
id() ) )
757 scheduleDeferredRedraw();
761 void QgsElevationProfileCanvas::regenerateResultsForLayer()
763 if (
QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( sender() ) )
768 scheduleDeferredRegeneration();
773 void QgsElevationProfileCanvas::scheduleDeferredRegeneration()
775 if ( !mDeferredRegenerationScheduled )
777 mDeferredRegenerationTimer->start( 1 );
778 mDeferredRegenerationScheduled =
true;
782 void QgsElevationProfileCanvas::scheduleDeferredRedraw()
784 if ( !mDeferredRedrawScheduled )
786 mDeferredRedrawTimer->start( 1 );
787 mDeferredRedrawScheduled =
true;
791 void QgsElevationProfileCanvas::startDeferredRegeneration()
793 if ( mCurrentJob && !mCurrentJob->
isActive() )
798 else if ( mCurrentJob )
800 mForceRegenerationAfterCurrentJobCompletes =
true;
803 mDeferredRegenerationScheduled =
false;
806 void QgsElevationProfileCanvas::startDeferredRedraw()
809 mDeferredRedrawScheduled =
false;
812 void QgsElevationProfileCanvas::refineResults()
817 context.
setDpi( QgsApplication::desktop()->logicalDpiX() );
818 const double plotDistanceRange = mPlotItem->xMaximum() - mPlotItem->xMinimum();
819 const double plotElevationRange = mPlotItem->yMaximum() - mPlotItem->yMinimum();
820 const double plotDistanceUnitsPerPixel = plotDistanceRange / mPlotItem->plotArea().width();
824 const double targetMaxErrorInMapUnits = MAX_ERROR_PIXELS * plotDistanceUnitsPerPixel;
825 const double factor = std::pow( 10.0, 1 - std::ceil( std::log10( std::fabs( targetMaxErrorInMapUnits ) ) ) );
826 const double roundedErrorInMapUnits = std::floor( targetMaxErrorInMapUnits * factor ) / factor;
834 mPlotItem->xMaximum() + plotDistanceRange * 0.05 ) );
837 mPlotItem->yMaximum() + plotElevationRange * 0.05 ) );
840 scheduleDeferredRegeneration();
845 if ( !mPlotItem->plotArea().contains( point.x(), point.y() ) )
848 return mPlotItem->canvasPointToPlotPoint( point );
853 return mPlotItem->plotPointToCanvasPoint( point );
859 mPlotItem->mProject = project;
869 mProfileCurve.reset( curve );
874 return mProfileCurve.get();
889 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
891 setupLayerConnections( layer,
true );
895 auto filteredList =
layers;
896 filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(),
899 return !layer || !layer->isValid();
900 } ), filteredList.end() );
902 mLayers = _qgis_listRawToQPointer( filteredList );
903 for (
QgsMapLayer *layer : std::as_const( mLayers ) )
905 setupLayerConnections( layer,
false );
911 return _qgis_listQPointerToRaw( mLayers );
917 mPlotItem->updateRect();
918 mCrossHairsItem->updateRect();
923 QgsPlotCanvas::paintEvent(
event );
925 if ( !mFirstDrawOccurred )
928 mFirstDrawOccurred =
true;
929 mPlotItem->updateRect();
930 mCrossHairsItem->updateRect();
936 if ( !mPlotItem->plotArea().contains( point.
x(), point.
y() ) )
939 if ( !mProfileCurve )
942 const double dx = point.
x() - mPlotItem->plotArea().left();
944 const double distanceAlongPlotPercent = dx / mPlotItem->plotArea().width();
945 double distanceAlongCurveLength = distanceAlongPlotPercent * ( mPlotItem->xMaximum() - mPlotItem->xMinimum() ) + mPlotItem->xMinimum();
947 std::unique_ptr< QgsPoint > mapXyPoint( mProfileCurve->interpolatePoint( distanceAlongCurveLength ) );
951 const double mapZ = ( mPlotItem->yMaximum() - mPlotItem->yMinimum() ) / ( mPlotItem->plotArea().height() ) * ( mPlotItem->plotArea().bottom() - point.
y() ) + mPlotItem->yMinimum();
953 return QgsPoint( mapXyPoint->x(), mapXyPoint->y(), mapZ );
958 if ( !mProfileCurve )
963 const double distanceAlongCurve =
geos.lineLocatePoint( point, &error );
965 const double distanceAlongCurveOnPlot = distanceAlongCurve - mPlotItem->xMinimum();
966 const double distanceAlongCurvePercent = distanceAlongCurveOnPlot / ( mPlotItem->xMaximum() - mPlotItem->xMinimum() );
967 const double distanceAlongPlotRect = distanceAlongCurvePercent * mPlotItem->plotArea().width();
969 const double canvasX = mPlotItem->plotArea().left() + distanceAlongPlotRect;
972 if ( std::isnan( point.
z() ) || point.
z() < mPlotItem->yMinimum() )
974 canvasY = mPlotItem->plotArea().top();
976 else if ( point.
z() > mPlotItem->yMaximum() )
978 canvasY = mPlotItem->plotArea().bottom();
982 const double yPercent = ( point.
z() - mPlotItem->yMinimum() ) / ( mPlotItem->yMaximum() - mPlotItem->yMinimum() );
983 canvasY = mPlotItem->plotArea().bottom() - mPlotItem->plotArea().height() * yPercent;
999 mPlotItem->setYMinimum( 0 );
1000 mPlotItem->setYMaximum( 10 );
1005 mPlotItem->setYMinimum( zRange.
lower() - 5 );
1006 mPlotItem->setYMaximum( zRange.
lower() + 5 );
1011 const double margin = ( zRange.
upper() - zRange.
lower() ) * 0.05;
1012 mPlotItem->setYMinimum( zRange.
lower() - margin );
1013 mPlotItem->setYMaximum( zRange.
upper() + margin );
1017 mPlotItem->setXMinimum( 0 );
1019 mPlotItem->setXMaximum( profileLength * 1.02 );
1022 mPlotItem->updatePlot();
1028 mPlotItem->setYMinimum( minimumElevation );
1029 mPlotItem->setYMaximum( maximumElevation );
1030 mPlotItem->setXMinimum( minimumDistance );
1031 mPlotItem->setXMaximum( maximumDistance );
1033 mPlotItem->updatePlot();
1039 return QgsDoubleRange( mPlotItem->xMinimum(), mPlotItem->xMaximum() );
1044 return QgsDoubleRange( mPlotItem->yMinimum(), mPlotItem->yMaximum() );
1053 class QgsElevationProfilePlot :
public Qgs2DPlot
1058 : mRenderer( renderer )
1067 rc.
painter()->translate( plotArea.left(), plotArea.top() );
1069 rc.
painter()->translate( -plotArea.left(), -plotArea.top() );
1086 QgsElevationProfilePlot profilePlot( mCurrentJob );
1090 QDomElement elem = doc.createElement( QStringLiteral(
"plot" ) );
1092 plotSettings.
writeXml( elem, doc, rwContext );
1093 profilePlot.readXml( elem, rwContext );
1095 profilePlot.setSize( QSizeF( width, height ) );
1096 profilePlot.render( context );
1106 return mCurrentJob->
identify( plotPoint, identifyContext() );
1117 double distance1 = topLeftPlotPoint.
distance();
1118 double distance2 = bottomRightPlotPoint.
distance();
1119 if ( distance2 < distance1 )
1120 std::swap( distance1, distance2 );
1122 double elevation1 = topLeftPlotPoint.
elevation();
1123 double elevation2 = bottomRightPlotPoint.
elevation();
1124 if ( elevation2 < elevation1 )
1125 std::swap( elevation1, elevation2 );
1133 mPlotItem->setRenderer(
nullptr );
1134 mPlotItem->updatePlot();
1139 mSnappingEnabled = enabled;