2015-09-17 11:42:35 -05:00
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
2015-11-06 01:32:58 -06:00
# include "RiuLineSegmentQwtPlotCurve.h"
2015-09-17 11:42:35 -05:00
2015-11-06 03:08:35 -06:00
# include "qwt_symbol.h"
2016-05-24 03:30:50 -05:00
# include "RigCurveDataTools.h"
# include "qwt_date.h"
2016-06-22 03:38:04 -05:00
# include "qwt_point_mapper.h"
# include "qwt_painter.h"
2015-10-15 04:27:12 -05:00
2015-09-17 11:42:35 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-11-06 03:08:35 -06:00
RiuLineSegmentQwtPlotCurve : : RiuLineSegmentQwtPlotCurve ( const QString & title )
: QwtPlotCurve ( title )
2015-09-17 11:42:35 -05:00
{
2016-06-22 03:38:04 -05:00
this - > setLegendAttribute ( QwtPlotCurve : : LegendShowLine , true ) ;
this - > setLegendAttribute ( QwtPlotCurve : : LegendShowSymbol , true ) ;
this - > setLegendAttribute ( QwtPlotCurve : : LegendShowBrush , true ) ;
this - > setRenderHint ( QwtPlotItem : : RenderAntialiased , true ) ;
m_symbolSkipPixelDistance = 10.0f ;
2015-09-17 11:42:35 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-11-06 01:32:58 -06:00
RiuLineSegmentQwtPlotCurve : : ~ RiuLineSegmentQwtPlotCurve ( )
2015-09-17 11:42:35 -05:00
{
}
2016-05-24 03:30:50 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2016-10-12 06:49:57 -05:00
void RiuLineSegmentQwtPlotCurve : : setSamplesFromDateAndValues ( const std : : vector < QDateTime > & dateTimes , const std : : vector < double > & timeHistoryValues , bool removeNegativeValues )
2016-05-24 03:30:50 -05:00
{
CVF_ASSERT ( dateTimes . size ( ) = = timeHistoryValues . size ( ) ) ;
QPolygonF points ;
std : : vector < std : : pair < size_t , size_t > > filteredIntervals ;
{
std : : vector < double > filteredTimeHistoryValues ;
std : : vector < QDateTime > filteredDateTimes ;
{
std : : vector < std : : pair < size_t , size_t > > intervalsOfValidValues ;
2016-10-12 06:49:57 -05:00
RigCurveDataTools : : calculateIntervalsOfValidValues ( timeHistoryValues , & intervalsOfValidValues , removeNegativeValues ) ;
2016-05-24 03:30:50 -05:00
RigCurveDataTools : : getValuesByIntervals ( timeHistoryValues , intervalsOfValidValues , & filteredTimeHistoryValues ) ;
RigCurveDataTools : : getValuesByIntervals ( dateTimes , intervalsOfValidValues , & filteredDateTimes ) ;
RigCurveDataTools : : computePolyLineStartStopIndices ( intervalsOfValidValues , & filteredIntervals ) ;
}
2016-11-22 04:13:34 -06:00
for ( size_t i = 0 ; i < filteredDateTimes . size ( ) ; i + + )
{
double milliSecSinceEpoch = QwtDate : : toDouble ( filteredDateTimes [ i ] ) ;
points < < QPointF ( milliSecSinceEpoch , filteredTimeHistoryValues [ i ] ) ;
}
}
this - > setSamples ( points ) ;
this - > setLineSegmentStartStopIndices ( filteredIntervals ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve : : setSamplesFromTimeTAndValues ( const std : : vector < time_t > & dateTimes , const std : : vector < double > & timeHistoryValues , bool removeNegativeValues )
{
CVF_ASSERT ( dateTimes . size ( ) = = timeHistoryValues . size ( ) ) ;
QPolygonF points ;
std : : vector < std : : pair < size_t , size_t > > filteredIntervals ;
{
std : : vector < double > filteredTimeHistoryValues ;
std : : vector < time_t > filteredDateTimes ;
{
std : : vector < std : : pair < size_t , size_t > > intervalsOfValidValues ;
RigCurveDataTools : : calculateIntervalsOfValidValues ( timeHistoryValues , & intervalsOfValidValues , removeNegativeValues ) ;
RigCurveDataTools : : getValuesByIntervals ( timeHistoryValues , intervalsOfValidValues , & filteredTimeHistoryValues ) ;
RigCurveDataTools : : getValuesByIntervals ( dateTimes , intervalsOfValidValues , & filteredDateTimes ) ;
RigCurveDataTools : : computePolyLineStartStopIndices ( intervalsOfValidValues , & filteredIntervals ) ;
}
2016-05-24 03:30:50 -05:00
for ( size_t i = 0 ; i < filteredDateTimes . size ( ) ; i + + )
{
2016-11-22 04:13:34 -06:00
double milliSecSinceEpoch = filteredDateTimes [ i ] * 1000 ; // This is kind of hack, as the c++ standard does not state what time_t is. "Almost always" secs since epoch according to cppreference.com
2016-05-24 03:30:50 -05:00
points < < QPointF ( milliSecSinceEpoch , filteredTimeHistoryValues [ i ] ) ;
}
}
this - > setSamples ( points ) ;
this - > setLineSegmentStartStopIndices ( filteredIntervals ) ;
}
2015-09-17 11:42:35 -05:00
//--------------------------------------------------------------------------------------------------
2016-11-22 04:13:34 -06:00
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve : : setSamplesFromTimeAndValues ( const std : : vector < double > & times , const std : : vector < double > & timeHistoryValues , bool removeNegativeValues )
{
CVF_ASSERT ( times . size ( ) = = timeHistoryValues . size ( ) ) ;
QPolygonF points ;
std : : vector < std : : pair < size_t , size_t > > filteredIntervals ;
{
std : : vector < double > filteredTimeHistoryValues ;
std : : vector < double > filteredTimes ;
{
std : : vector < std : : pair < size_t , size_t > > intervalsOfValidValues ;
RigCurveDataTools : : calculateIntervalsOfValidValues ( timeHistoryValues , & intervalsOfValidValues , removeNegativeValues ) ;
RigCurveDataTools : : getValuesByIntervals ( timeHistoryValues , intervalsOfValidValues , & filteredTimeHistoryValues ) ;
RigCurveDataTools : : getValuesByIntervals ( times , intervalsOfValidValues , & filteredTimes ) ;
RigCurveDataTools : : computePolyLineStartStopIndices ( intervalsOfValidValues , & filteredIntervals ) ;
}
for ( size_t i = 0 ; i < filteredTimes . size ( ) ; i + + )
{
points < < QPointF ( filteredTimes [ i ] , filteredTimeHistoryValues [ i ] ) ;
}
}
this - > setSamples ( points ) ;
this - > setLineSegmentStartStopIndices ( filteredIntervals ) ;
}
//--------------------------------------------------------------------------------------------------
2015-09-17 11:42:35 -05:00
///
//--------------------------------------------------------------------------------------------------
2015-11-06 01:32:58 -06:00
void RiuLineSegmentQwtPlotCurve : : drawCurve ( QPainter * p , int style ,
2015-09-17 11:42:35 -05:00
const QwtScaleMap & xMap , const QwtScaleMap & yMap ,
const QRectF & canvasRect , int from , int to ) const
{
2015-10-15 16:12:18 -05:00
size_t intervalCount = m_polyLineStartStopIndices . size ( ) ;
2015-09-17 11:42:35 -05:00
if ( intervalCount > 0 )
{
for ( size_t intIdx = 0 ; intIdx < intervalCount ; intIdx + + )
{
2015-11-06 03:08:35 -06:00
if ( m_polyLineStartStopIndices [ intIdx ] . first = = m_polyLineStartStopIndices [ intIdx ] . second )
{
// Use a symbol to draw a single value, as a single value will not be visible
// when using QwtPlotCurve::drawCurve without symbols activated
QwtSymbol symbol ( QwtSymbol : : XCross ) ;
symbol . setSize ( 10 , 10 ) ;
QwtPlotCurve : : drawSymbols ( p , symbol , xMap , yMap , canvasRect , ( int ) m_polyLineStartStopIndices [ intIdx ] . first , ( int ) m_polyLineStartStopIndices [ intIdx ] . second ) ;
}
else
{
QwtPlotCurve : : drawCurve ( p , style , xMap , yMap , canvasRect , ( int ) m_polyLineStartStopIndices [ intIdx ] . first , ( int ) m_polyLineStartStopIndices [ intIdx ] . second ) ;
}
2015-09-17 11:42:35 -05:00
}
}
2015-11-06 03:08:35 -06:00
else
{
QwtPlotCurve : : drawCurve ( p , style , xMap , yMap , canvasRect , from , to ) ;
}
2015-09-17 11:42:35 -05:00
} ;
2015-10-15 04:27:12 -05:00
2016-06-22 03:38:04 -05:00
//--------------------------------------------------------------------------------------------------
/// Drawing symbols but skipping if they are to close to the previous one
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve : : drawSymbols ( QPainter * painter , const QwtSymbol & symbol ,
const QwtScaleMap & xMap , const QwtScaleMap & yMap ,
const QRectF & canvasRect , int from , int to ) const
{
if ( m_symbolSkipPixelDistance < = 0 )
{
QwtPlotCurve : : drawSymbols ( painter , symbol , xMap , yMap , canvasRect , from , to ) ;
return ;
}
QwtPointMapper mapper ;
mapper . setFlag ( QwtPointMapper : : RoundPoints ,
QwtPainter : : roundingAlignment ( painter ) ) ;
mapper . setFlag ( QwtPointMapper : : WeedOutPoints ,
testPaintAttribute ( QwtPlotCurve : : FilterPoints ) ) ;
mapper . setBoundingRect ( canvasRect ) ;
const QPolygonF points = mapper . toPointsF ( xMap , yMap ,
data ( ) , from , to ) ;
int pointCount = points . size ( ) ;
QPolygonF filteredPoints ;
QPointF lastDrawnSymbolPos ;
if ( pointCount > 0 )
{
filteredPoints . push_back ( points [ 0 ] ) ;
lastDrawnSymbolPos = points [ 0 ] ;
}
float sqSkipDist = m_symbolSkipPixelDistance * m_symbolSkipPixelDistance ;
for ( int pIdx = 1 ; pIdx < pointCount - 1 ; + + pIdx )
{
QPointF diff = points [ pIdx ] - lastDrawnSymbolPos ;
float sqDistBetweenSymbols = diff . x ( ) * diff . x ( ) + diff . y ( ) * diff . y ( ) ;
if ( sqDistBetweenSymbols > sqSkipDist )
{
filteredPoints . push_back ( points [ pIdx ] ) ;
lastDrawnSymbolPos = points [ pIdx ] ;
}
}
if ( pointCount > 1 ) filteredPoints . push_back ( points . back ( ) ) ;
if ( filteredPoints . size ( ) > 0 )
symbol . drawSymbols ( painter , filteredPoints ) ;
}
2015-10-15 04:27:12 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-11-06 03:08:35 -06:00
void RiuLineSegmentQwtPlotCurve : : setLineSegmentStartStopIndices ( const std : : vector < std : : pair < size_t , size_t > > & lineSegmentStartStopIndices )
2015-11-06 01:32:58 -06:00
{
m_polyLineStartStopIndices = lineSegmentStartStopIndices ;
2015-10-15 04:27:12 -05:00
}
2016-06-22 03:38:04 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve : : setSymbolSkipPixelDistance ( float distance )
{
m_symbolSkipPixelDistance = distance > = 0.0f ? distance : 0.0f ;
}