#5079 Curve Error Bars : Move to RimPlotCurve

This commit is contained in:
Magne Sjaastad 2019-11-22 14:22:00 +01:00
parent d079f233a4
commit 36772e77b1
8 changed files with 225 additions and 241 deletions

View File

@ -36,6 +36,12 @@ class RiaCurveDataTools
public: public:
typedef std::vector<std::pair<size_t, size_t>> CurveIntervals; typedef std::vector<std::pair<size_t, size_t>> CurveIntervals;
enum ErrorAxis
{
ERROR_ALONG_X_AXIS,
ERROR_ALONG_Y_AXIS
};
public: public:
static CurveIntervals calculateIntervalsOfValidValues( const std::vector<double>& values, static CurveIntervals calculateIntervalsOfValidValues( const std::vector<double>& values,
bool includePositiveValuesOnly ); bool includePositiveValuesOnly );

View File

@ -18,7 +18,9 @@
#include "RimPlotCurve.h" #include "RimPlotCurve.h"
#include "RiaCurveDataTools.h"
#include "RiaGuiApplication.h" #include "RiaGuiApplication.h"
#include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h" #include "RimEnsembleCurveSetCollection.h"
#include "RimNameConfig.h" #include "RimNameConfig.h"
@ -35,12 +37,16 @@
#include "cvfAssert.h" #include "cvfAssert.h"
#include "qwt_date.h"
#include "qwt_interval_symbol.h"
#include "qwt_plot.h" #include "qwt_plot.h"
#include "qwt_symbol.h" #include "qwt_symbol.h"
// NB! Special macro for pure virtual class // NB! Special macro for pure virtual class
CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPlotCurve, "PlotCurve" ); CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPlotCurve, "PlotCurve" );
#define DOUBLE_INF std::numeric_limits<double>::infinity()
namespace caf namespace caf
{ {
template <> template <>
@ -147,7 +153,12 @@ RimPlotCurve::RimPlotCurve()
CAF_PDM_InitFieldNoDefault( &m_symbolLabelPosition, "SymbolLabelPosition", "Symbol Label Position", "", "", "" ); CAF_PDM_InitFieldNoDefault( &m_symbolLabelPosition, "SymbolLabelPosition", "Symbol Label Position", "", "", "" );
m_qwtPlotCurve = new RiuRimQwtPlotCurve( this ); m_qwtPlotCurve = new RiuRimQwtPlotCurve( this );
m_qwtCurveErrorBars = new QwtPlotIntervalCurve();
m_qwtCurveErrorBars->setStyle( QwtPlotIntervalCurve::CurveStyle::NoCurve );
m_qwtCurveErrorBars->setSymbol( new QwtIntervalSymbol( QwtIntervalSymbol::Bar ) );
m_qwtCurveErrorBars->setItemAttribute( QwtPlotItem::Legend, false );
m_qwtCurveErrorBars->setZ( RiuQwtPlotCurve::Z_ERROR_BARS );
m_parentQwtPlot = nullptr; m_parentQwtPlot = nullptr;
} }
@ -164,6 +175,13 @@ RimPlotCurve::~RimPlotCurve()
m_qwtPlotCurve = nullptr; m_qwtPlotCurve = nullptr;
} }
if ( m_qwtCurveErrorBars )
{
m_qwtCurveErrorBars->detach();
delete m_qwtCurveErrorBars;
m_qwtCurveErrorBars = nullptr;
}
if ( m_parentQwtPlot ) if ( m_parentQwtPlot )
{ {
m_parentQwtPlot->replot(); m_parentQwtPlot->replot();
@ -220,7 +238,6 @@ void RimPlotCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
} }
else if ( changedField == &m_showErrorBars ) else if ( changedField == &m_showErrorBars )
{ {
m_qwtPlotCurve->showErrorBars( m_showErrorBars );
updateCurveAppearance(); updateCurveAppearance();
} }
RiuPlotMainWindowTools::refreshToolbars(); RiuPlotMainWindowTools::refreshToolbars();
@ -271,11 +288,12 @@ void RimPlotCurve::updateCurveVisibility( bool updateParentPlot )
{ {
if ( canCurveBeAttached() ) if ( canCurveBeAttached() )
{ {
m_qwtPlotCurve->attach( m_parentQwtPlot ); attachCurveAndErrorBars();
} }
else else
{ {
m_qwtPlotCurve->detach(); m_qwtPlotCurve->detach();
m_qwtCurveErrorBars->detach();
} }
if ( updateParentPlot ) if ( updateParentPlot )
@ -323,7 +341,8 @@ void RimPlotCurve::setParentQwtPlotAndReplot( QwtPlot* plot )
m_parentQwtPlot = plot; m_parentQwtPlot = plot;
if ( canCurveBeAttached() ) if ( canCurveBeAttached() )
{ {
m_qwtPlotCurve->attach( m_parentQwtPlot ); attachCurveAndErrorBars();
m_parentQwtPlot->replot(); m_parentQwtPlot->replot();
} }
} }
@ -336,11 +355,12 @@ void RimPlotCurve::setParentQwtPlotNoReplot( QwtPlot* plot )
m_parentQwtPlot = plot; m_parentQwtPlot = plot;
if ( canCurveBeAttached() ) if ( canCurveBeAttached() )
{ {
m_qwtPlotCurve->attach( m_parentQwtPlot ); attachCurveAndErrorBars();
} }
else else
{ {
m_qwtPlotCurve->detach(); m_qwtPlotCurve->detach();
m_qwtCurveErrorBars->detach();
} }
} }
@ -366,6 +386,7 @@ void RimPlotCurve::setColor( const cvf::Color3f& color )
void RimPlotCurve::detachQwtCurve() void RimPlotCurve::detachQwtCurve()
{ {
m_qwtPlotCurve->detach(); m_qwtPlotCurve->detach();
m_qwtCurveErrorBars->detach();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -376,7 +397,7 @@ void RimPlotCurve::reattachQwtCurve()
detachQwtCurve(); detachQwtCurve();
if ( canCurveBeAttached() ) if ( canCurveBeAttached() )
{ {
m_qwtPlotCurve->attach( m_parentQwtPlot ); attachCurveAndErrorBars();
} }
} }
@ -486,6 +507,75 @@ void RimPlotCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& u
throw std::logic_error( "The method or operation is not implemented." ); throw std::logic_error( "The method or operation is not implemented." );
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::setSamplesFromXYErrorValues(
const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& errorValues,
bool keepOnlyPositiveValues,
RiaCurveDataTools::ErrorAxis errorAxis /*= RiuQwtPlotCurve::ERROR_ALONG_Y_AXIS */ )
{
CVF_ASSERT( xValues.size() == yValues.size() );
CVF_ASSERT( xValues.size() == errorValues.size() );
auto intervalsOfValidValues = RiaCurveDataTools::calculateIntervalsOfValidValues( yValues, keepOnlyPositiveValues );
std::vector<double> filteredYValues;
std::vector<double> filteredXValues;
RiaCurveDataTools::getValuesByIntervals( yValues, intervalsOfValidValues, &filteredYValues );
RiaCurveDataTools::getValuesByIntervals( xValues, intervalsOfValidValues, &filteredXValues );
std::vector<double> filteredErrorValues;
RiaCurveDataTools::getValuesByIntervals( errorValues, intervalsOfValidValues, &filteredErrorValues );
QVector<QwtIntervalSample> errorIntervals;
errorIntervals.reserve( static_cast<int>( filteredXValues.size() ) );
for ( size_t i = 0; i < filteredXValues.size(); i++ )
{
if ( filteredYValues[i] != DOUBLE_INF && filteredErrorValues[i] != DOUBLE_INF )
{
if ( errorAxis == RiaCurveDataTools::ERROR_ALONG_Y_AXIS )
{
errorIntervals << QwtIntervalSample( filteredXValues[i],
filteredYValues[i] - filteredErrorValues[i],
filteredYValues[i] + filteredErrorValues[i] );
}
else
{
errorIntervals << QwtIntervalSample( filteredYValues[i],
filteredXValues[i] - filteredErrorValues[i],
filteredXValues[i] + filteredErrorValues[i] );
}
}
}
if ( m_qwtPlotCurve )
{
m_qwtPlotCurve->setSamples( filteredXValues.data(),
filteredYValues.data(),
static_cast<int>( filteredXValues.size() ) );
m_qwtPlotCurve->setLineSegmentStartStopIndices( intervalsOfValidValues );
}
if ( m_qwtCurveErrorBars )
{
m_qwtCurveErrorBars->setSamples( errorIntervals );
if ( errorAxis == RiaCurveDataTools::ERROR_ALONG_Y_AXIS )
{
m_qwtCurveErrorBars->setOrientation( Qt::Vertical );
}
else
{
m_qwtCurveErrorBars->setOrientation( Qt::Horizontal );
}
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -557,6 +647,19 @@ bool RimPlotCurve::canCurveBeAttached() const
return isVisibleInPossibleParent; return isVisibleInPossibleParent;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::attachCurveAndErrorBars()
{
m_qwtPlotCurve->attach( m_parentQwtPlot );
if ( m_showErrorBars )
{
m_qwtCurveErrorBars->attach( m_parentQwtPlot );
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -585,7 +688,11 @@ void RimPlotCurve::updateCurveAppearance()
m_qwtPlotCurve->setSymbol( symbol ); m_qwtPlotCurve->setSymbol( symbol );
m_qwtPlotCurve->setSymbolSkipPixelDistance( m_symbolSkipPixelDistance() ); m_qwtPlotCurve->setSymbolSkipPixelDistance( m_symbolSkipPixelDistance() );
m_qwtPlotCurve->setErrorBarsColor( curveColor ); {
QwtIntervalSymbol* newSymbol = new QwtIntervalSymbol( QwtIntervalSymbol::Bar );
newSymbol->setPen( QPen( curveColor ) );
m_qwtCurveErrorBars->setSymbol( newSymbol );
}
// Make sure the legend lines are long enough to distinguish between line types. // Make sure the legend lines are long enough to distinguish between line types.
// Standard width in Qwt is 8 which is too short. // Standard width in Qwt is 8 which is too short.

View File

@ -18,6 +18,9 @@
#pragma once #pragma once
#include "RifEclipseSummaryAddress.h" #include "RifEclipseSummaryAddress.h"
#include "RiaCurveDataTools.h"
#include "RiuQwtPlotCurve.h" #include "RiuQwtPlotCurve.h"
#include "RiuQwtSymbol.h" #include "RiuQwtSymbol.h"
@ -29,6 +32,7 @@
class QwtPlot; class QwtPlot;
class QwtPlotCurve; class QwtPlotCurve;
class QwtPlotIntervalCurve;
//================================================================================================== //==================================================================================================
/// ///
@ -120,6 +124,12 @@ protected:
virtual void updateLegendsInPlot(); virtual void updateLegendsInPlot();
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void setSamplesFromXYErrorValues( const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& errorValues,
bool keepOnlyPositiveValues,
RiaCurveDataTools::ErrorAxis errorAxis = RiaCurveDataTools::ERROR_ALONG_Y_AXIS );
protected: protected:
// Overridden PDM methods // Overridden PDM methods
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
@ -134,10 +144,13 @@ protected:
private: private:
bool canCurveBeAttached() const; bool canCurveBeAttached() const;
void attachCurveAndErrorBars();
protected: protected:
QPointer<QwtPlot> m_parentQwtPlot; QPointer<QwtPlot> m_parentQwtPlot;
RiuQwtPlotCurve* m_qwtPlotCurve;
RiuQwtPlotCurve* m_qwtPlotCurve;
QwtPlotIntervalCurve* m_qwtCurveErrorBars;
caf::PdmField<bool> m_showCurve; caf::PdmField<bool> m_showCurve;
caf::PdmField<QString> m_curveName; caf::PdmField<QString> m_curveName;

View File

@ -47,7 +47,7 @@ RimWellLogCurve::RimWellLogCurve()
CAF_PDM_InitObject( "WellLogCurve", ":/WellLogCurve16x16.png", "", "" ); CAF_PDM_InitObject( "WellLogCurve", ":/WellLogCurve16x16.png", "", "" );
m_qwtPlotCurve->setXAxis( QwtPlot::xTop ); m_qwtPlotCurve->setXAxis( QwtPlot::xTop );
m_qwtPlotCurve->setErrorBarsXAxis( QwtPlot::xTop ); m_qwtCurveErrorBars->setXAxis( QwtPlot::xTop );
m_qwtPlotCurve->setYAxis( QwtPlot::yLeft ); m_qwtPlotCurve->setYAxis( QwtPlot::yLeft );
m_curveData = new RigWellLogCurveData; m_curveData = new RigWellLogCurveData;

View File

@ -378,6 +378,7 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
RimWellRftPlot* rftPlot = dynamic_cast<RimWellRftPlot*>( wellLogPlot ); RimWellRftPlot* rftPlot = dynamic_cast<RimWellRftPlot*>( wellLogPlot );
bool showErrorBarsInObservedData = rftPlot ? rftPlot->showErrorBarsForObservedData() : false; bool showErrorBarsInObservedData = rftPlot ? rftPlot->showErrorBarsForObservedData() : false;
m_showErrorBars = showErrorBarsInObservedData;
std::vector<double> measuredDepthVector = measuredDepthValues(); std::vector<double> measuredDepthVector = measuredDepthValues();
std::vector<double> tvDepthVector = tvDepthValues(); std::vector<double> tvDepthVector = tvDepthValues();
@ -447,14 +448,24 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
if ( wellLogPlot->depthType() == RiaDefines::MEASURED_DEPTH ) if ( wellLogPlot->depthType() == RiaDefines::MEASURED_DEPTH )
{ {
m_qwtPlotCurve->showErrorBars( showErrorBarsInObservedData );
m_qwtPlotCurve->setPerPointLabels( perPointLabels ); m_qwtPlotCurve->setPerPointLabels( perPointLabels );
m_qwtPlotCurve->setSamplesFromXValuesAndYValues( this->curveData()->xPlotValues(),
this->curveData()->depthPlotValues( RiaDefines::MEASURED_DEPTH, auto xValues = this->curveData()->xPlotValues();
displayUnit ), auto yValues = this->curveData()->depthPlotValues( RiaDefines::MEASURED_DEPTH, displayUnit );
errors, bool keepOnlyPositiveValues = false;
false,
RiuQwtPlotCurve::ERROR_ALONG_X_AXIS ); if ( !errors.empty() )
{
this->setSamplesFromXYErrorValues( xValues,
yValues,
errors,
keepOnlyPositiveValues,
RiaCurveDataTools::ERROR_ALONG_X_AXIS );
}
else
{
m_qwtPlotCurve->setSamplesFromXValuesAndYValues( xValues, yValues, keepOnlyPositiveValues );
}
RimWellLogTrack* wellLogTrack; RimWellLogTrack* wellLogTrack;
firstAncestorOrThisOfType( wellLogTrack ); firstAncestorOrThisOfType( wellLogTrack );
@ -483,14 +494,24 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
} }
else else
{ {
m_qwtPlotCurve->showErrorBars( showErrorBarsInObservedData );
m_qwtPlotCurve->setPerPointLabels( perPointLabels ); m_qwtPlotCurve->setPerPointLabels( perPointLabels );
m_qwtPlotCurve->setSamplesFromXValuesAndYValues( this->curveData()->xPlotValues(),
this->curveData()->depthPlotValues( RiaDefines::TRUE_VERTICAL_DEPTH, auto xValues = this->curveData()->xPlotValues();
displayUnit ), auto yValues = this->curveData()->depthPlotValues( RiaDefines::TRUE_VERTICAL_DEPTH, displayUnit );
errors, bool isLogCurve = false;
false,
RiuQwtPlotCurve::ERROR_ALONG_X_AXIS ); if ( !errors.empty() )
{
this->setSamplesFromXYErrorValues( xValues,
yValues,
errors,
isLogCurve,
RiaCurveDataTools::ERROR_ALONG_X_AXIS );
}
else
{
m_qwtPlotCurve->setSamplesFromXValuesAndYValues( xValues, yValues, isLogCurve );
}
} }
m_qwtPlotCurve->setLineSegmentStartStopIndices( this->curveData()->polylineStartStopIndices() ); m_qwtPlotCurve->setLineSegmentStartStopIndices( this->curveData()->polylineStartStopIndices() );

View File

@ -151,7 +151,7 @@ void RimSummaryCurve::setSummaryCaseY( RimSummaryCase* sumCase )
{ {
if ( m_yValuesSummaryCase != sumCase ) if ( m_yValuesSummaryCase != sumCase )
{ {
m_qwtPlotCurve->clearErrorBars(); m_qwtCurveErrorBars->setSamples( nullptr );
} }
m_yValuesSummaryCase = sumCase; m_yValuesSummaryCase = sumCase;
@ -208,7 +208,7 @@ void RimSummaryCurve::setSummaryAddressY( const RifEclipseSummaryAddress& addres
{ {
if ( m_yValuesSummaryAddress->address() != address ) if ( m_yValuesSummaryAddress->address() != address )
{ {
m_qwtPlotCurve->clearErrorBars(); m_qwtCurveErrorBars->setSamples( nullptr );
} }
m_yValuesSummaryAddress->setAddress( address ); m_yValuesSummaryAddress->setAddress( address );
@ -520,10 +520,17 @@ void RimSummaryCurve::onLoadDataAndUpdate( bool updateParentPlot )
{ {
std::vector<double> errValues; std::vector<double> errValues;
reader->values( errAddress, &errValues ); reader->values( errAddress, &errValues );
m_qwtPlotCurve->setSamplesFromTimeTAndYValues( curveTimeStepsY,
curveValuesY, auto timeSteps = RiuQwtPlotCurve::fromTime_t( curveTimeStepsY );
errValues,
isLogCurve ); if ( !errValues.empty() )
{
this->setSamplesFromXYErrorValues( timeSteps, curveValuesY, errValues, isLogCurve );
}
else
{
m_qwtPlotCurve->setSamplesFromXValuesAndYValues( timeSteps, curveValuesY, isLogCurve );
}
} }
else else
{ {
@ -564,8 +571,6 @@ void RimSummaryCurve::onLoadDataAndUpdate( bool updateParentPlot )
updateZoomInParentPlot(); updateZoomInParentPlot();
m_parentQwtPlot->replot(); m_parentQwtPlot->replot();
} }
m_qwtPlotCurve->showErrorBars( m_showErrorBars );
} }
if ( updateParentPlot ) updateQwtPlotAxis(); if ( updateParentPlot ) updateQwtPlotAxis();

View File

@ -21,12 +21,12 @@
#include "RiaCurveDataTools.h" #include "RiaCurveDataTools.h"
#include "RiaImageTools.h" #include "RiaImageTools.h"
#include "RiuQwtSymbol.h" #include "RiuQwtSymbol.h"
#include "qwt_date.h" #include "qwt_date.h"
#include "qwt_interval_symbol.h" #include "qwt_interval_symbol.h"
#include "qwt_painter.h" #include "qwt_painter.h"
#include "qwt_plot_intervalcurve.h"
#include "qwt_point_mapper.h" #include "qwt_point_mapper.h"
#include "qwt_scale_map.h" #include "qwt_scale_map.h"
#include "qwt_symbol.h" #include "qwt_symbol.h"
@ -52,14 +52,6 @@ RiuQwtPlotCurve::RiuQwtPlotCurve( const QString& title )
m_symbolSkipPixelDistance = 10.0f; m_symbolSkipPixelDistance = 10.0f;
m_errorBars = new QwtPlotIntervalCurve();
m_errorBars->setStyle( QwtPlotIntervalCurve::CurveStyle::NoCurve );
m_errorBars->setSymbol( new QwtIntervalSymbol( QwtIntervalSymbol::Bar ) );
m_errorBars->setItemAttribute( QwtPlotItem::Legend, false );
m_errorBars->setZ( Z_ERROR_BARS );
m_showErrorBars = true;
m_attachedToPlot = nullptr;
m_blackAndWhiteLegendIcon = false; m_blackAndWhiteLegendIcon = false;
} }
@ -68,81 +60,6 @@ RiuQwtPlotCurve::RiuQwtPlotCurve( const QString& title )
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RiuQwtPlotCurve::~RiuQwtPlotCurve() {} RiuQwtPlotCurve::~RiuQwtPlotCurve() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setSamplesFromXValuesAndYValues( const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& errorValues,
bool keepOnlyPositiveValues,
ErrorAxis errorAxis )
{
CVF_ASSERT( xValues.size() == yValues.size() );
CVF_ASSERT( errorValues.empty() || errorValues.size() == xValues.size() );
bool showErrorBars = m_showErrorBars && !errorValues.empty();
QPolygonF points;
QVector<QwtIntervalSample> errorIntervals;
std::vector<std::pair<size_t, size_t>> filteredIntervals;
{
std::vector<double> filteredYValues;
std::vector<double> filteredXValues;
std::vector<double> filteredErrorValues;
{
auto intervalsOfValidValues = RiaCurveDataTools::calculateIntervalsOfValidValues( yValues,
keepOnlyPositiveValues );
RiaCurveDataTools::getValuesByIntervals( yValues, intervalsOfValidValues, &filteredYValues );
RiaCurveDataTools::getValuesByIntervals( xValues, intervalsOfValidValues, &filteredXValues );
if ( showErrorBars )
RiaCurveDataTools::getValuesByIntervals( errorValues, intervalsOfValidValues, &filteredErrorValues );
filteredIntervals = RiaCurveDataTools::computePolyLineStartStopIndices( intervalsOfValidValues );
}
points.reserve( static_cast<int>( filteredXValues.size() ) );
errorIntervals.reserve( static_cast<int>( filteredXValues.size() ) );
for ( size_t i = 0; i < filteredXValues.size(); i++ )
{
points << QPointF( filteredXValues[i], filteredYValues[i] );
if ( showErrorBars && filteredYValues[i] != DOUBLE_INF && filteredErrorValues[i] != DOUBLE_INF )
{
if ( errorAxis == ERROR_ALONG_Y_AXIS )
{
errorIntervals << QwtIntervalSample( filteredXValues[i],
filteredYValues[i] - filteredErrorValues[i],
filteredYValues[i] + filteredErrorValues[i] );
}
else
{
errorIntervals << QwtIntervalSample( filteredYValues[i],
filteredXValues[i] - filteredErrorValues[i],
filteredXValues[i] + filteredErrorValues[i] );
}
}
}
}
this->setSamples( points );
this->setLineSegmentStartStopIndices( filteredIntervals );
if ( showErrorBars )
{
m_errorBars->setSamples( errorIntervals );
if ( errorAxis == ERROR_ALONG_Y_AXIS )
{
m_errorBars->setOrientation( Qt::Vertical );
}
else
{
m_errorBars->setOrientation( Qt::Horizontal );
}
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -150,7 +67,7 @@ void RiuQwtPlotCurve::setSamplesFromXValuesAndYValues( const std::vector<double>
const std::vector<double>& yValues, const std::vector<double>& yValues,
bool keepOnlyPositiveValues ) bool keepOnlyPositiveValues )
{ {
setSamplesFromXValuesAndYValues( xValues, yValues, std::vector<double>(), keepOnlyPositiveValues ); computeValidIntervalsAndSetCurveData( xValues, yValues, keepOnlyPositiveValues );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -160,10 +77,9 @@ void RiuQwtPlotCurve::setSamplesFromDatesAndYValues( const std::vector<QDateTime
const std::vector<double>& yValues, const std::vector<double>& yValues,
bool keepOnlyPositiveValues ) bool keepOnlyPositiveValues )
{ {
setSamplesFromXValuesAndYValues( RiuQwtPlotCurve::fromQDateTime( dateTimes ), auto xValues = RiuQwtPlotCurve::fromQDateTime( dateTimes );
yValues,
std::vector<double>(), computeValidIntervalsAndSetCurveData( xValues, yValues, keepOnlyPositiveValues );
keepOnlyPositiveValues );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -173,24 +89,9 @@ void RiuQwtPlotCurve::setSamplesFromTimeTAndYValues( const std::vector<time_t>&
const std::vector<double>& yValues, const std::vector<double>& yValues,
bool keepOnlyPositiveValues ) bool keepOnlyPositiveValues )
{ {
setSamplesFromXValuesAndYValues( RiuQwtPlotCurve::fromTime_t( dateTimes ), auto xValues = RiuQwtPlotCurve::fromTime_t( dateTimes );
yValues,
std::vector<double>(),
keepOnlyPositiveValues );
}
//-------------------------------------------------------------------------------------------------- computeValidIntervalsAndSetCurveData( xValues, yValues, keepOnlyPositiveValues );
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setSamplesFromTimeTAndYValues( const std::vector<time_t>& dateTimes,
const std::vector<double>& yValues,
const std::vector<double>& yErrorValues,
bool keepOnlyPositiveValues )
{
setSamplesFromXValuesAndYValues( RiuQwtPlotCurve::fromTime_t( dateTimes ),
yValues,
yErrorValues,
keepOnlyPositiveValues );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -348,69 +249,6 @@ void RiuQwtPlotCurve::setSymbolSkipPixelDistance( float distance )
m_symbolSkipPixelDistance = distance >= 0.0f ? distance : 0.0f; m_symbolSkipPixelDistance = distance >= 0.0f ? distance : 0.0f;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::attach( QwtPlot* plot )
{
QwtPlotItem::attach( plot );
if ( m_showErrorBars )
{
m_errorBars->attach( plot );
}
m_attachedToPlot = plot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::detach()
{
QwtPlotItem::detach();
m_errorBars->detach();
m_attachedToPlot = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::clearErrorBars()
{
m_errorBars->setSamples( nullptr );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::showErrorBars( bool show )
{
m_showErrorBars = show;
if ( m_showErrorBars && m_attachedToPlot )
m_errorBars->attach( m_attachedToPlot );
else
m_errorBars->detach();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setErrorBarsColor( QColor color )
{
QwtIntervalSymbol* newSymbol = new QwtIntervalSymbol( QwtIntervalSymbol::Bar );
newSymbol->setPen( QPen( color ) );
m_errorBars->setSymbol( newSymbol );
}
//--------------------------------------------------------------------------------------------------
/// Set the Qwt X-Axis (QwtPlot::xBottom or QwtPlot::xTop).
/// This is important to make sure the x-axis interval is set correctly.
/// WellLogPlots use top-axis and Summary uses bottom axis.
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setErrorBarsXAxis( int axis )
{
m_errorBars->setXAxis( axis );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -499,6 +337,26 @@ QwtGraphic RiuQwtPlotCurve::legendIcon( int index, const QSizeF& size ) const
return icon; return icon;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::computeValidIntervalsAndSetCurveData( const std::vector<double>& xValues,
const std::vector<double>& yValues,
bool keepOnlyPositiveValues )
{
auto intervalsOfValidValues = RiaCurveDataTools::calculateIntervalsOfValidValues( yValues, keepOnlyPositiveValues );
std::vector<double> validYValues;
std::vector<double> validXValues;
RiaCurveDataTools::getValuesByIntervals( yValues, intervalsOfValidValues, &validYValues );
RiaCurveDataTools::getValuesByIntervals( xValues, intervalsOfValidValues, &validXValues );
setSamples( validXValues.data(), validYValues.data(), static_cast<int>( validXValues.size() ) );
setLineSegmentStartStopIndices( intervalsOfValidValues );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -23,10 +23,6 @@
#include "qwt_plot_intervalcurve.h" #include "qwt_plot_intervalcurve.h"
#include "qwt_symbol.h" #include "qwt_symbol.h"
#include <memory>
class RiuErrorBarsQwtPlotCurve;
//================================================================================================== //==================================================================================================
// //
// If infinite data is present in the curve data, Qwt is not able to draw a nice curve. // If infinite data is present in the curve data, Qwt is not able to draw a nice curve.
@ -50,12 +46,6 @@ class RiuErrorBarsQwtPlotCurve;
class RiuQwtPlotCurve : public QwtPlotCurve class RiuQwtPlotCurve : public QwtPlotCurve
{ {
public: public:
enum ErrorAxis
{
ERROR_ALONG_X_AXIS,
ERROR_ALONG_Y_AXIS
};
enum CurveInterpolationEnum enum CurveInterpolationEnum
{ {
INTERPOLATION_POINT_TO_POINT, INTERPOLATION_POINT_TO_POINT,
@ -89,12 +79,6 @@ public:
const std::vector<double>& yValues, const std::vector<double>& yValues,
bool keepOnlyPositiveValues ); bool keepOnlyPositiveValues );
void setSamplesFromXValuesAndYValues( const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& errorValues,
bool keepOnlyPositiveValues,
ErrorAxis errorAxis = ERROR_ALONG_Y_AXIS );
void setSamplesFromDatesAndYValues( const std::vector<QDateTime>& dateTimes, void setSamplesFromDatesAndYValues( const std::vector<QDateTime>& dateTimes,
const std::vector<double>& yValues, const std::vector<double>& yValues,
bool keepOnlyPositiveValues ); bool keepOnlyPositiveValues );
@ -103,30 +87,22 @@ public:
const std::vector<double>& yValues, const std::vector<double>& yValues,
bool keepOnlyPositiveValues ); bool keepOnlyPositiveValues );
void setSamplesFromTimeTAndYValues( const std::vector<time_t>& dateTimes,
const std::vector<double>& yValues,
const std::vector<double>& yErrorValues,
bool keepOnlyPositiveValues );
void setLineSegmentStartStopIndices( const std::vector<std::pair<size_t, size_t>>& lineSegmentStartStopIndices ); void setLineSegmentStartStopIndices( const std::vector<std::pair<size_t, size_t>>& lineSegmentStartStopIndices );
void setSymbolSkipPixelDistance( float distance ); void setSymbolSkipPixelDistance( float distance );
void attach( QwtPlot* plot );
void detach();
void clearErrorBars();
void showErrorBars( bool show );
void setErrorBarsColor( QColor color );
void setErrorBarsXAxis( int axis );
void setPerPointLabels( const std::vector<QString>& labels ); void setPerPointLabels( const std::vector<QString>& labels );
void setAppearance( LineStyleEnum lineStyle, void setAppearance( LineStyleEnum lineStyle,
CurveInterpolationEnum interpolationType, CurveInterpolationEnum interpolationType,
int curveThickness, int curveThickness,
const QColor& curveColor ); const QColor& curveColor );
void setBlackAndWhiteLegendIcon( bool blackAndWhite ); void setBlackAndWhiteLegendIcon( bool blackAndWhite );
QwtGraphic legendIcon( int index, const QSizeF& size ) const override; QwtGraphic legendIcon( int index, const QSizeF& size ) const override;
static std::vector<double> fromQDateTime( const std::vector<QDateTime>& dateTimes );
static std::vector<double> fromTime_t( const std::vector<time_t>& timeSteps );
protected: protected:
void drawCurve( QPainter* p, void drawCurve( QPainter* p,
int style, int style,
@ -145,17 +121,15 @@ protected:
int to ) const override; int to ) const override;
private: private:
static std::vector<double> fromQDateTime( const std::vector<QDateTime>& dateTimes ); void computeValidIntervalsAndSetCurveData( const std::vector<double>& xValues,
static std::vector<double> fromTime_t( const std::vector<time_t>& timeSteps ); const std::vector<double>& yValues,
bool keepOnlyPositiveValues );
private: private:
std::vector<std::pair<size_t, size_t>> m_polyLineStartStopIndices; float m_symbolSkipPixelDistance;
float m_symbolSkipPixelDistance; bool m_blackAndWhiteLegendIcon;
bool m_showErrorBars;
QwtPlotIntervalCurve* m_errorBars;
QwtPlot* m_attachedToPlot;
bool m_blackAndWhiteLegendIcon;
std::vector<QString> m_perPointLabels; std::vector<QString> m_perPointLabels;
std::vector<std::pair<size_t, size_t>> m_polyLineStartStopIndices;
}; };