42 fmt.Printf( wxT(
"%%.0%df" ), nDigits );
55 static void getSISuffix(
double x,
const wxString& unit,
int& power, wxString& suffix )
57 const int n_powers = 11;
85 for(
int i = 0; i < n_powers - 1; i++ )
87 double r_cur = pow( 10, powers[i].exponent );
89 if( fabs( x ) >= r_cur && fabs( x ) < r_cur * 1000.0 )
91 power = powers[i].exponent;
93 if( powers[i].suffix )
94 suffix = wxString( powers[i].suffix ) + unit;
106 if( std::isnan( x ) )
112 int64_t k = (int)( ( x - floor( x ) ) * pow( 10.0, (
double) maxDigits ) );
115 while( k && ( ( k % 10LL ) == 0LL || ( k % 10LL ) == 9LL ) )
132 template <
typename parent>
140 double maxVis = parent::AbsVisibleMaxValue();
143 int power, digits = 0;
144 int constexpr DIGITS = 3;
148 double sf = pow( 10.0, power );
150 for(
auto& l : parent::TickLabels() )
154 digits = std::max( digits, k );
157 for(
auto& l : parent::TickLabels() )
159 l.label =
formatFloat( l.pos / sf, digits ) + suffix;
169 template <
typename parent>
180 for(
auto& l : parent::TickLabels() )
183 double sf = pow( 10.0, power );
207 if( dataX.size() <= 1 )
215 auto maxXIt = std::upper_bound( dataX.begin(), dataX.end(),
m_coords.x );
216 int maxIdx = maxXIt - dataX.begin();
217 int minIdx = maxIdx - 1;
226 else if( maxIdx >= (
int) dataX.size() )
228 maxIdx = dataX.size() - 1;
233 const double leftX = dataX[minIdx];
234 const double rightX = dataX[maxIdx];
235 const double leftY = dataY[minIdx];
236 const double rightY = dataY[maxIdx];
239 m_coords.y = leftY + ( rightY - leftY ) / ( rightX - leftX ) * (
m_coords.x - leftX );
243 wxQueueEvent( aWindow.GetParent(),
new wxCommandEvent( EVT_SIM_CURSOR_UPDATE ) );
268 pen.SetStyle(
m_continuous ? wxPENSTYLE_SOLID : wxPENSTYLE_LONG_DASH );
271 if( topPx < cursorPos.y && cursorPos.y < bottomPx )
272 aDC.DrawLine( leftPx, cursorPos.y, rightPx, cursorPos.y );
274 if( leftPx < cursorPos.x && cursorPos.x < rightPx )
275 aDC.DrawLine( cursorPos.x, topPx, cursorPos.x, bottomPx );
284 return ( std::abs( (
double) aPoint.x -
286 || ( std::abs( (
double) aPoint.y -
303 const wxSize& size,
long style,
const wxString&
name )
306 m_axis_y1( nullptr ),
307 m_axis_y2( nullptr ),
308 m_dotted_cp( false ),
309 m_masterFrame( aMainFrame )
311 m_sizer =
new wxBoxSizer( wxVERTICAL );
404 if( sim_cmd.StartsWith(
".dc", &rem ) )
412 ch = rem.GetChar( 0 );
454 if( t.second->GetCursor() )
455 t.second->GetCursor()->SetPen(
474 const wxString& aParam )
476 TRACE* trace =
nullptr;
477 wxString
name = aTitle;
483 bool addedNewEntry = ( prev ==
m_traces.end() );
489 bool hasVoltageTraces =
false;
495 hasVoltageTraces =
true;
500 if( !hasVoltageTraces )
507 trace =
new TRACE( aName, aType, aParam );
523 trace = prev->second;
526 std::vector<double> tmp( aY, aY + aPoints );
532 for(
int i = 0; i < aPoints; i++ )
533 tmp[i] = tmp[i] * 180.0 / M_PI;
537 for(
int i = 0; i < aPoints; i++ )
541 tmp[i] = 20 * log( tmp[i] ) / log( 10.0 );
546 trace->
SetData( std::vector<double>( aX, aX + aPoints ), tmp );
555 return addedNewEntry;
565 TRACE* trace = it->second;
604 if( t ==
nullptr || t->
HasCursor() == aEnable )
614 c->
SetX( plotCenter );
627 wxQueueEvent( GetParent(),
new wxCommandEvent( EVT_SIM_CURSOR_UPDATE ) );
643 t.second->UpdateScales();
bool addTrace(const wxString &aTitle, const wxString &aName, int aPoints, const double *aX, const double *aY, SIM_PLOT_TYPE aType, const wxString &aParam)
void Plot(wxDC &aDC, mpWindow &aWindow) override
Plot method.
double s2x(double plotCoordX) const
#define mpALIGN_LEFT
Aligns label to the left.
class WXDLLIMPEXP_MATHPLOT mpWindow
int GetMarginBottom() const
wxDEFINE_EVENT(EVT_SIM_CURSOR_UPDATE, wxCommandEvent)
static wxString formatFloat(double x, int nDigits)
static constexpr int DRAG_MARGIN
void SetNameAlign(int align)
mpWindow * GetPlotWin() const
double p2x(wxCoord pixelCoordX)
Converts mpWindow (screen) pixel coordinates into graph (floating point) coordinates,...
bool DelLayer(mpLayer *layer, bool alsoDeleteObject=false, bool refreshDisplay=true)
Remove a plot layer from the canvas.
virtual void SetScale(mpScaleBase *scaleX, mpScaleBase *scaleY)
int GetXScreen(void) const
const std::vector< double > & GetDataX() const
bool HasCursorEnabled(const wxString &aName) const
Toggle cursor for a particular trace.
wxColour GetTraceColour()
void SetMasterScale(mpScaleY *masterScale)
double y2s(double y) const
static int countDecimalDigits(double x, int maxDigits)
#define mpALIGN_RIGHT
Aligns label to the right.
bool AddLayer(mpLayer *layer, bool refreshDisplay=true)
Add a plot layer to the canvas.
virtual ~SIM_PLOT_PANEL()
set the pointer to the sim plot frame
TRACE * GetTrace(const wxString &aName) const
void SetPen(wxPen pen)
Set layer pen.
void formatLabels() override
void UpdateTraceStyle(TRACE *trace)
void UpdateReference() override
Updates the rectangle reference point.
void EnableDoubleBuffer(bool enabled)
Enable/disable the double-buffering of the window, eliminating the flicker (default=disabled).
void UpdateAll()
Refresh display.
void EnableCursor(const wxString &aName, bool aEnable)
Reset scale ranges to fit the current traces.
int GetMarginRight() const
wxColour GenerateColor(std::map< wxString, TRACE * > aTraces)
wxCoord y2p(double y)
Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates,...
void SetVisible(bool show)
Sets layer visibility.
static void getSISuffix(double x, const wxString &unit, int &power, wxString &suffix)
std::vector< mpLayer * > m_topLevel
std::map< wxString, TRACE * > m_traces
const wxString & getSimCommand() const
int GetScrX(void) const
Get current view's X dimension in device context units.
void SetMargins(int top, int right, int bottom, int left)
Set window margins, creating a blank area where some kinds of layers cannot draw.
class WXDLLIMPEXP_MATHPLOT mpScaleY
void SetColourTheme(const wxColour &bgColour, const wxColour &drawColour, const wxColour &axesColour)
Set Color theme.
SIM_PLOT_TYPE GetType() const
void SetTicks(bool enable)
Set X axis ticks or grid.
Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
void updateAxes()
Create/Ensure axes are available for plotting
void ResetScales()
Update trace line style.
void formatLabels() override
Implementing SIM_PLOT_FRAME_BASE.
bool m_drawOutsideMargins
wxColour GetPlotColor(enum COLOR_SET aColorId)
double x2s(double x) const
void UpdatePlotColors()
Update plot colors
SIM_PLOT_PANEL(const wxString &aCommand, wxWindow *parent, SIM_PLOT_FRAME *aMainFrame, wxWindowID id, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0, const wxString &name=wxPanelNameStr)
wxCoord x2p(double x)
Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates,...
bool deleteTrace(const wxString &aName)
CURSOR * GetCursor() const
void LimitView(bool aEnable)
Limit zooming & panning to the area used by the plots.
void SetData(const std::vector< double > &aX, const std::vector< double > &aY) override
Assigns new data set for the trace.
Canvas for plotting mpLayer implementations.
LOG_SCALE(wxString name, wxString unit, int flags)
void SetTicks(bool ticks)
Set Y axis ticks or grid.
#define mpALIGN_BOTTOM
Aligns label to the bottom.
const std::vector< double > & GetDataY() const
int GetMarginLeft() const
LIN_SCALE(wxString name, wxString unit, int flags)
Implements the legend to be added to the plot This layer allows you to add a legend to describe the p...
void SetCursor(CURSOR *aCursor)
const wxPen & GetPen() const
Get pen set for this layer.
Class is responsible for providing colors for traces on simulation plot.
bool Inside(wxPoint &aPoint) override
Checks whether a point is inside the info box rectangle.
Cursor attached to a trace to follow its values:
void SetTraceColour(wxColour aColour)
int GetScrY(void) const
Get current view's Y dimension in device context units.