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, you may find one here:
22 * https://www.gnu.org/licenses/gpl-3.0.html
23 * or you may search the http://www.gnu.org website for the version 3 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#ifndef __SIM_PLOT_PANEL_H
29#define __SIM_PLOT_PANEL_H
30
31#include "sim_types.h"
32#include <map>
33#include <limits>
34#include <widgets/mathplot.h>
35#include <wx/colour.h>
36#include <wx/sizer.h>
37#include "sim_tab.h"
38#include "sim_plot_colors.h"
39
40class SIMULATOR_FRAME;
41class SIM_PLOT_TAB;
42class TRACE;
43
61
62
64class CURSOR : public mpInfoLayer
65{
66public:
67 CURSOR( TRACE* aTrace, SIM_PLOT_TAB* aPlotTab ) :
68 mpInfoLayer( wxRect( 0, 0, DRAG_MARGIN, DRAG_MARGIN ), wxTRANSPARENT_BRUSH ),
69 m_trace( aTrace ),
70 m_updateRequired( true ),
71 m_updateRef( false ),
72 m_coords( 0.0, 0.0 ),
73 m_window( nullptr ),
74 m_sweepIndex( 0 ),
75 m_snapToNearest( false ),
76 m_snapTargetY( 0.0 )
77 {
78 }
79
80 void Plot( wxDC& aDC, mpWindow& aWindow ) override;
81
82 void SetX( int aX )
83 {
84 m_reference.x = 0;
85 m_updateRef = true;
86 Move( wxPoint( aX, 0 ) );
87 }
88
89 void Update()
90 {
91 m_updateRequired = true;
92 }
93
94 bool Inside( const wxPoint& aPoint ) const override;
95
96 void Move( wxPoint aDelta ) override;
97
98 void UpdateReference() override;
99
100 bool OnDoubleClick( const wxPoint& aPoint, mpWindow& aWindow ) override;
101
102 const wxRealPoint& GetCoords() const
103 {
104 return m_coords;
105 }
106
107 void SetCoordX( double aValue );
108
109private:
110 void doSetCoordX( double aValue );
111
112 wxString getID();
113
114private:
118 wxRealPoint m_coords;
123
124 static constexpr int DRAG_MARGIN = 10;
125};
126
127
128class TRACE : public mpFXYVector
129{
130public:
131 TRACE( const wxString& aName, SIM_TRACE_TYPE aType ) :
132 mpFXYVector( aName ),
133 m_type( aType ),
134 m_isMultiRun( false )
135 {
136 SetContinuity( true );
137 ShowName( false );
138 SetName( aName );
139 }
140
141 void SetName( const wxString& aName ) override
142 {
143 for( auto& [ idx, cursor ] : m_cursors )
144 {
145 if( cursor )
146 cursor->SetName( aName );
147 }
148
149 mpFXYVector::SetName( aName );
150
151 if( m_type & SPT_AC_GAIN )
152 m_displayName = aName + _( " (gain)" );
153 else if( m_type & SPT_AC_PHASE )
154 m_displayName = aName + _( " (phase)" );
155 else
156 m_displayName = aName;
157 }
158
165 void SetData( const std::vector<double>& aX, const std::vector<double>& aY ) override
166 {
167 for( auto& [ idx, cursor ] : m_cursors )
168 {
169 if( cursor )
170 cursor->Update();
171 }
172
173 mpFXYVector::SetData( aX, aY );
174 }
175
176 const std::vector<double>& GetDataX() const { return m_xs; }
177 const std::vector<double>& GetDataY() const { return m_ys; }
178
179 bool HasCursor( int aCursorId ) { return m_cursors[ aCursorId ] != nullptr; }
180
181 void SetCursor( int aCursorId, CURSOR* aCursor ) { m_cursors[ aCursorId ] = aCursor; }
182 CURSOR* GetCursor( int aCursorId ) { return m_cursors[ aCursorId ]; }
183 std::map<int, CURSOR*>& GetCursors() { return m_cursors; }
184
185 SIM_TRACE_TYPE GetType() const { return m_type; }
186
187 void SetTraceColour( const wxColour& aColour ) { m_traceColour = aColour; }
188 wxColour GetTraceColour() const { return m_traceColour; }
189
190 void SetIsMultiRun( bool aIsMultiRun ) { m_isMultiRun = aIsMultiRun; }
191 bool IsMultiRun() const { return m_isMultiRun; }
192
193 void SetMultiRunLabels( const std::vector<wxString>& aLabels ) { m_multiRunLabels = aLabels; }
194 const std::vector<wxString>& GetMultiRunLabels() const { return m_multiRunLabels; }
195
196protected:
197 std::map<int, CURSOR*> m_cursors; // No ownership; the mpWindow owns the CURSORs
201 std::vector<wxString> m_multiRunLabels;
202};
203
204
205class SIM_PLOT_TAB : public SIM_TAB
206{
207public:
208 SIM_PLOT_TAB( const wxString& aSimCommand, wxWindow* parent );
209
210 virtual ~SIM_PLOT_TAB();
211
212 void ApplyPreferences( const SIM_PREFERENCES& aPrefs ) override
213 {
214 m_plotWin->SetMouseWheelActions( convertMouseWheelActions( aPrefs.mouse_wheel_actions ) );
215 }
216
217 wxString GetLabelX() const
218 {
219 return m_axis_x ? m_axis_x->GetName() : wxString( wxS( "" ) );
220 }
221
222 wxString GetLabelY1() const
223 {
224 return m_axis_y1 ? m_axis_y1->GetName() : wxString( wxS( "" ) );
225 }
226
227 wxString GetLabelY2() const
228 {
229 return m_axis_y2 ? m_axis_y2->GetName() : wxString( wxS( "" ) );
230 }
231
232 wxString GetLabelY3() const
233 {
234 return m_axis_y3 ? m_axis_y3->GetName() : wxString( wxS( "" ) );
235 }
236
237 bool GetY1Scale( double* aMin, double* aMax ) const
238 {
239 if( m_axis_y1 )
240 return m_axis_y1->GetAxisMinMax( aMin, aMax );
241
242 return false;
243 }
244
245 bool GetY2Scale( double* aMin, double* aMax ) const
246 {
247 if( m_axis_y2 )
248 return m_axis_y2->GetAxisMinMax( aMin, aMax );
249
250 return false;
251 }
252
253 bool GetY3Scale( double* aMin, double* aMax ) const
254 {
255 if( m_axis_y3 )
256 return m_axis_y3->GetAxisMinMax( aMin, aMax );
257
258 return false;
259 }
260
261 void SetY1Scale( bool aLock, double aMin, double aMax );
262 void SetY2Scale( bool aLock, double aMin, double aMax );
263 void SetY3Scale( bool aLock, double aMin, double aMax );
264
265 wxString GetUnitsX() const;
266 wxString GetUnitsY1() const;
267 wxString GetUnitsY2() const;
268 wxString GetUnitsY3() const;
269
270 const std::map<wxString, TRACE*>& GetTraces() const
271 {
272 return m_traces;
273 }
274
275 TRACE* GetTrace( const wxString& aVecName, int aType ) const
276 {
277 auto trace = m_traces.find( getTraceId( aVecName, aType ) );
278
279 return trace == m_traces.end() ? nullptr : trace->second;
280 }
281
282 void ShowGrid( bool aEnable )
283 {
284 if( m_axis_x )
285 m_axis_x->SetTicks( !aEnable );
286
287 if( m_axis_y1 )
288 m_axis_y1->SetTicks( !aEnable );
289
290 if( m_axis_y2 )
291 m_axis_y2->SetTicks( !aEnable );
292
293 if( m_axis_y3 )
294 m_axis_y3->SetTicks( !aEnable );
295
296 m_plotWin->UpdateAll();
297 }
298
299 bool IsGridShown() const
300 {
301 if( !m_axis_x || !m_axis_y1 )
302 return false;
303
304 return !m_axis_x->GetTicks();
305 }
306
307 void ShowLegend( bool aEnable )
308 {
309 m_legend->SetVisible( aEnable );
310 m_plotWin->UpdateAll();
311 }
312
313 bool IsLegendShown() const
314 {
315 return m_legend->IsVisible();
316 }
317
318 wxPoint GetLegendPosition() const
319 {
320 return m_legend->GetPosition();
321 }
322
323 void SetLegendPosition( const wxPoint& aPosition )
324 {
325 m_legend->Move( aPosition );
326 m_legend->UpdateReference();
327 m_LastLegendPosition = aPosition;
328 }
329
333 void SetDottedSecondary( bool aEnable )
334 {
335 m_dotted_cp = aEnable;
336
337 for( const auto& [ name, trace ] : m_traces )
338 UpdateTraceStyle( trace );
339
340 m_plotWin->UpdateAll();
341 }
342
344 {
345 return m_dotted_cp;
346 }
347
349 void EnableCursor( TRACE* aTrace, int aCursorId, const wxString& aSignalName );
350 void DisableCursor( TRACE* aTrace, int aCursorId );
351
353 void ResetScales( bool aIncludeX );
354
356 void UpdateTraceStyle( TRACE* trace );
357
359 void UpdatePlotColors();
360
361 void OnLanguageChanged() override;
362
364 mpWindow* GetPlotWin() const { return m_plotWin; }
365
366 TRACE* GetOrAddTrace( const wxString& aVectorName, int aType );
367
368 void SetTraceData( TRACE* aTrace, std::vector<double>& aX, std::vector<double>& aY,
369 int aSweepCount, size_t aSweepSize, bool aIsMultiRun = false,
370 const std::vector<wxString>& aMultiRunLabels = {} );
371
372 bool DeleteTrace( const wxString& aVectorName, int aTraceType );
373 void DeleteTrace( TRACE* aTrace );
374
375 std::vector<std::pair<wxString, wxString>>& Measurements() { return m_measurements; }
376
378
379public:
381
382private:
385 {
386 static_assert( static_cast<unsigned>( mpWindow::MouseWheelAction::COUNT )
387 == static_cast<unsigned>( SIM_MOUSE_WHEEL_ACTION::COUNT ),
388 "mpWindow::MouseWheelAction enum must match SIM_MOUSE_WHEEL_ACTION" );
389
392 m.verticalUnmodified = static_cast<A>( s.vertical_unmodified );
393 m.verticalWithCtrl = static_cast<A>( s.vertical_with_ctrl );
394 m.verticalWithShift = static_cast<A>( s.vertical_with_shift );
395 m.verticalWithAlt = static_cast<A>( s.vertical_with_alt );
396 m.horizontal = static_cast<A>( s.horizontal );
397
398 return m;
399 }
400
401 wxString getTraceId( const wxString& aVectorName, int aType ) const
402 {
403 return wxString::Format( wxS( "%s%d" ), aVectorName, aType & SPT_Y_AXIS_MASK );
404 }
405
407 void prepareDCAxes( int aNewTraceType );
408
410 void updateAxes( int aNewTraceType = SIM_TRACE_TYPE::SPT_UNKNOWN );
411
413
414private:
416 std::map<wxString, wxColour> m_sessionTraceColors;
417
418 // Top-level plot window
420 wxBoxSizer* m_sizer;
421
422 // Traces to be plotted
423 std::map<wxString, TRACE*> m_traces;
424
430
432
433 // Measurements (and their format strings)
434 std::vector<std::pair<wxString, wxString>> m_measurements;
435};
436
437wxDECLARE_EVENT( EVT_SIM_CURSOR_UPDATE, wxCommandEvent );
438
439#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:33
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:50
@ SPT_AC_PHASE
Definition sim_types.h:54
@ SPT_UNKNOWN
Definition sim_types.h:67
@ SPT_AC_GAIN
Definition sim_types.h:55
@ SPT_Y_AXIS_MASK
Definition sim_types.h:58
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