From 9ef43542f1f809be6dcfeee536cb4471316249f5 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sun, 12 May 2024 23:27:13 +0200 Subject: [PATCH] add option to provide an option for color fill in some graphs #820 --- Source/Core/Core.h | 1 + Source/Core/VideoCore.cpp | 10 ++-- Source/GUI/Plot.cpp | 98 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core.h b/Source/Core/Core.h index 53644fe8a..972d0c426 100755 --- a/Source/Core/Core.h +++ b/Source/Core/Core.h @@ -65,6 +65,7 @@ struct per_item const activefilter Filter; const char* color; const int thickness; + const char* fillInfo { nullptr }; }; struct stream_info diff --git a/Source/Core/VideoCore.cpp b/Source/Core/VideoCore.cpp index 6602ea8be..70087c868 100644 --- a/Source/Core/VideoCore.cpp +++ b/Source/Core/VideoCore.cpp @@ -271,11 +271,11 @@ struct per_group VideoPerGroup [Group_VideoMax]= const struct per_item VideoPerItem [Item_VideoMax]= { //Y - { Group_Y, Group_VideoMax, "Y MIN", "lavfi.signalstats.YMIN", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, "gray", 1 }, - { Group_Y, Group_VideoMax, "Y LOW", "lavfi.signalstats.YLOW", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, "green", 2 }, - { Group_Y, Group_VideoMax, "Y AVG", "lavfi.signalstats.YAVG", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, "yellow", 3 }, - { Group_Y, Group_VideoMax, "Y HIGH", "lavfi.signalstats.YHIGH", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, nullptr, -1 }, - { Group_Y, Group_VideoMax, "Y MAX", "lavfi.signalstats.YMAX", 0, true, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, nullptr, -1 }, + { Group_Y, Group_VideoMax, "Y MIN", "lavfi.signalstats.YMIN", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, "gray", 1, }, // "Y LOW;green;0.5" }, + { Group_Y, Group_VideoMax, "Y LOW", "lavfi.signalstats.YLOW", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, "green", 2, }, // "Y LOW;transparent;0.5" }, + { Group_Y, Group_VideoMax, "Y AVG", "lavfi.signalstats.YAVG", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, "yellow", 3, }, // "Y LOW;red;0.5" }, + { Group_Y, Group_VideoMax, "Y HIGH", "lavfi.signalstats.YHIGH", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, nullptr, -1, "Y AVG;yellow;0.8" }, + { Group_Y, Group_VideoMax, "Y MAX", "lavfi.signalstats.YMAX", 0, true, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, nullptr, -1, "Y HIGH;green;0.5" }, //U { Group_U, Group_VideoMax, "U MIN", "lavfi.signalstats.UMIN", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, nullptr, -1 }, { Group_U, Group_VideoMax, "U LOW", "lavfi.signalstats.ULOW", 0, false, DBL_MAX, DBL_MAX, ActiveFilter_Video_signalstats, nullptr, -1 }, diff --git a/Source/GUI/Plot.cpp b/Source/GUI/Plot.cpp index 2c0dbef7b..6dfa56117 100644 --- a/Source/GUI/Plot.cpp +++ b/Source/GUI/Plot.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "Core/FileInformation.h" #include @@ -250,7 +251,80 @@ class PlotCurve : public QwtPlotCurve { m_count = count; } + void setClipCurve(QwtPlotCurve* curve) { + m_clipCurve = curve; + } + + void setFillBrush(QBrush brush) { + m_fillBrush = brush; + } + protected: + virtual void drawCurve( QPainter* painter , int style, const QwtScaleMap& xMap, const QwtScaleMap& yMap, const QRectF& canvasRect, int from, int to ) const { + QwtPlotCurve::drawCurve(painter, style, xMap, yMap, canvasRect, from, to); + + if(m_clipCurve && !symbol()) + { + auto brush = m_fillBrush; + + if ( brush.style() == Qt::NoBrush ) + return; + + const bool doFit = ( testCurveAttribute( Fitted ) && curveFitter() ); + const bool doAlign = !doFit && QwtPainter::roundingAlignment( painter ); + + QwtPointMapper mapper; + + if ( doAlign ) + { + mapper.setFlag( QwtPointMapper::RoundPoints, true ); + mapper.setFlag( QwtPointMapper::WeedOutIntermediatePoints, + testPaintAttribute( FilterPointsAggressive ) ); + } + + mapper.setFlag( QwtPointMapper::WeedOutPoints, + testPaintAttribute( FilterPoints ) || + testPaintAttribute( FilterPointsAggressive ) ); + + mapper.setBoundingRect( canvasRect ); + QPolygonF polygon = mapper.toPolygonF( xMap, yMap, data(), from, to); + QPolygonF baselinePolygon = mapper.toPolygonF( xMap, yMap, m_clipCurve->data(), from, to); + + for(auto it = baselinePolygon.rbegin(); it != baselinePolygon.rend(); ++it) { + polygon += *it; + } + + if ( polygon.count() <= 2 ) // a line can't be filled + return; + + if ( !brush.color().isValid() ) + brush.setColor( this->pen().color() ); + + if ( testPaintAttribute(ClipPolygons) ) + { + const QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter ); + QwtClipper::clipPolygonF( clipRect, polygon, true ); + } + + painter->save(); + + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); + + QwtPainter::drawPolygon( painter, polygon ); + + painter->restore(); + } + } + + virtual void fillCurve( QPainter *painter, const QwtScaleMap& xMap, const QwtScaleMap& yMap, const QRectF& canvasRect, QPolygonF& polygon) const { + QwtPlotCurve::fillCurve(painter, xMap, yMap, canvasRect, polygon); + } + + virtual void drawLines(QPainter* p, const QwtScaleMap& xMap, const QwtScaleMap& yMap, const QRectF& canvasRect, int from, int to) const { + QwtPlotCurve::drawLines(p, xMap, yMap, canvasRect, from, to); + } + void drawSymbols(QPainter *p, const QwtSymbol &s, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const { QwtPointMapper mapper; @@ -287,6 +361,8 @@ class PlotCurve : public QwtPlotCurve { private: int m_index; int m_count; + QBrush m_fillBrush; + QwtPlotCurve* m_clipCurve { nullptr }; }; //*************************************************************************** @@ -506,6 +582,7 @@ Plot::Plot( size_t streamPos, size_t Type, size_t Group, const FileInformation* // curves m_curves.reserve(PerStreamType[m_type].PerGroup[m_group].Count); + QMap curvesByName; for( unsigned j = 0; j < PerStreamType[m_type].PerGroup[m_group].Count; ++j ) { @@ -536,6 +613,27 @@ Plot::Plot( size_t streamPos, size_t Type, size_t Group, const FileInformation* curve->attach( this ); m_curves += curve; + + curvesByName[item.Name] = curve; + } + + for( unsigned j = 0; j < PerStreamType[m_type].PerGroup[m_group].Count; ++j ) + { + auto item = PerStreamType[m_type].PerItem[PerStreamType[m_type].PerGroup[m_group].Start + j]; + if(item.fillInfo) { + auto splitted = QString(item.fillInfo).split(";"); + auto curveName = splitted[0]; + auto color = QColor(splitted[1]); + auto alpha = QString(splitted[2]).toFloat(); + + color.setAlphaF(alpha); + auto curve = curvesByName[item.Name]; + curve->setFillBrush(QBrush(color)); + + auto fillCurve = curvesByName[curveName]; + + curve->setClipCurve(fillCurve); + } } PlotPicker* picker = new PlotPicker( this, &PerStreamType[m_type], m_group, &m_curves, fileInformation );