KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sim_plot_tab.h
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-2023 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Tomasz Wlostowski <[email protected]>
8 * @author Maciej Suminski <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 3
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#ifndef __SIM_PLOT_PANEL_H
25#define __SIM_PLOT_PANEL_H
26
27#include "sim_types.h"
28#include <map>
29#include <limits>
30#include <widgets/mathplot.h>
31#include <wx/colour.h>
32#include <wx/sizer.h>
33#include "sim_tab.h"
34#include "sim_plot_colors.h"
35
36class SIMULATOR_FRAME;
37class SIM_PLOT_TAB;
38class TRACE;
39
57
58
60class CURSOR : public mpInfoLayer
61{
62public:
63 CURSOR( TRACE* aTrace, SIM_PLOT_TAB* aPlotTab ) :
64 mpInfoLayer( wxRect( 0, 0, DRAG_MARGIN, DRAG_MARGIN ), wxTRANSPARENT_BRUSH ),
65 m_trace( aTrace ),
66 m_updateRequired( true ),
67 m_updateRef( false ),
68 m_coords( 0.0, 0.0 ),
69 m_window( nullptr ),
70 m_sweepIndex( 0 ),
71 m_snapToNearest( false ),
72 m_snapTargetY( 0.0 )
73 {
74 }
75
76 void Plot( wxDC& aDC, mpWindow& aWindow ) override;
77
78 void SetX( int aX )
79 {
80 m_reference.x = 0;
81 m_updateRef = true;
82 Move( wxPoint( aX, 0 ) );
83 }
84
85 void Update()
86 {
87 m_updateRequired = true;
88 }
89
90 bool Inside( const wxPoint& aPoint ) const override;
91
92 void Move( wxPoint aDelta ) override;
93
94 void UpdateReference() override;
95
96 bool OnDoubleClick( const wxPoint& aPoint, mpWindow& aWindow ) override;
97
98 const wxRealPoint& GetCoords() const
99 {
100 return m_coords;
101 }
102
103 void SetCoordX( double aValue );
104
105private:
106 void doSetCoordX( double aValue );
107
108 wxString getID();
109
110private:
114 wxRealPoint m_coords;
119
120 static constexpr int DRAG_MARGIN = 10;
121};
122
123
124class TRACE : public mpFXYVector
125{
126public:
127 TRACE( const wxString& aName, SIM_TRACE_TYPE aType ) :
128 mpFXYVector( aName ),
129 m_type( aType ),
130 m_isMultiRun( false )
131 {
132 SetContinuity( true );
133 ShowName( false );
134 SetName( aName );
135 }
136
137 void SetName( const wxString& aName ) override
138 {
139 for( auto& [ idx, cursor ] : m_cursors )
140 {
141 if( cursor )
142 cursor->SetName( aName );
143 }
144
145 mpFXYVector::SetName( aName );
146
147 if( m_type & SPT_AC_GAIN )
148 m_displayName = aName + _( " (gain)" );
149 else if( m_type & SPT_AC_PHASE )
150 m_displayName = aName + _( " (phase)" );
151 else
152 m_displayName = aName;
153 }
154
161 void SetData( const std::vector<double>& aX, const std::vector<double>& aY ) override
162 {
163 for( auto& [ idx, cursor ] : m_cursors )
164 {
165 if( cursor )
166 cursor->Update();
167 }
168
169 mpFXYVector::SetData( aX, aY );
170 }
171
172 const std::vector<double>& GetDataX() const { return m_xs; }
173 const std::vector<double>& GetDataY() const { return m_ys; }
174
175 bool HasCursor( int aCursorId ) { return m_cursors[ aCursorId ] != nullptr; }
176
177 void SetCursor( int aCursorId, CURSOR* aCursor ) { m_cursors[ aCursorId ] = aCursor; }
178 CURSOR* GetCursor( int aCursorId ) { return m_cursors[ aCursorId ]; }
179 std::map<int, CURSOR*>& GetCursors() { return m_cursors; }
180
181 SIM_TRACE_TYPE GetType() const { return m_type; }
182
183 void SetTraceColour( const wxColour& aColour ) { m_traceColour = aColour; }
184 wxColour GetTraceColour() const { return m_traceColour; }
185
186 void SetIsMultiRun( bool aIsMultiRun ) { m_isMultiRun = aIsMultiRun; }
187 bool IsMultiRun() const { return m_isMultiRun; }
188
189 void SetMultiRunLabels( const std::vector<wxString>& aLabels ) { m_multiRunLabels = aLabels; }
190 const std::vector<wxString>& GetMultiRunLabels() const { return m_multiRunLabels; }
191
192protected:
193 std::map<int, CURSOR*> m_cursors; // No ownership; the mpWindow owns the CURSORs
197 std::vector<wxString> m_multiRunLabels;
198};
199
200
201class SIM_PLOT_TAB : public SIM_TAB
202{
203public:
204 SIM_PLOT_TAB( const wxString& aSimCommand, wxWindow* parent );
205
206 virtual ~SIM_PLOT_TAB();
207
208 void ApplyPreferences( const SIM_PREFERENCES& aPrefs ) override
209 {
210 m_plotWin->SetMouseWheelActions( convertMouseWheelActions( aPrefs.mouse_wheel_actions ) );
211 }
212
213 wxString GetLabelX() const
214 {
215 return m_axis_x ? m_axis_x->GetName() : wxString( wxS( "" ) );
216 }
217
218 wxString GetLabelY1() const
219 {
220 return m_axis_y1 ? m_axis_y1->GetName() : wxString( wxS( "" ) );
221 }
222
223 wxString GetLabelY2() const
224 {
225 return m_axis_y2 ? m_axis_y2->GetName() : wxString( wxS( "" ) );
226 }
227
228 wxString GetLabelY3() const
229 {
230 return m_axis_y3 ? m_axis_y3->GetName() : wxString( wxS( "" ) );
231 }
232
233 bool GetY1Scale( double* aMin, double* aMax ) const
234 {
235 if( m_axis_y1 )
236 return m_axis_y1->GetAxisMinMax( aMin, aMax );
237
238 return false;
239 }
240
241 bool GetY2Scale( double* aMin, double* aMax ) const
242 {
243 if( m_axis_y2 )
244 return m_axis_y2->GetAxisMinMax( aMin, aMax );
245
246 return false;
247 }
248
249 bool GetY3Scale( double* aMin, double* aMax ) const
250 {
251 if( m_axis_y3 )
252 return m_axis_y3->GetAxisMinMax( aMin, aMax );
253
254 return false;
255 }
256
257 void SetY1Scale( bool aLock, double aMin, double aMax );
258 void SetY2Scale( bool aLock, double aMin, double aMax );
259 void SetY3Scale( bool aLock, double aMin, double aMax );
260
261 wxString GetUnitsX() const;
262 wxString GetUnitsY1() const;
263 wxString GetUnitsY2() const;
264 wxString GetUnitsY3() const;
265
266 const std::map<wxString, TRACE*>& GetTraces() const
267 {
268 return m_traces;
269 }
270
271 TRACE* GetTrace( const wxString& aVecName, int aType ) const
272 {
273 auto trace = m_traces.find( getTraceId( aVecName, aType ) );
274
275 return trace == m_traces.end() ? nullptr : trace->second;
276 }
277
278 void ShowGrid( bool aEnable )
279 {
280 if( m_axis_x )
281 m_axis_x->SetTicks( !aEnable );
282
283 if( m_axis_y1 )
284 m_axis_y1->SetTicks( !aEnable );
285
286 if( m_axis_y2 )
287 m_axis_y2->SetTicks( !aEnable );
288
289 if( m_axis_y3 )
290 m_axis_y3->SetTicks( !aEnable );
291
292 m_plotWin->UpdateAll();
293 }
294
295 bool IsGridShown() const
296 {
297 if( !m_axis_x || !m_axis_y1 )
298 return false;
299
300 return !m_axis_x->GetTicks();
301 }
302
303 void ShowLegend( bool aEnable )
304 {
305 m_legend->SetVisible( aEnable );
306 m_plotWin->UpdateAll();
307 }
308
309 bool IsLegendShown() const
310 {
311 return m_legend->IsVisible();
312 }
313
314 wxPoint GetLegendPosition() const
315 {
316 return m_legend->GetPosition();
317 }
318
319 void SetLegendPosition( const wxPoint& aPosition )
320 {
321 m_legend->Move( aPosition );
322 m_legend->UpdateReference();
323 m_LastLegendPosition = aPosition;
324 }
325
329 void SetDottedSecondary( bool aEnable )
330 {
331 m_dotted_cp = aEnable;
332
333 for( const auto& [ name, trace ] : m_traces )
334 UpdateTraceStyle( trace );
335
336 m_plotWin->UpdateAll();
337 }
338
340 {
341 return m_dotted_cp;
342 }
343
345 void EnableCursor( TRACE* aTrace, int aCursorId, const wxString& aSignalName );
346 void DisableCursor( TRACE* aTrace, int aCursorId );
347
349 void ResetScales( bool aIncludeX );
350
352 void UpdateTraceStyle( TRACE* trace );
353
355 void UpdatePlotColors();
356
357 void OnLanguageChanged() override;
358
360 mpWindow* GetPlotWin() const { return m_plotWin; }
361
362 TRACE* GetOrAddTrace( const wxString& aVectorName, int aType );
363
364 void SetTraceData( TRACE* aTrace, std::vector<double>& aX, std::vector<double>& aY,
365 int aSweepCount, size_t aSweepSize, bool aIsMultiRun = false,
366 const std::vector<wxString>& aMultiRunLabels = {} );
367
368 bool DeleteTrace( const wxString& aVectorName, int aTraceType );
369 void DeleteTrace( TRACE* aTrace );
370
371 std::vector<std::pair<wxString, wxString>>& Measurements() { return m_measurements; }
372
374
375public:
377
378private:
381 {
382 static_assert( static_cast<unsigned>( mpWindow::MouseWheelAction::COUNT )
383 == static_cast<unsigned>( SIM_MOUSE_WHEEL_ACTION::COUNT ),
384 "mpWindow::MouseWheelAction enum must match SIM_MOUSE_WHEEL_ACTION" );
385
388 m.verticalUnmodified = static_cast<A>( s.vertical_unmodified );
389 m.verticalWithCtrl = static_cast<A>( s.vertical_with_ctrl );
390 m.verticalWithShift = static_cast<A>( s.vertical_with_shift );
391 m.verticalWithAlt = static_cast<A>( s.vertical_with_alt );
392 m.horizontal = static_cast<A>( s.horizontal );
393
394 return m;
395 }
396
397 wxString getTraceId( const wxString& aVectorName, int aType ) const
398 {
399 return wxString::Format( wxS( "%s%d" ), aVectorName, aType & SPT_Y_AXIS_MASK );
400 }
401
403 void prepareDCAxes( int aNewTraceType );
404
406 void updateAxes( int aNewTraceType = SIM_TRACE_TYPE::SPT_UNKNOWN );
407
409
410private:
412 std::map<wxString, wxColour> m_sessionTraceColors;
413
414 // Top-level plot window
416 wxBoxSizer* m_sizer;
417
418 // Traces to be plotted
419 std::map<wxString, TRACE*> m_traces;
420
426
428
429 // Measurements (and their format strings)
430 std::vector<std::pair<wxString, wxString>> m_measurements;
431};
432
433wxDECLARE_EVENT( EVT_SIM_CURSOR_UPDATE, wxCommandEvent );
434
435#endif
const char * name
The SIMULATOR_FRAME holds the main user-interface for running simulations.
CURSOR(TRACE *aTrace, SIM_PLOT_TAB *aPlotTab)
mpWindow * m_window
const wxRealPoint & GetCoords() const
void Move(wxPoint aDelta) override
Moves the layer rectangle of given pixel deltas.
void SetX(int aX)
wxString getID()
wxRealPoint m_coords
bool m_updateRef
static constexpr int DRAG_MARGIN
bool Inside(const wxPoint &aPoint) const override
Checks whether a point is inside the info box rectangle.
void doSetCoordX(double aValue)
int m_sweepIndex
bool OnDoubleClick(const wxPoint &aPoint, mpWindow &aWindow) override
void SetCoordX(double aValue)
void UpdateReference() override
Updates the rectangle reference point.
bool m_updateRequired
double m_snapTargetY
TRACE * m_trace
void Plot(wxDC &aDC, mpWindow &aWindow) override
Plot method.
bool m_snapToNearest
void Update()
The SIMULATOR_FRAME holds the main user-interface for running simulations.
bool DeleteTrace(const wxString &aVectorName, int aTraceType)
mpScaleXBase * m_axis_x
wxString GetLabelY1() const
mpWindow * GetPlotWin() const
void prepareDCAxes(int aNewTraceType)
Create/Ensure axes are available for plotting.
void ShowGrid(bool aEnable)
void SetTraceData(TRACE *aTrace, std::vector< double > &aX, std::vector< double > &aY, int aSweepCount, size_t aSweepSize, bool aIsMultiRun=false, const std::vector< wxString > &aMultiRunLabels={})
wxString GetUnitsY2() const
void SetY2Scale(bool aLock, double aMin, double aMax)
TRACE * GetTrace(const wxString &aVecName, int aType) const
virtual ~SIM_PLOT_TAB()
wxString GetLabelX() const
bool IsGridShown() const
const std::map< wxString, TRACE * > & GetTraces() const
wxString GetLabelY3() const
void SetY1Scale(bool aLock, double aMin, double aMax)
bool GetDottedSecondary() const
Turn on/off the cursor for a particular trace.
wxPoint GetLegendPosition() const
mpInfoLegend * m_legend
std::vector< std::pair< wxString, wxString > > m_measurements
void UpdateAxisVisibility()
void SetY3Scale(bool aLock, double aMin, double aMax)
wxBoxSizer * m_sizer
std::map< wxString, TRACE * > m_traces
bool IsLegendShown() const
std::vector< std::pair< wxString, wxString > > & Measurements()
SIM_PLOT_COLORS m_colors
void UpdateTraceStyle(TRACE *trace)
Update plot colors.
void SetLegendPosition(const wxPoint &aPosition)
void ResetScales(bool aIncludeX)
Update trace line style.
void UpdatePlotColors()
mpScaleY * m_axis_y2
void ShowLegend(bool aEnable)
bool GetY3Scale(double *aMin, double *aMax) const
SIM_PLOT_TAB(const wxString &aSimCommand, wxWindow *parent)
wxString GetLabelY2() const
void EnableCursor(TRACE *aTrace, int aCursorId, const wxString &aSignalName)
wxString GetUnitsX() const
void OnLanguageChanged() override
Getter for math plot window.
void EnsureThirdYAxisExists()
wxString getTraceId(const wxString &aVectorName, int aType) const
Construct the plot axes for DC simulation plot.
TRACE * GetOrAddTrace(const wxString &aVectorName, int aType)
mpScaleY * m_axis_y1
void SetDottedSecondary(bool aEnable)
Draw secondary signal traces (current or phase) with dotted lines.
void ApplyPreferences(const SIM_PREFERENCES &aPrefs) override
mpScaleY * m_axis_y3
wxPoint m_LastLegendPosition
wxString GetUnitsY1() const
std::map< wxString, wxColour > m_sessionTraceColors
mpWindow * m_plotWin
static mpWindow::MouseWheelActionSet convertMouseWheelActions(const SIM_MOUSE_WHEEL_ACTION_SET &s)
void DisableCursor(TRACE *aTrace, int aCursorId)
Reset scale ranges to fit the current traces.
bool GetY2Scale(double *aMin, double *aMax) const
void updateAxes(int aNewTraceType=SIM_TRACE_TYPE::SPT_UNKNOWN)
bool GetY1Scale(double *aMin, double *aMax) const
wxString GetUnitsY3() const
SIM_TAB()
Definition sim_tab.cpp:29
std::vector< wxString > m_multiRunLabels
void SetIsMultiRun(bool aIsMultiRun)
void SetTraceColour(const wxColour &aColour)
void SetName(const wxString &aName) override
Set layer name.
wxColour m_traceColour
void SetMultiRunLabels(const std::vector< wxString > &aLabels)
std::map< int, CURSOR * > & GetCursors()
SIM_TRACE_TYPE m_type
SIM_TRACE_TYPE GetType() const
std::map< int, CURSOR * > m_cursors
bool HasCursor(int aCursorId)
bool m_isMultiRun
TRACE(const wxString &aName, SIM_TRACE_TYPE aType)
void SetData(const std::vector< double > &aX, const std::vector< double > &aY) override
Assigns new data set for the trace.
const std::vector< wxString > & GetMultiRunLabels() const
void SetCursor(int aCursorId, CURSOR *aCursor)
bool IsMultiRun() const
const std::vector< double > & GetDataY() const
wxColour GetTraceColour() const
const std::vector< double > & GetDataX() const
CURSOR * GetCursor(int aCursorId)
mpFXYVector(const wxString &name=wxEmptyString, int flags=mpALIGN_NE)
std::vector< double > m_ys
Definition mathplot.h:1458
std::vector< double > m_xs
The internal copy of the set of data to draw.
Definition mathplot.h:1458
virtual void SetData(const std::vector< double > &xs, const std::vector< double > &ys)
Changes the internal data: the set of points to draw.
wxPoint m_reference
Definition mathplot.h:383
mpInfoLayer()
Default constructor.
Definition mathplot.cpp:78
Implements the legend to be added to the plot This layer allows you to add a legend to describe the p...
Definition mathplot.h:395
void SetContinuity(bool continuity)
Set the 'continuity' property of the layer (true:draws a continuous line, false:draws separate points...
Definition mathplot.h:259
void ShowName(bool show)
Shows or hides the text label with the name of the layer (default is visible).
Definition mathplot.h:268
virtual void SetName(const wxString &name)
Set layer name.
Definition mathplot.h:273
wxString m_displayName
Definition mathplot.h:311
Plot layer implementing a y-scale ruler.
Definition mathplot.h:830
Canvas for plotting mpLayer implementations.
Definition mathplot.h:910
MouseWheelAction
Enumerates the possible mouse wheel actions that can be performed on the plot.
Definition mathplot.h:916
#define _(s)
Class is responsible for providing colors for traces on simulation plot.
wxDECLARE_EVENT(EVT_SIM_CURSOR_UPDATE, wxCommandEvent)
SIM_TRACE_TYPE
Definition sim_types.h:46
@ SPT_AC_PHASE
Definition sim_types.h:50
@ SPT_UNKNOWN
Definition sim_types.h:63
@ SPT_AC_GAIN
Definition sim_types.h:51
@ SPT_Y_AXIS_MASK
Definition sim_types.h:54
Contains the set of modified mouse wheel actions that can be performed on a simulator plot.
SIM_MOUSE_WHEEL_ACTION vertical_unmodified
SIM_MOUSE_WHEEL_ACTION vertical_with_alt
SIM_MOUSE_WHEEL_ACTION horizontal
SIM_MOUSE_WHEEL_ACTION vertical_with_ctrl
SIM_MOUSE_WHEEL_ACTION vertical_with_shift
Contains preferences pertaining to the simulator.
SIM_MOUSE_WHEEL_ACTION_SET mouse_wheel_actions
Contains the set of modified mouse wheel actions that can be performed on the plot.
Definition mathplot.h:931
MouseWheelAction horizontal
Definition mathplot.h:941
MouseWheelAction verticalWithShift
Definition mathplot.h:939
MouseWheelAction verticalWithCtrl
Definition mathplot.h:938
MouseWheelAction verticalWithAlt
Definition mathplot.h:940
MouseWheelAction verticalUnmodified
Definition mathplot.h:937