From edae328ca613ac4d3291df9c8d7ab285ad4cfd89 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 23 May 2024 12:24:13 +0100 Subject: [PATCH] Push multi-sweep traces down into MathPlot. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17215 --- common/widgets/mathplot.cpp | 14 +++++++---- eeschema/sim/sim_plot_tab.cpp | 5 +++- eeschema/sim/sim_plot_tab.h | 3 ++- eeschema/sim/simulator_frame_ui.cpp | 38 ++++++----------------------- include/widgets/mathplot.h | 16 +++++++++--- 5 files changed, 35 insertions(+), 41 deletions(-) diff --git a/common/widgets/mathplot.cpp b/common/widgets/mathplot.cpp index 0f15997c08..9b2f1fe05a 100644 --- a/common/widgets/mathplot.cpp +++ b/common/widgets/mathplot.cpp @@ -518,8 +518,10 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w ) ys.insert( w.y2p( py ) ); } } - else + else for( int sweep = 0; sweep < GetSweepCount(); ++sweep ) { + SetSweepWindow( sweep ); + int count = 0; int x0 = 0; // X position of merged current vertical line int ymin0 = 0; // y min coord of merged current vertical line @@ -2590,18 +2592,20 @@ double mpScaleXLog::TransformFromPlot( double xplot ) const void mpFXYVector::Rewind() { m_index = 0; + m_sweepWindow = std::numeric_limits::max(); } -size_t mpFXYVector::GetCount() const +void mpFXYVector::SetSweepWindow( int aSweepIdx ) { - return m_xs.size(); + m_index = aSweepIdx * m_sweepSize; + m_sweepWindow = ( aSweepIdx + 1 ) * m_sweepSize; } bool mpFXYVector::GetNextXY( double& x, double& y ) { - if( m_index >= m_xs.size() ) + if( m_index >= m_xs.size() || m_index >= m_sweepWindow ) { return false; } @@ -2609,7 +2613,7 @@ bool mpFXYVector::GetNextXY( double& x, double& y ) { x = m_xs[m_index]; y = m_ys[m_index++]; - return m_index <= m_xs.size(); + return m_index <= m_xs.size() && m_index <= m_sweepWindow; } } diff --git a/eeschema/sim/sim_plot_tab.cpp b/eeschema/sim/sim_plot_tab.cpp index 782e75de4f..e9909e6667 100644 --- a/eeschema/sim/sim_plot_tab.cpp +++ b/eeschema/sim/sim_plot_tab.cpp @@ -874,7 +874,8 @@ TRACE* SIM_PLOT_TAB::GetOrAddTrace( const wxString& aVectorName, int aType ) } -void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector& aX, std::vector& aY ) +void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector& aX, std::vector& aY, + int aSweepCount, size_t aSweepSize ) { if( dynamic_cast*>( m_axis_x ) ) { @@ -905,6 +906,8 @@ void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector& aX, std::vec } trace->SetData( aX, aY ); + trace->SetSweepCount( aSweepCount ); + trace->SetSweepSize( aSweepSize ); if( ( trace->GetType() & SPT_AC_PHASE ) || ( trace->GetType() & SPT_CURRENT ) ) trace->SetScale( m_axis_x, m_axis_y2 ); diff --git a/eeschema/sim/sim_plot_tab.h b/eeschema/sim/sim_plot_tab.h index ce8574d56b..6dba50b8db 100644 --- a/eeschema/sim/sim_plot_tab.h +++ b/eeschema/sim/sim_plot_tab.h @@ -351,7 +351,8 @@ public: TRACE* GetOrAddTrace( const wxString& aVectorName, int aType ); - void SetTraceData( TRACE* aTrace, std::vector& aX, std::vector& aY ); + void SetTraceData( TRACE* aTrace, std::vector& aX, std::vector& aY, + int aSweepCount, size_t aSweepSize ); bool DeleteTrace( const wxString& aVectorName, int aTraceType ); void DeleteTrace( TRACE* aTrace ); diff --git a/eeschema/sim/simulator_frame_ui.cpp b/eeschema/sim/simulator_frame_ui.cpp index 36c4e97a5a..da171cc5dc 100644 --- a/eeschema/sim/simulator_frame_ui.cpp +++ b/eeschema/sim/simulator_frame_ui.cpp @@ -1744,46 +1744,24 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp wxFAIL_MSG( wxT( "Unhandled plot type" ) ); } - // If we did a two-source DC analysis, we need to split the resulting vector and add traces - // for each input step SPICE_DC_PARAMS source1, source2; + int sweepCount = 1; + size_t sweepSize = std::numeric_limits::max(); if( simType == ST_DC && circuitModel()->ParseDCCommand( aPlotTab->GetSimCommand(), &source1, &source2 ) && !source2.m_source.IsEmpty() ) { - // Source 1 is the inner loop, so lets add traces for each Source 2 (outer loop) step - SPICE_VALUE v = source2.m_vstart; + SPICE_VALUE v = ( source2.m_vend - source2.m_vstart ) / source2.m_vincrement; - size_t offset = 0; - size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble(); - size_t inner = aDataX->size() / ( outer + 1 ); - - wxASSERT( aDataX->size() % ( outer + 1 ) == 0 ); - - for( size_t idx = 0; idx <= outer; idx++ ) - { - if( TRACE* trace = aPlotTab->GetOrAddTrace( aVectorName, aTraceType ) ) - { - if( data_y.size() >= size ) - { - std::vector sub_x( aDataX->begin() + offset, - aDataX->begin() + offset + inner ); - std::vector sub_y( data_y.begin() + offset, - data_y.begin() + offset + inner ); - - aPlotTab->SetTraceData( trace, sub_x, sub_y ); - } - } - - v = v + source2.m_vincrement; - offset += inner; - } + sweepCount = KiROUND( v.ToDouble() ) + 1; + sweepSize = aDataX->size() / sweepCount; } - else if( TRACE* trace = aPlotTab->GetOrAddTrace( aVectorName, aTraceType ) ) + + if( TRACE* trace = aPlotTab->GetOrAddTrace( aVectorName, aTraceType ) ) { if( data_y.size() >= size ) - aPlotTab->SetTraceData( trace, *aDataX, data_y ); + aPlotTab->SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize ); } } diff --git a/include/widgets/mathplot.h b/include/widgets/mathplot.h index 9c1fea0443..e416036af1 100644 --- a/include/widgets/mathplot.h +++ b/include/widgets/mathplot.h @@ -550,6 +550,7 @@ public: * Override this function in your implementation. */ virtual void Rewind() = 0; + virtual void SetSweepWindow( int aSweepIdx ) { Rewind(); } /** Get locus value for next N. * Override this function in your implementation. @@ -559,6 +560,7 @@ public: virtual bool GetNextXY( double& x, double& y ) = 0; virtual size_t GetCount() const = 0; + virtual int GetSweepCount() const { return 1; } /** Layer plot handler. * This implementation will plot the locus in the visible area and put a label according to @@ -1419,6 +1421,9 @@ public: */ virtual void SetData( const std::vector& xs, const std::vector& ys ); + void SetSweepCount( int aSweepCount ) { m_sweepCount = aSweepCount; } + void SetSweepSize( size_t aSweepSize ) { m_sweepSize = aSweepSize; } + /** Clears all the data, leaving the layer empty. * @sa SetData */ @@ -1429,18 +1434,20 @@ protected: */ std::vector m_xs, m_ys; - /** The internal counter for the "GetNextXY" interface - */ - size_t m_index; + size_t m_index; // internal counter for the "GetNextXY" interface + size_t m_sweepWindow; // last m_index of the current sweep /** Loaded at SetData */ double m_minX, m_maxX, m_minY, m_maxY; + int m_sweepCount = 1; // sweeps to split data into + size_t m_sweepSize = std::numeric_limits::max(); // data-points in each sweep /** Rewind value enumeration with mpFXY::GetNextXY. * Overridden in this implementation. */ void Rewind() override; + void SetSweepWindow( int aSweepIdx ) override; /** Get locus value for next N. * Overridden in this implementation. @@ -1449,7 +1456,8 @@ protected: */ bool GetNextXY( double& x, double& y ) override; - size_t GetCount() const override; + size_t GetCount() const override { return m_xs.size(); } + int GetSweepCount() const override { return m_sweepCount; } public: /** Returns the actual minimum X data (loaded in SetData).