Push multi-sweep traces down into MathPlot.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/17215
This commit is contained in:
parent
0bcd5e5795
commit
edae328ca6
|
@ -518,8 +518,10 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
|
||||||
ys.insert( w.y2p( py ) );
|
ys.insert( w.y2p( py ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else for( int sweep = 0; sweep < GetSweepCount(); ++sweep )
|
||||||
{
|
{
|
||||||
|
SetSweepWindow( sweep );
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int x0 = 0; // X position of merged current vertical line
|
int x0 = 0; // X position of merged current vertical line
|
||||||
int ymin0 = 0; // y min coord 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()
|
void mpFXYVector::Rewind()
|
||||||
{
|
{
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
|
m_sweepWindow = std::numeric_limits<size_t>::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 )
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2609,7 +2613,7 @@ bool mpFXYVector::GetNextXY( double& x, double& y )
|
||||||
{
|
{
|
||||||
x = m_xs[m_index];
|
x = m_xs[m_index];
|
||||||
y = m_ys[m_index++];
|
y = m_ys[m_index++];
|
||||||
return m_index <= m_xs.size();
|
return m_index <= m_xs.size() && m_index <= m_sweepWindow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -874,7 +874,8 @@ TRACE* SIM_PLOT_TAB::GetOrAddTrace( const wxString& aVectorName, int aType )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector<double>& aX, std::vector<double>& aY )
|
void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector<double>& aX, std::vector<double>& aY,
|
||||||
|
int aSweepCount, size_t aSweepSize )
|
||||||
{
|
{
|
||||||
if( dynamic_cast<LOG_SCALE<mpScaleXLog>*>( m_axis_x ) )
|
if( dynamic_cast<LOG_SCALE<mpScaleXLog>*>( m_axis_x ) )
|
||||||
{
|
{
|
||||||
|
@ -905,6 +906,8 @@ void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector<double>& aX, std::vec
|
||||||
}
|
}
|
||||||
|
|
||||||
trace->SetData( aX, aY );
|
trace->SetData( aX, aY );
|
||||||
|
trace->SetSweepCount( aSweepCount );
|
||||||
|
trace->SetSweepSize( aSweepSize );
|
||||||
|
|
||||||
if( ( trace->GetType() & SPT_AC_PHASE ) || ( trace->GetType() & SPT_CURRENT ) )
|
if( ( trace->GetType() & SPT_AC_PHASE ) || ( trace->GetType() & SPT_CURRENT ) )
|
||||||
trace->SetScale( m_axis_x, m_axis_y2 );
|
trace->SetScale( m_axis_x, m_axis_y2 );
|
||||||
|
|
|
@ -351,7 +351,8 @@ public:
|
||||||
|
|
||||||
TRACE* GetOrAddTrace( const wxString& aVectorName, int aType );
|
TRACE* GetOrAddTrace( const wxString& aVectorName, int aType );
|
||||||
|
|
||||||
void SetTraceData( TRACE* aTrace, std::vector<double>& aX, std::vector<double>& aY );
|
void SetTraceData( TRACE* aTrace, std::vector<double>& aX, std::vector<double>& aY,
|
||||||
|
int aSweepCount, size_t aSweepSize );
|
||||||
|
|
||||||
bool DeleteTrace( const wxString& aVectorName, int aTraceType );
|
bool DeleteTrace( const wxString& aVectorName, int aTraceType );
|
||||||
void DeleteTrace( TRACE* aTrace );
|
void DeleteTrace( TRACE* aTrace );
|
||||||
|
|
|
@ -1744,46 +1744,24 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp
|
||||||
wxFAIL_MSG( wxT( "Unhandled plot type" ) );
|
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;
|
SPICE_DC_PARAMS source1, source2;
|
||||||
|
int sweepCount = 1;
|
||||||
|
size_t sweepSize = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
if( simType == ST_DC
|
if( simType == ST_DC
|
||||||
&& circuitModel()->ParseDCCommand( aPlotTab->GetSimCommand(), &source1, &source2 )
|
&& circuitModel()->ParseDCCommand( aPlotTab->GetSimCommand(), &source1, &source2 )
|
||||||
&& !source2.m_source.IsEmpty() )
|
&& !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_vend - source2.m_vstart ) / source2.m_vincrement;
|
||||||
SPICE_VALUE v = source2.m_vstart;
|
|
||||||
|
|
||||||
size_t offset = 0;
|
sweepCount = KiROUND( v.ToDouble() ) + 1;
|
||||||
size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble();
|
sweepSize = aDataX->size() / sweepCount;
|
||||||
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<double> sub_x( aDataX->begin() + offset,
|
|
||||||
aDataX->begin() + offset + inner );
|
|
||||||
std::vector<double> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if( TRACE* trace = aPlotTab->GetOrAddTrace( aVectorName, aTraceType ) )
|
|
||||||
|
if( TRACE* trace = aPlotTab->GetOrAddTrace( aVectorName, aTraceType ) )
|
||||||
{
|
{
|
||||||
if( data_y.size() >= size )
|
if( data_y.size() >= size )
|
||||||
aPlotTab->SetTraceData( trace, *aDataX, data_y );
|
aPlotTab->SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -550,6 +550,7 @@ public:
|
||||||
* Override this function in your implementation.
|
* Override this function in your implementation.
|
||||||
*/
|
*/
|
||||||
virtual void Rewind() = 0;
|
virtual void Rewind() = 0;
|
||||||
|
virtual void SetSweepWindow( int aSweepIdx ) { Rewind(); }
|
||||||
|
|
||||||
/** Get locus value for next N.
|
/** Get locus value for next N.
|
||||||
* Override this function in your implementation.
|
* Override this function in your implementation.
|
||||||
|
@ -559,6 +560,7 @@ public:
|
||||||
virtual bool GetNextXY( double& x, double& y ) = 0;
|
virtual bool GetNextXY( double& x, double& y ) = 0;
|
||||||
|
|
||||||
virtual size_t GetCount() const = 0;
|
virtual size_t GetCount() const = 0;
|
||||||
|
virtual int GetSweepCount() const { return 1; }
|
||||||
|
|
||||||
/** Layer plot handler.
|
/** Layer plot handler.
|
||||||
* This implementation will plot the locus in the visible area and put a label according to
|
* 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<double>& xs, const std::vector<double>& ys );
|
virtual void SetData( const std::vector<double>& xs, const std::vector<double>& ys );
|
||||||
|
|
||||||
|
void SetSweepCount( int aSweepCount ) { m_sweepCount = aSweepCount; }
|
||||||
|
void SetSweepSize( size_t aSweepSize ) { m_sweepSize = aSweepSize; }
|
||||||
|
|
||||||
/** Clears all the data, leaving the layer empty.
|
/** Clears all the data, leaving the layer empty.
|
||||||
* @sa SetData
|
* @sa SetData
|
||||||
*/
|
*/
|
||||||
|
@ -1429,18 +1434,20 @@ protected:
|
||||||
*/
|
*/
|
||||||
std::vector<double> m_xs, m_ys;
|
std::vector<double> m_xs, m_ys;
|
||||||
|
|
||||||
/** The internal counter for the "GetNextXY" interface
|
size_t m_index; // internal counter for the "GetNextXY" interface
|
||||||
*/
|
size_t m_sweepWindow; // last m_index of the current sweep
|
||||||
size_t m_index;
|
|
||||||
|
|
||||||
/** Loaded at SetData
|
/** Loaded at SetData
|
||||||
*/
|
*/
|
||||||
double m_minX, m_maxX, m_minY, m_maxY;
|
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<size_t>::max(); // data-points in each sweep
|
||||||
|
|
||||||
/** Rewind value enumeration with mpFXY::GetNextXY.
|
/** Rewind value enumeration with mpFXY::GetNextXY.
|
||||||
* Overridden in this implementation.
|
* Overridden in this implementation.
|
||||||
*/
|
*/
|
||||||
void Rewind() override;
|
void Rewind() override;
|
||||||
|
void SetSweepWindow( int aSweepIdx ) override;
|
||||||
|
|
||||||
/** Get locus value for next N.
|
/** Get locus value for next N.
|
||||||
* Overridden in this implementation.
|
* Overridden in this implementation.
|
||||||
|
@ -1449,7 +1456,8 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool GetNextXY( double& x, double& y ) override;
|
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:
|
public:
|
||||||
/** Returns the actual minimum X data (loaded in SetData).
|
/** Returns the actual minimum X data (loaded in SetData).
|
||||||
|
|
Loading…
Reference in New Issue