KiCad PCB EDA Suite
sim_plot_panel.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 CERN
5  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * https://www.gnu.org/licenses/gpl-3.0.html
21  * or you may search the http://www.gnu.org website for the version 3 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include "sim_plot_colors.h"
27 #include "sim_plot_panel.h"
28 #include "sim_plot_frame.h"
29 
30 #include <algorithm>
31 #include <limits>
32 
33 #include <wx/regex.h>
34 
35 static wxString formatFloat( double x, int nDigits )
36 {
37  wxString rv, fmt;
38 
39  if( nDigits )
40  {
41  fmt.Printf( "%%.0%df", nDigits );
42  }
43  else
44  {
45  fmt = wxT( "%.0f" );
46  }
47 
48  rv.Printf( fmt, x );
49 
50  return rv;
51 }
52 
53 
54 static void getSISuffix( double x, const wxString& unit, int& power, wxString& suffix )
55 {
56  const int n_powers = 11;
57 
58  const struct
59  {
60  double exponent;
61  char suffix;
62  } powers[] =
63  {
64  { -18, 'a' },
65  { -15, 'f' },
66  { -12, 'p' },
67  { -9, 'n' },
68  { -6, 'u' },
69  { -3, 'm' },
70  { 0, 0 },
71  { 3, 'k' },
72  { 6, 'M' },
73  { 9, 'G' },
74  { 12, 'T' },
75  { 14, 'P' }
76  };
77 
78  power = 0;
79  suffix = unit;
80 
81  if( x == 0.0 )
82  return;
83 
84  for( int i = 0; i < n_powers - 1; i++ )
85  {
86  double r_cur = pow( 10, powers[i].exponent );
87 
88  if( fabs( x ) >= r_cur && fabs( x ) < r_cur * 1000.0 )
89  {
90  power = powers[i].exponent;
91 
92  if( powers[i].suffix )
93  suffix = wxString( powers[i].suffix ) + unit;
94  else
95  suffix = unit;
96 
97  return;
98  }
99  }
100 }
101 
102 
103 static int countDecimalDigits( double x, int maxDigits )
104 {
105  if( std::isnan( x ) )
106  {
107  // avoid trying to count the decimals of NaN
108  return 0;
109  }
110 
111  int64_t k = (int)( ( x - floor( x ) ) * pow( 10.0, (double) maxDigits ) );
112  int n = 0;
113 
114  while( k && ( ( k % 10LL ) == 0LL || ( k % 10LL ) == 9LL ) )
115  {
116  k /= 10LL;
117  }
118 
119  n = 0;
120 
121  while( k != 0LL )
122  {
123  n++;
124  k /= 10LL;
125  }
126 
127  return n;
128 }
129 
130 
131 template <typename parent>
132 class LIN_SCALE : public parent
133 {
134 private:
135  const wxString m_unit;
136 
137 public:
138  LIN_SCALE( wxString name, wxString unit, int flags ) : parent( name, flags ), m_unit( unit ){};
139 
140  void formatLabels() override
141  {
142  double maxVis = parent::AbsVisibleMaxValue();
143 
144  wxString suffix;
145  int power, digits = 0;
146  int constexpr DIGITS = 3;
147 
148  getSISuffix( maxVis, m_unit, power, suffix );
149 
150  double sf = pow( 10.0, power );
151 
152  for( auto& l : parent::TickLabels() )
153  {
154  int k = countDecimalDigits( l.pos / sf, DIGITS );
155 
156  digits = std::max( digits, k );
157  }
158 
159  for( auto& l : parent::TickLabels() )
160  {
161  l.label = formatFloat( l.pos / sf, digits ) + suffix;
162  l.visible = true;
163  }
164  }
165 };
166 
167 
168 template <typename parent>
169 class LOG_SCALE : public parent
170 {
171 private:
172  const wxString m_unit;
173 
174 public:
175  LOG_SCALE( wxString name, wxString unit, int flags ) : parent( name, flags ), m_unit( unit ){};
176 
177  void formatLabels() override
178  {
179  wxString suffix;
180  int power;
181 
182  for( auto& l : parent::TickLabels() )
183  {
184  getSISuffix( l.pos, m_unit, power, suffix );
185  double sf = pow( 10.0, power );
186  int k = countDecimalDigits( l.pos / sf, 3 );
187 
188  l.label = formatFloat( l.pos / sf, k ) + suffix;
189  l.visible = true;
190  }
191  }
192 };
193 
194 
195 void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow )
196 {
197  if( !m_window )
198  m_window = &aWindow;
199 
200  if( !m_visible )
201  return;
202 
203  const auto& dataX = m_trace->GetDataX();
204  const auto& dataY = m_trace->GetDataY();
205 
206  if( dataX.size() <= 1 )
207  return;
208 
209  if( m_updateRequired )
210  {
211  m_coords.x = m_trace->s2x( aWindow.p2x( m_dim.x ) );
212 
213  // Find the closest point coordinates
214  auto maxXIt = std::upper_bound( dataX.begin(), dataX.end(), m_coords.x );
215  int maxIdx = maxXIt - dataX.begin();
216  int minIdx = maxIdx - 1;
217 
218  // Out of bounds checks
219  if( minIdx < 0 )
220  {
221  minIdx = 0;
222  maxIdx = 1;
223  m_coords.x = dataX[0];
224  }
225  else if( maxIdx >= (int) dataX.size() )
226  {
227  maxIdx = dataX.size() - 1;
228  minIdx = maxIdx - 1;
229  m_coords.x = dataX[maxIdx];
230  }
231 
232  const double leftX = dataX[minIdx];
233  const double rightX = dataX[maxIdx];
234  const double leftY = dataY[minIdx];
235  const double rightY = dataY[maxIdx];
236 
237  // Linear interpolation
238  m_coords.y = leftY + ( rightY - leftY ) / ( rightX - leftX ) * ( m_coords.x - leftX );
239  m_updateRequired = false;
240 
241  // Notify the parent window about the changes
242  wxQueueEvent( aWindow.GetParent(), new wxCommandEvent( EVT_SIM_CURSOR_UPDATE ) );
243  }
244  else
245  {
246  m_updateRef = true;
247  }
248 
249  if( m_updateRef )
250  {
251  UpdateReference();
252  m_updateRef = false;
253  }
254 
255  // Line length in horizontal and vertical dimensions
256  const wxPoint cursorPos( aWindow.x2p( m_trace->x2s( m_coords.x ) ),
257  aWindow.y2p( m_trace->y2s( m_coords.y ) ) );
258 
259  wxCoord leftPx = m_drawOutsideMargins ? 0 : aWindow.GetMarginLeft();
260  wxCoord rightPx = m_drawOutsideMargins ? aWindow.GetScrX() : aWindow.GetScrX() - aWindow.GetMarginRight();
261  wxCoord topPx = m_drawOutsideMargins ? 0 : aWindow.GetMarginTop();
262  wxCoord bottomPx = m_drawOutsideMargins ? aWindow.GetScrY() : aWindow.GetScrY() - aWindow.GetMarginBottom();
263 
264  wxPen pen = GetPen();
265  pen.SetStyle( m_continuous ? wxPENSTYLE_SOLID : wxPENSTYLE_LONG_DASH );
266  aDC.SetPen( pen );
267 
268  if( topPx < cursorPos.y && cursorPos.y < bottomPx )
269  aDC.DrawLine( leftPx, cursorPos.y, rightPx, cursorPos.y );
270 
271  if( leftPx < cursorPos.x && cursorPos.x < rightPx )
272  aDC.DrawLine( cursorPos.x, topPx, cursorPos.x, bottomPx );
273 }
274 
275 
276 bool CURSOR::Inside( wxPoint& aPoint )
277 {
278  if( !m_window )
279  return false;
280 
281  return ( std::abs( (double) aPoint.x - m_window->x2p( m_trace->x2s( m_coords.x ) ) ) <= DRAG_MARGIN )
282  || ( std::abs( (double) aPoint.y - m_window->y2p( m_trace->y2s( m_coords.y ) ) ) <= DRAG_MARGIN );
283 }
284 
285 
287 {
288  if( !m_window )
289  return;
290 
291  m_reference.x = m_window->x2p( m_trace->x2s( m_coords.x ) );
292  m_reference.y = m_window->y2p( m_trace->y2s( m_coords.y ) );
293 }
294 
295 
296 SIM_PLOT_PANEL::SIM_PLOT_PANEL( wxString aCommand, wxWindow* parent, SIM_PLOT_FRAME* aMainFrame,
297  wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
298  : SIM_PANEL_BASE( aCommand, parent, id, pos, size, style, name ),
299  m_axis_x( nullptr ),
300  m_axis_y1( nullptr ),
301  m_axis_y2( nullptr ),
302  m_dotted_cp( false ),
303  m_masterFrame( aMainFrame )
304 {
305  m_sizer = new wxBoxSizer( wxVERTICAL );
306  m_plotWin = new mpWindow( this, wxID_ANY, pos, size, style );
307 
308  m_plotWin->LimitView( true );
309  m_plotWin->SetMargins( 50, 80, 50, 80 );
310 
312 
313  switch( GetType() )
314  {
315  case ST_AC:
316  m_axis_x = new LOG_SCALE<mpScaleXLog>( _( "Frequency" ), wxT( "Hz" ), mpALIGN_BOTTOM );
317  m_axis_y1 = new LIN_SCALE<mpScaleY>( _( "Gain" ), wxT( "dBV" ), mpALIGN_LEFT );
318  m_axis_y2 = new LIN_SCALE<mpScaleY>( _( "Phase" ), wxT( "\u00B0" ),
319  mpALIGN_RIGHT ); // degree sign
321  break;
322 
323  case ST_DC:
324  prepareDCAxes();
325  break;
326 
327  case ST_NOISE:
328  m_axis_x = new LOG_SCALE<mpScaleXLog>( _( "Frequency" ), wxT( "Hz" ), mpALIGN_BOTTOM );
329  m_axis_y1 = new mpScaleY( _( "noise [(V or A)^2/Hz]" ), mpALIGN_LEFT );
330  break;
331 
332  case ST_TRANSIENT:
333  m_axis_x = new LIN_SCALE<mpScaleX>( _( "Time" ), wxT( "s" ), mpALIGN_BOTTOM );
334  m_axis_y1 = new LIN_SCALE<mpScaleY>( _( "Voltage" ), wxT( "V" ), mpALIGN_LEFT );
335  m_axis_y2 = new LIN_SCALE<mpScaleY>( _( "Current" ), wxT( "A" ), mpALIGN_RIGHT );
337  break;
338 
339  default:
340  // suppress warnings
341  break;
342  }
343 
344  if( m_axis_x )
345  {
346  m_axis_x->SetTicks( false );
348 
350  }
351 
352  if( m_axis_y1 )
353  {
354  m_axis_y1->SetTicks( false );
357  }
358 
359  if( m_axis_y2 )
360  {
361  m_axis_y2->SetTicks( false );
364  }
365 
366  // a mpInfoLegend displays le name of traces on the left top panel corner:
367  m_legend = new mpInfoLegend( wxRect( 0, 40, 200, 40 ), wxTRANSPARENT_BRUSH );
368  m_legend->SetVisible( false );
370 
371  m_plotWin->EnableDoubleBuffer( true );
372  m_plotWin->UpdateAll();
373 
374  m_sizer->Add( m_plotWin, 1, wxALL | wxEXPAND, 1 );
375  SetSizer( m_sizer );
376 }
377 
378 
380 {
381  // ~mpWindow destroys all the added layers, so there is no need to destroy m_traces contents
382 }
383 
384 
386 {
387  wxRegEx simCmd( "^.dc[[:space:]]+([[:alnum:]]+\\M).*", wxRE_ADVANCED | wxRE_ICASE );
388 
389  if( simCmd.Matches( m_simCommand ) )
390  {
391  switch( static_cast<char>( simCmd.GetMatch( m_simCommand.Lower(), 1 ).GetChar( 0 ) ) )
392  {
393  case 'v':
394  m_axis_x =
395  new LIN_SCALE<mpScaleX>( _( "Voltage (swept)" ), wxT( "V" ), mpALIGN_BOTTOM );
396  break;
397  case 'i':
398  m_axis_x =
399  new LIN_SCALE<mpScaleX>( _( "Current (swept)" ), wxT( "A" ), mpALIGN_BOTTOM );
400  break;
401  case 'r':
402  m_axis_x = new LIN_SCALE<mpScaleX>( _( "Resistance (swept)" ), wxT( "\u03A9" ),
403  mpALIGN_BOTTOM );
404  break;
405  case 't':
406  m_axis_x = new LIN_SCALE<mpScaleX>( _( "Temperature (swept)" ), wxT( "\u00B0C" ),
407  mpALIGN_BOTTOM );
408  break;
409  }
410 
411  m_axis_y1 = new LIN_SCALE<mpScaleY>( _( "Voltage (measured)" ), wxT( "V" ), mpALIGN_LEFT );
412  m_axis_y2 = new LIN_SCALE<mpScaleY>( _( "Current" ), wxT( "A" ), mpALIGN_RIGHT );
413  }
414 }
415 
416 
418 {
419  // Update bg and fg colors:
423 
424  // Update color of all traces
425  for( auto& t : m_traces )
426  if( t.second->GetCursor() )
427  t.second->GetCursor()->SetPen(
429 
430  m_plotWin->UpdateAll();
431 }
432 
433 
435 {
436  int flags = trace->GetFlags();
437  wxPenStyle penStyle = ( ( flags & SPT_AC_PHASE || flags & SPT_CURRENT ) && m_dotted_cp ) ?
438  wxPENSTYLE_DOT :
439  wxPENSTYLE_SOLID;
440  trace->SetPen( wxPen( trace->GetTraceColour(), 2, penStyle ) );
441 }
442 
443 
444 bool SIM_PLOT_PANEL::AddTrace( const wxString& aName, int aPoints,
445  const double* aX, const double* aY, SIM_PLOT_TYPE aFlags )
446 {
447  TRACE* trace = NULL;
448 
449  // Find previous entry, if there is one
450  auto prev = m_traces.find( aName );
451  bool addedNewEntry = ( prev == m_traces.end() );
452 
453  if( addedNewEntry )
454  {
455  if( GetType() == ST_TRANSIENT )
456  {
457  bool hasVoltageTraces = false;
458 
459  for( const auto& tr : m_traces )
460  {
461  if( !( tr.second->GetFlags() & SPT_CURRENT ) )
462  {
463  hasVoltageTraces = true;
464  break;
465  }
466  }
467 
468  if( !hasVoltageTraces )
469  m_axis_y2->SetMasterScale( nullptr );
470  else
472  }
473 
474  // New entry
475  trace = new TRACE( aName );
477  UpdateTraceStyle( trace );
478  m_traces[aName] = trace;
479 
480  // It is a trick to keep legend & coords always on the top
481  for( mpLayer* l : m_topLevel )
482  m_plotWin->DelLayer( l );
483 
484  m_plotWin->AddLayer( (mpLayer*) trace );
485 
486  for( mpLayer* l : m_topLevel )
487  m_plotWin->AddLayer( l );
488  }
489  else
490  {
491  trace = prev->second;
492  }
493 
494  std::vector<double> tmp( aY, aY + aPoints );
495 
496  if( GetType() == ST_AC )
497  {
498  if( aFlags & SPT_AC_PHASE )
499  {
500  for( int i = 0; i < aPoints; i++ )
501  tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees
502  }
503  else
504  {
505  for( int i = 0; i < aPoints; i++ )
506  tmp[i] = 20 * log( tmp[i] ) / log( 10.0 ); // convert to dB
507  }
508  }
509 
510  trace->SetData( std::vector<double>( aX, aX + aPoints ), tmp );
511 
512  if( ( aFlags & SPT_AC_PHASE ) || ( aFlags & SPT_CURRENT ) )
513  trace->SetScale( m_axis_x, m_axis_y2 );
514  else
515  trace->SetScale( m_axis_x, m_axis_y1 );
516 
517  trace->SetFlags( aFlags );
518 
519  m_plotWin->UpdateAll();
520 
521  return addedNewEntry;
522 }
523 
524 
525 bool SIM_PLOT_PANEL::DeleteTrace( const wxString& aName )
526 {
527  auto it = m_traces.find( aName );
528 
529  if( it != m_traces.end() )
530  {
531  TRACE* trace = it->second;
532  m_traces.erase( it );
533 
534  if( CURSOR* cursor = trace->GetCursor() )
535  m_plotWin->DelLayer( cursor, true );
536 
537  m_plotWin->DelLayer( trace, true, true );
538  ResetScales();
539 
540  return true;
541  }
542 
543  return false;
544 }
545 
546 
548 {
549  for( auto& t : m_traces )
550  {
551  DeleteTrace( t.first );
552  }
553 
554  m_traces.clear();
555 }
556 
557 
558 bool SIM_PLOT_PANEL::HasCursorEnabled( const wxString& aName ) const
559 {
560  TRACE* t = GetTrace( aName );
561 
562  return t ? t->HasCursor() : false;
563 }
564 
565 
566 void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, bool aEnable )
567 {
568  TRACE* t = GetTrace( aName );
569 
570  if( t == nullptr || t->HasCursor() == aEnable )
571  return;
572 
573  if( aEnable )
574  {
575  CURSOR* c = new CURSOR( t, this );
576  int plotCenter = GetPlotWin()->GetMarginLeft()
578  - GetPlotWin()->GetMarginRight() )
579  / 2;
580  c->SetX( plotCenter );
582  t->SetCursor( c );
583  m_plotWin->AddLayer( c );
584  }
585  else
586  {
587  CURSOR* c = t->GetCursor();
588  t->SetCursor( NULL );
589  m_plotWin->DelLayer( c, true );
590  }
591 
592  // Notify the parent window about the changes
593  wxQueueEvent( GetParent(), new wxCommandEvent( EVT_SIM_CURSOR_UPDATE ) );
594 }
595 
596 
598 {
599  if( m_axis_x )
601 
602  if( m_axis_y1 )
604 
605  if( m_axis_y2 )
607 
608  for( auto t : m_traces )
609  t.second->UpdateScales();
610 }
611 
612 
613 wxDEFINE_EVENT( EVT_SIM_CURSOR_UPDATE, wxCommandEvent );
void Plot(wxDC &aDC, mpWindow &aWindow) override
Plot method.
double s2x(double plotCoordX) const
Definition: mathplot.cpp:3955
#define mpALIGN_LEFT
Aligns label to the left.
Definition: mathplot.h:482
class WXDLLIMPEXP_MATHPLOT mpWindow
Definition: mathplot.h:109
wxDEFINE_EVENT(EVT_SIM_CURSOR_UPDATE, wxCommandEvent)
bool m_continuous
Definition: mathplot.h:319
static wxString formatFloat(double x, int nDigits)
static constexpr int DRAG_MARGIN
mpWindow * m_plotWin
void SetNameAlign(int align)
Definition: mathplot.h:710
const TRACE * m_trace
wxRealPoint m_coords
const wxString m_unit
mpWindow * GetPlotWin() const
mpScaleY * m_axis_y1
double p2x(wxCoord pixelCoordX)
Converts mpWindow (screen) pixel coordinates into graph (floating point) coordinates,...
Definition: mathplot.h:1189
bool HasCursor() const
bool DelLayer(mpLayer *layer, bool alsoDeleteObject=false, bool refreshDisplay=true)
Remove a plot layer from the canvas.
Definition: mathplot.cpp:2443
virtual void SetScale(mpScaleBase *scaleX, mpScaleBase *scaleY)
Definition: mathplot.cpp:3936
int GetXScreen(void) const
Definition: mathplot.h:1136
int GetMarginBottom()
Definition: mathplot.h:1372
const std::vector< double > & GetDataX() const
mpScaleXBase * m_axis_x
bool HasCursorEnabled(const wxString &aName) const
Toggles cursor for a particular trace.
wxColour GetTraceColour()
void SetMasterScale(mpScaleY *masterScale)
Definition: mathplot.h:980
double y2s(double y) const
Definition: mathplot.cpp:3973
static int countDecimalDigits(double x, int maxDigits)
#define mpALIGN_RIGHT
Aligns label to the right.
Definition: mathplot.h:478
bool AddLayer(mpLayer *layer, bool refreshDisplay=true)
Add a plot layer to the canvas.
Definition: mathplot.cpp:2426
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.
Definition: mathplot.h:278
void formatLabels() override
void UpdateTraceStyle(TRACE *trace)
void UpdateReference() override
Updates the rectangle reference point.
void SetFlags(int aFlags)
void EnableDoubleBuffer(bool enabled)
Enable/disable the double-buffering of the window, eliminating the flicker (default=disabled).
Definition: mathplot.h:1209
bool m_visible
Definition: mathplot.h:323
bool DeleteTrace(const wxString &aName)
void UpdateAll()
Refresh display.
Definition: mathplot.cpp:2750
void EnableCursor(const wxString &aName, bool aEnable)
Resets scale ranges to fit the current traces.
wxColour GenerateColor(std::map< wxString, TRACE * > aTraces)
SIM_PLOT_COLORS m_colors
wxCoord y2p(double y)
Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates,...
Definition: mathplot.h:1204
void ResetDataRange()
Definition: mathplot.h:760
#define NULL
void SetVisible(bool show)
Sets layer visibility.
Definition: mathplot.h:303
int GetMarginTop()
Definition: mathplot.h:1368
static void getSISuffix(double x, const wxString &unit, int &power, wxString &suffix)
std::vector< mpLayer * > m_topLevel
std::map< wxString, TRACE * > m_traces
int GetScrX(void) const
Get current view's X dimension in device context units.
Definition: mathplot.h:1135
void SetMargins(int top, int right, int bottom, int left)
Set window margins, creating a blank area where some kinds of layers cannot draw.
Definition: mathplot.cpp:3038
class WXDLLIMPEXP_MATHPLOT mpScaleY
Definition: mathplot.h:108
bool AddTrace(const wxString &aName, int aPoints, const double *aX, const double *aY, SIM_PLOT_TYPE aFlags)
void SetColourTheme(const wxColour &bgColour, const wxColour &drawColour, const wxColour &axesColour)
Set Color theme.
Definition: mathplot.cpp:3108
mpScaleY * m_axis_y2
void SetTicks(bool enable)
Set X axis ticks or grid.
Definition: mathplot.h:715
Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
void ResetScales()
Update trace line style.
void formatLabels() override
bool m_updateRequired
wxRect m_dim
Definition: mathplot.h:393
Implementing SIM_PLOT_FRAME_BASE.
mpWindow * m_window
bool m_drawOutsideMargins
Definition: mathplot.h:321
wxColour GetPlotColor(enum COLOR_SET aColorId)
int GetMarginRight()
Definition: mathplot.h:1370
wxPoint m_reference
Definition: mathplot.h:397
int GetMarginLeft()
Definition: mathplot.h:1374
SIM_TYPE GetType() const
const wxString m_simCommand
double x2s(double x) const
Definition: mathplot.cpp:3967
void UpdatePlotColors()
Update plot colors
wxCoord x2p(double x)
Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates,...
Definition: mathplot.h:1199
const char * name
Definition: DXF_plotter.cpp:59
int GetFlags() const
#define _(s)
Definition: 3d_actions.cpp:33
mpInfoLegend * m_legend
void SetX(int aX)
CURSOR * GetCursor() const
const wxString m_unit
void LimitView(bool aEnable)
Limit zooming & panning to the area used by the plots.
Definition: mathplot.h:1426
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.
Definition: mathplot.h:1047
LOG_SCALE(wxString name, wxString unit, int flags)
void SetTicks(bool ticks)
Set Y axis ticks or grid.
Definition: mathplot.h:970
#define mpALIGN_BOTTOM
Aligns label to the bottom.
Definition: mathplot.h:486
const std::vector< double > & GetDataY() const
LIN_SCALE(wxString name, wxString unit, int flags)
SIM_PLOT_PANEL(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)
Implements the legend to be added to the plot This layer allows you to add a legend to describe the p...
Definition: mathplot.h:438
void SetCursor(CURSOR *aCursor)
SIM_PLOT_TYPE
Definition: sim_types.h:46
bool m_updateRef
const wxPen & GetPen() const
Get pen set for this layer.
Definition: mathplot.h:249
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.
wxBoxSizer * m_sizer
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.
Definition: mathplot.h:1144