20#include "../elements/controlElement/ConnectionLine.h"
21#include "../elements/controlElement/Constant.h"
22#include "../elements/controlElement/ControlElement.h"
23#include "../elements/controlElement/Divider.h"
24#include "../elements/controlElement/Exponential.h"
25#include "../elements/controlElement/Gain.h"
26#include "../elements/controlElement/Limiter.h"
27#include "../elements/controlElement/MathExpression.h"
28#include "../elements/controlElement/MathOperation.h"
29#include "../elements/controlElement/Multiplier.h"
30#include "../elements/controlElement/RateLimiter.h"
31#include "../elements/controlElement/Sum.h"
32#include "../elements/controlElement/TransferFunction.h"
33#include "../elements/controlElement/ControlElementContainer.h"
34#include "../elements/controlElement/ControlElementSolver.h"
37#include "utils/DegreesAndRadians.h"
39#include "../utils/Camera.h"
40#include "../utils/FileHanding.h"
41#include "../utils/Path.h"
44#include "../utils/ElementPlotData.h"
46ControlElementButton::ControlElementButton(wxWindow* parent, wxString label, wxImage image, wxWindowID
id)
47 : wxWindow(parent, id)
49 SetBackgroundColour(*wxWHITE);
50 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
53 m_imageSize = wxSize(image.GetWidth(), image.GetHeight());
58 wxSize textSize = dc.GetTextExtent(label);
61 if (textSize.GetWidth() > m_imageSize.GetWidth()) {
62 buttonWidth = textSize.GetWidth();
63 m_imagePosition = wxPoint((buttonWidth - m_imageSize.GetWidth()) / 2 + m_borderSize, m_borderSize);
64 m_labelPosition = wxPoint(m_borderSize, m_imageSize.GetHeight() + m_borderSize);
67 buttonWidth = m_imageSize.GetWidth();
68 m_imagePosition = wxPoint(m_borderSize, m_borderSize);
70 wxPoint((buttonWidth - textSize.GetWidth()) / 2 + m_borderSize, m_imageSize.GetHeight() + m_borderSize);
73 wxSize(buttonWidth + 2 * m_borderSize, textSize.GetHeight() + m_imageSize.GetHeight() + 2 * m_borderSize);
74 SetMinSize(m_buttonSize + wxSize(m_borderSize, m_borderSize));
77 Bind(wxEVT_PAINT, &ControlElementButton::OnPaint,
this);
78 Bind(wxEVT_ENTER_WINDOW, &ControlElementButton::OnMouseEnter,
this);
79 Bind(wxEVT_LEAVE_WINDOW, &ControlElementButton::OnMouseLeave,
this);
80 Bind(wxEVT_LEFT_DOWN, &ControlElementButton::OnLeftClickDown,
this);
81 Bind(wxEVT_LEFT_UP, &ControlElementButton::OnLeftClickUp,
this);
84ControlElementButton::~ControlElementButton() {}
85void ControlElementButton::OnPaint(wxPaintEvent& event)
88 wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
92 gc->SetPen(wxPen(wxColour(0, 125, 255, 255), m_borderSize - 1));
93 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 100)));
96 gc->SetPen(*wxTRANSPARENT_PEN);
97 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 70)));
99 gc->DrawRectangle(m_borderSize / 2, m_borderSize / 2, m_buttonSize.GetWidth(), m_buttonSize.GetHeight());
101 gc->DrawBitmap(gc->CreateBitmapFromImage(m_image), m_imagePosition.x, m_imagePosition.y, m_imageSize.GetWidth(),
102 m_imageSize.GetHeight());
103 gc->SetFont(m_font, *wxBLACK);
104 gc->DrawText(m_label, m_labelPosition.x, m_labelPosition.y);
109void ControlElementButton::OnMouseEnter(wxMouseEvent& event)
116void ControlElementButton::OnMouseLeave(wxMouseEvent& event)
118 m_mouseAbove =
false;
123void ControlElementButton::OnLeftClickDown(wxMouseEvent& event)
130void ControlElementButton::OnLeftClickUp(wxMouseEvent& event)
137ControlEditor::ControlEditor(wxWindow* parent,
int ioflags) : ControlEditorBase(parent)
139 BuildControlElementPanel();
143 m_selectionRect = wxRect2DDouble(0, 0, 0, 0);
144 m_cePanel->SetBackgroundColour(wxColour(255, 255, 255));
145 m_cePanel->SetBackgroundStyle(wxBG_STYLE_PAINT);
151ControlEditor::~ControlEditor()
156void ControlEditor::BuildControlElementPanel()
158 m_panelControlElements->SetDoubleBuffered(
true);
159 wxWrapSizer* wrapSizer =
new wxWrapSizer();
160 m_panelControlElements->SetSizer(wrapSizer);
162 wxFileName exeFileName(wxStandardPaths::Get().GetExecutablePath());
166 m_panelControlElements, _(
"In/Out"),
167 wxImage(Paths::GetDataPath() +
"/images/control/io.png"),
168 static_cast<int>(ControlElementButtonID::ID_IO));
169 wrapSizer->Add(ioButton, 0, wxALL, 5);
170 ioButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
173 m_panelControlElements, _(
"Transfer fcn"),
174 wxImage(Paths::GetDataPath() +
"/images/control/transferFunc.png"),
175 static_cast<int>(ControlElementButtonID::ID_TF));
176 wrapSizer->Add(tfButton, 0, wxALL, 5);
177 tfButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
180 m_panelControlElements, _(
"Sum"),
181 wxImage(Paths::GetDataPath() +
"/images/control/sum.png"),
182 static_cast<int>(ControlElementButtonID::ID_SUM));
183 wrapSizer->Add(sumButton, 0, wxALL, 5);
184 sumButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
187 m_panelControlElements, _(
"Constant"),
188 wxImage(Paths::GetDataPath() +
"/images/control/value.png"),
189 static_cast<int>(ControlElementButtonID::ID_CONST));
190 wrapSizer->Add(constButton, 0, wxALL, 5);
191 constButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
194 m_panelControlElements, _(
"Gain"),
195 wxImage(Paths::GetDataPath() +
"/images/control/gain.png"),
196 static_cast<int>(ControlElementButtonID::ID_GAIN));
197 wrapSizer->Add(gainButton, 0, wxALL, 5);
198 gainButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
201 m_panelControlElements, _(
"Limiter"),
202 wxImage(Paths::GetDataPath() +
"/images/control/limiter.png"),
203 static_cast<int>(ControlElementButtonID::ID_LIMITER));
204 wrapSizer->Add(limButton, 0, wxALL, 5);
205 limButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
208 m_panelControlElements, _(
"Rate limiter"),
209 wxImage(Paths::GetDataPath() +
"/images/control/rateLimiter.png"),
210 static_cast<int>(ControlElementButtonID::ID_RATELIM));
211 wrapSizer->Add(rateLimButton, 0, wxALL, 5);
212 rateLimButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
215 m_panelControlElements, _(
"Multiplier"),
216 wxImage(Paths::GetDataPath() +
"/images/control/mult.png"),
217 static_cast<int>(ControlElementButtonID::ID_MULT));
218 wrapSizer->Add(multButton, 0, wxALL, 5);
219 multButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
222 m_panelControlElements, _(
"Divider"),
223 wxImage(Paths::GetDataPath() +
"/images/control/div.png"),
224 static_cast<int>(ControlElementButtonID::ID_MATH_DIV));
225 wrapSizer->Add(divButton, 0, wxALL, 5);
226 divButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
229 m_panelControlElements, _(
"Math Expression"),
230 wxImage(Paths::GetDataPath() +
"/images/control/mathExpr.png"),
231 static_cast<int>(ControlElementButtonID::ID_MATH_EXPR));
232 wrapSizer->Add(mathExprButton, 0, wxALL, 5);
233 mathExprButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
236 m_panelControlElements, _(
"Exponential"),
237 wxImage(Paths::GetDataPath() +
"/images/control/sat.png"),
238 static_cast<int>(ControlElementButtonID::ID_EXP));
239 wrapSizer->Add(satButton, 0, wxALL, 5);
240 satButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
243void ControlEditor::LeftClickDown(wxMouseEvent& event)
245 AddElement(
static_cast<ControlElementButtonID
>(event.GetId()));
274void ControlEditor::AddElement(ControlElementButtonID
id)
277 case ControlElementButtonID::ID_IO: {
278 m_mode = ControlEditorMode::MODE_INSERT;
279 auto io = std::make_shared<IOControl>(m_ioFlags, GetNextID());
280 m_elementList.push_back(io);
282 case ControlElementButtonID::ID_TF: {
283 m_mode = ControlEditorMode::MODE_INSERT;
284 auto tf = std::make_shared<TransferFunction>(GetNextID());
285 m_elementList.push_back(tf);
287 case ControlElementButtonID::ID_SUM: {
288 m_mode = ControlEditorMode::MODE_INSERT;
289 auto sum = std::make_shared<Sum>(GetNextID());
290 m_elementList.push_back(sum);
292 case ControlElementButtonID::ID_CONST: {
293 m_mode = ControlEditorMode::MODE_INSERT;
294 auto constant = std::make_shared<Constant>(GetNextID());
295 m_elementList.push_back(constant);
297 case ControlElementButtonID::ID_LIMITER: {
298 m_mode = ControlEditorMode::MODE_INSERT;
299 auto limiter = std::make_shared<Limiter>(GetNextID());
300 m_elementList.push_back(limiter);
302 case ControlElementButtonID::ID_GAIN: {
303 m_mode = ControlEditorMode::MODE_INSERT;
304 auto gain = std::make_shared<Gain>(GetNextID());
305 m_elementList.push_back(gain);
307 case ControlElementButtonID::ID_MULT: {
308 m_mode = ControlEditorMode::MODE_INSERT;
309 auto mult = std::make_shared<Multiplier>(GetNextID());
310 m_elementList.push_back(mult);
312 case ControlElementButtonID::ID_EXP: {
313 m_mode = ControlEditorMode::MODE_INSERT;
314 auto exp = std::make_shared<Exponential>(GetNextID());
315 m_elementList.push_back(exp);
317 case ControlElementButtonID::ID_RATELIM: {
318 m_mode = ControlEditorMode::MODE_INSERT;
319 auto rateLim = std::make_shared<RateLimiter>(GetNextID());
320 m_elementList.push_back(rateLim);
322 case ControlElementButtonID::ID_MATH_DIV: {
323 m_mode = ControlEditorMode::MODE_INSERT;
324 auto divider = std::make_shared<Divider>(GetNextID());
325 m_elementList.push_back(divider);
327 case ControlElementButtonID::ID_MATH_EXPR: {
328 m_mode = ControlEditorMode::MODE_INSERT;
329 auto mathExpr = std::make_shared<MathExpression>(GetNextID());
330 m_elementList.push_back(mathExpr);
335void ControlEditor::OnPaint(wxPaintEvent& event)
375 wxBufferedPaintDC dc(m_cePanel);
377 wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
382 gc->Scale(m_camera->GetScale(), m_camera->GetScale());
383 gc->Translate(m_camera->GetTranslation().m_x, m_camera->GetTranslation().m_y);
385 for (
auto line : m_connectionList) {
387 line->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
390 for (
auto element : m_elementList) {
391 element->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
395 gc->SetPen(wxPen(wxColour(0, 125, 255, 255)));
396 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 125)));
397 gc->DrawRectangle(m_selectionRect.m_x, m_selectionRect.m_y, m_selectionRect.m_width, m_selectionRect.m_height);
404void ControlEditor::OnDoubleClick(wxMouseEvent& event)
406 wxPoint2DDouble clickPoint =
event.GetPosition();
409 if (m_mode == ControlEditor::ControlEditorMode::MODE_EDIT) {
410 for (
auto& element : m_elementList) {
411 if (element->Contains(m_camera->ScreenToWorld(clickPoint))) {
412 element->ShowForm(
this, element.get());
414 auto childList = element->GetChildList();
415 for (
auto itC = childList.begin(), itEndC = childList.end(); itC != itEndC; ++itC) {
417 line->UpdatePoints();
424 if (redraw) Redraw();
427void ControlEditor::OnLeftClickDown(wxMouseEvent& event)
429 wxPoint2DDouble clickPoint =
event.GetPosition();
430 bool foundElement =
false;
432 if (m_mode == ControlEditorMode::MODE_INSERT) {
433 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
436 for (
auto& element : m_elementList) {
437 bool foundNode =
false;
438 auto nodeList = element->GetNodeList();
439 for (
auto itN = nodeList.begin(), itNEnd = nodeList.end(); itN != itNEnd; ++itN) {
441 if (node->Contains(m_camera->ScreenToWorld(clickPoint))) {
442 m_mode = ControlEditorMode::MODE_INSERT_LINE;
443 auto line = std::make_shared<ConnectionLine>(node, GetNextID());
444 m_connectionList.push_back(line);
445 element->AddChild(line.get());
446 line->AddParent(element.get());
454 element->StartMove(m_camera->ScreenToWorld(clickPoint));
457 if (element->Contains(m_camera->ScreenToWorld(clickPoint))) {
459 element->SetSelected();
462 m_mode = ControlEditor::ControlEditorMode::MODE_MOVE_ELEMENT;
466 if (m_mode != ControlEditorMode::MODE_INSERT_LINE) {
467 for (
auto& line : m_connectionList) {
468 line->StartMove(m_camera->ScreenToWorld(clickPoint));
469 if (line->Contains(m_camera->ScreenToWorld(clickPoint))) {
472 m_mode = ControlEditorMode::MODE_MOVE_LINE;
479 m_mode = ControlEditorMode::MODE_SELECTION_RECT;
480 m_startSelRect = m_camera->ScreenToWorld(clickPoint);
487void ControlEditor::OnLeftClickUp(wxMouseEvent& event)
489 bool foundNode =
false;
490 for (
auto& element : m_elementList) {
491 if (m_mode == ControlEditorMode::MODE_INSERT_LINE) {
492 auto nodeList = element->GetNodeList();
493 for (
auto node : nodeList) {
494 if (node->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
496 auto line = m_connectionList.back();
497 if (line->AppendNode(node, element.get())) {
498 line->AddParent(element.get());
499 element->AddChild(line.get());
500 line->UpdatePoints();
501 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
507 else if (m_mode == ControlEditorMode::MODE_SELECTION_RECT) {
508 if (element->Intersects(m_selectionRect)) {
509 element->SetSelected();
511 else if (!event.ControlDown()) {
512 element->SetSelected(
false);
515 else if (!event.ControlDown()) {
516 if (!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetSelected(
false); }
520 auto& lastLine = m_connectionList.back();
521 for (
auto& cLine : m_connectionList) {
522 if (m_mode == ControlEditorMode::MODE_INSERT_LINE && !foundNode && cLine.get() != lastLine.get()) {
523 if (cLine->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
525 auto iLine = m_connectionList.back();
526 if (iLine->SetParentLine(cLine.get())) {
527 cLine->AddChild(iLine.get());
528 iLine->UpdatePoints();
529 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
534 else if (m_mode == ControlEditorMode::MODE_SELECTION_RECT) {
535 if (cLine->Intersects(m_selectionRect)) {
536 cLine->SetSelected();
538 else if (!event.ControlDown()) {
539 cLine->SetSelected(
false);
542 else if (!event.ControlDown()) {
543 if (!cLine->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { cLine->SetSelected(
false); }
547 m_selectionRect = wxRect2DDouble(0, 0, 0, 0);
549 if (m_mode == ControlEditorMode::MODE_INSERT_LINE && !foundNode) {
551 auto cLine = m_connectionList.back();
553 auto nodeList = cLine->GetNodeList();
554 for (
auto itN = nodeList.begin(), itEndN = nodeList.end(); itN != itEndN; ++itN) {
556 node->SetConnected(
false);
559 auto parentList = cLine->GetParentList();
560 for (
auto it = parentList.begin(), itEnd = parentList.end(); it != itEnd; ++it) {
564 m_connectionList.pop_back();
566 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
568 else if (m_mode != ControlEditorMode::MODE_INSERT) {
569 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
576void ControlEditor::OnMiddleDown(wxMouseEvent& event)
580 case ControlEditorMode::MODE_INSERT: {
581 m_mode = ControlEditorMode::MODE_DRAG_INSERT;
583 case ControlEditorMode::MODE_PASTE: {
584 m_mode = ControlEditorMode::MODE_DRAG_PASTE;
587 m_mode = ControlEditorMode::MODE_DRAG;
590 m_camera->StartTranslation(m_camera->ScreenToWorld(event.GetPosition()));
593void ControlEditor::OnMiddleUp(wxMouseEvent& event)
596 case ControlEditorMode::MODE_DRAG_INSERT: {
597 m_mode = ControlEditorMode::MODE_INSERT;
599 case ControlEditorMode::MODE_DRAG_PASTE: {
600 m_mode = ControlEditorMode::MODE_PASTE;
602 case ControlEditorMode::MODE_INSERT:
603 case ControlEditorMode::MODE_PASTE: {
607 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
612void ControlEditor::OnMouseMotion(wxMouseEvent& event)
614 wxPoint2DDouble clickPoint =
event.GetPosition();
618 case ControlEditorMode::MODE_INSERT: {
620 auto newElement = m_elementList.back();
621 newElement->Move(m_camera->ScreenToWorld(clickPoint));
624 case ControlEditorMode::MODE_INSERT_LINE: {
626 auto line = m_connectionList.back();
627 line->SetTemporarySecondPoint(m_camera->ScreenToWorld(clickPoint));
628 line->UpdatePoints();
631 case ControlEditorMode::MODE_DRAG:
632 case ControlEditorMode::MODE_DRAG_INSERT:
633 case ControlEditorMode::MODE_DRAG_PASTE: {
634 m_camera->SetTranslation(clickPoint);
637 case ControlEditor::ControlEditorMode::MODE_MOVE_ELEMENT: {
638 for (
auto& element : m_elementList) {
640 element->
Move(m_camera->ScreenToWorld(clickPoint));
642 for (
auto itC = childList.begin(), itEndC = childList.end(); itC != itEndC; itC++) {
644 line->UpdatePoints();
650 case ControlEditorMode::MODE_MOVE_LINE: {
651 for (
auto& line : m_connectionList) {
652 if (line->IsSelected()) {
653 line->Move(m_camera->ScreenToWorld(clickPoint));
658 case ControlEditorMode::MODE_SELECTION_RECT: {
659 wxPoint2DDouble currentPos = m_camera->ScreenToWorld(clickPoint);
661 if (currentPos.m_x < m_startSelRect.m_x) {
663 w = m_startSelRect.m_x - currentPos.m_x;
666 x = m_startSelRect.m_x;
667 w = currentPos.m_x - m_startSelRect.m_x;
669 if (currentPos.m_y < m_startSelRect.m_y) {
671 h = m_startSelRect.m_y - currentPos.m_y;
674 y = m_startSelRect.m_y;
675 h = currentPos.m_y - m_startSelRect.m_y;
678 m_selectionRect = wxRect2DDouble(x, y, w, h);
685 if (redraw) Redraw();
689void ControlEditor::OnScroll(wxMouseEvent& event)
691 if (event.GetWheelRotation() > 0)
692 m_camera->SetScale(event.GetPosition(), +0.05);
694 m_camera->SetScale(event.GetPosition(), -0.05);
699void ControlEditor::OnIdle(wxIdleEvent& event)
713void ControlEditor::OnKeyDown(wxKeyEvent& event)
715 char key =
event.GetUnicodeKey();
716 if (key != WXK_NONE) {
720 DeleteSelectedElements();
724 RotateSelectedElements(event.GetModifiers() != wxMOD_SHIFT);
733void ControlEditor::RotateSelectedElements(
bool clockwise)
735 for (
auto& element : m_elementList) {
737 element->
Rotate(clockwise);
739 for (
auto itC = childList.begin(), itEndC = childList.end(); itC != itEndC; itC++) {
741 line->UpdatePoints();
748void ControlEditor::DeleteSelectedElements()
750 for (
auto it = m_elementList.begin(); it != m_elementList.end();) {
755 for (
auto child : childList) {
760 for (
auto itCo = m_connectionList.begin(); itCo != m_connectionList.end(); ) {
761 if (itCo->get() == childLine)
762 itCo = DeleteLineFromList(itCo);
769 m_elementList.erase(it);
777 for (
auto it = m_connectionList.begin(); it != m_connectionList.end(); ) {
780 it = DeleteLineFromList(it);
787std::vector< std::shared_ptr<ConnectionLine> >::iterator ControlEditor::DeleteLineFromList(std::vector< std::shared_ptr<ConnectionLine> >::iterator& it)
792 auto childList = cLine->GetLineChildList();
793 for (
auto child : childList) {
794 for (
auto itL = m_connectionList.begin(); itL != m_connectionList.end(); ) {
795 if (itL->get() == child)
796 itL = DeleteLineFromList(itL);
803 for (
auto parent : parentList) {
804 if (parent) parent->RemoveChild(cLine);
806 if (cLine->GetParentLine()) cLine->GetParentLine()->
RemoveChild(cLine);
809 auto nodeList = cLine->GetNodeList();
810 for (
auto node : nodeList)
811 node->SetConnected(false);
813 return m_connectionList.erase(it);
816void ControlEditor::CheckConnections()
818 for (
auto it = m_connectionList.begin(); it != m_connectionList.end(); ++it) {
820 if (cLine->GetType() == ConnectionLine::ConnectionLineType::ELEMENT_ELEMENT) {
821 if (cLine->
GetParentList().size() < 2) { it = DeleteLineFromList(it); }
824 it = DeleteLineFromList(it);
829void ControlEditor::OnExportClick(wxCommandEvent& event)
833 wxFileDialog saveFileDialog(
this, _(
"Save CTL file"),
"",
"",
"CTL files (*.ctl)|*.ctl",
834 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
835 if (saveFileDialog.ShowModal() == wxID_CANCEL)
return;
837 fileHandling.SaveControl(saveFileDialog.GetPath());
838 wxFileName fileName(saveFileDialog.GetPath());
842void ControlEditor::OnImportClick(wxCommandEvent& event)
844 wxFileDialog openFileDialog(
this, _(
"Open CTL file"),
"",
"",
"CTL files (*.ctl)|*.ctl",
845 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
846 if (openFileDialog.ShowModal() == wxID_CANCEL)
return;
848 wxFileName fileName(openFileDialog.GetPath());
851 if (!fileHandling.OpenControl(fileName, m_elementList, m_connectionList)) {
852 wxMessageDialog msgDialog(
this, _(
"It was not possible to open the selected file."), _(
"Error"),
853 wxOK | wxCENTRE | wxICON_ERROR);
854 msgDialog.ShowModal();
860void ControlEditor::OnTestClick(wxCommandEvent& event)
863 m_itColourList = --m_colourList.end();
865 std::vector<IOControl*> ioList;
867 for (
auto& element : m_elementList) {
868 if (
auto io =
dynamic_cast<IOControl*
>(element.get())) {
869 ioList.push_back(io);
873 ControlSystemTest csTest(
this, ioList, &m_inputType, &m_startTime, &m_slope, &m_timeStep, &m_simTime);
874 if (csTest.ShowModal() == wxID_OK) {
875 double printStep = 1e-3;
876 double pdbStep = 1e-1;
880 std::vector<double> values;
883 std::vector<InputData> inputList;
886 std::vector<IOControl::IOFlags> realFlagValue;
887 for (
auto* io : ioList) {
888 realFlagValue.push_back(io->GetValue());
889 if (io->GetType() == Node::NodeType::NODE_OUT) {
891 io->SetValue(IOControl::IN_TEST);
892 io->SetTestValue(testData.initialValue);
893 inputList.push_back({ io->GetName(), {} });
897 wxProgressDialog pbd(_(
"Test"), _(
"Initializing..."), 100,
this,
898 wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_SMOOTH);
900 solver.InitializeValues(
false);
902 bool simStopped =
false;
903 double currentTime = 0.0;
904 double printTime = 0.0;
905 double pdbTime = 0.0;
906 std::vector<double> time;
907 std::vector<double> solution;
909 while (currentTime <= m_simTime) {
910 for (
auto* io : ioList) {
912 if (currentTime >= testData.startTime) {
913 switch (testData.type) {
915 io->SetTestValue(testData.slope);
918 io->SetTestValue(testData.slope * (currentTime - testData.startTime));
921 io->SetTestValue(testData.slope * std::pow(currentTime - testData.startTime, 2));
924 io->SetTestValue(0.0);
931 solver.SetCurrentTime(currentTime);
932 solver.SolveNextStep();
933 if (!solver.IsOK()) {
934 wxString msg = wxString::Format(_(
"Failed to solve the control system.\n%s"), solver.GetErrorMessage());
935 wxMessageDialog msgDialog(
this, msg, _(
"Error"), wxOK | wxCENTRE | wxICON_ERROR);
936 msgDialog.ShowModal();
938 currentTime = m_simTime;
941 if (printTime >= printStep) {
942 time.push_back(currentTime);
943 solution.push_back(solver.GetLastSolution());
946 for (
auto* io : ioList) {
947 if (io->GetType() == Node::NodeType::NODE_OUT) {
948 inputList[i].values.push_back(io->GetTestValue());
955 if (pdbTime > pdbStep) {
956 if (!pbd.Update((currentTime / m_simTime) * 100, wxString::Format(
"Time = %.2fs", currentTime))) {
959 currentTime = m_simTime;
964 printTime += m_timeStep;
965 currentTime += m_timeStep;
966 pdbTime += m_timeStep;
970 std::vector<ElementPlotData> epdList;
971 ElementPlotData curveData(_(
"I/O"), ElementPlotData::CurveType::CT_TEST);
973 for (
const auto& input : inputList) {
974 curveData.AddData(input.values, input.name);
975 curveData.SetPlot(i);
976 curveData.SetColour(i, GetNextColour());
980 curveData.AddData(solution, _(
"Output"));
981 curveData.SetPlot(i);
982 curveData.SetColour(i, GetNextColour());
989 epdList.push_back(curveData);
991 ChartView* cView =
new ChartView(
this, epdList, time,
static_cast<PlotLib
>(m_plotLib));
997 wxMessageDialog msgDialog(
999 wxString::Format(_(
"Failed to solve the control system.\n%s"), solver.GetErrorMessage()),
1001 wxOK | wxCENTRE | wxICON_ERROR
1004 msgDialog.ShowModal();
1008 for (
size_t i = 0; i < ioList.size(); i++) {
1009 if (ioList[i]->GetType() == Node::NodeType::NODE_OUT)
1010 ioList[i]->SetValue(realFlagValue[i]);
1015void ControlEditor::OnClose(wxCloseEvent& event)
1017 if (m_ctrlContainer) { m_ctrlContainer->FillContainer(
this); }
1021int ControlEditor::GetNextID()
1024 for (
auto& element : m_elementList) {
1025 if (element->
GetID() >
id)
id = element->
GetID();
1027 for (
auto& line : m_connectionList) {
1034void ControlEditor::BuildColourList()
1036 m_colourList.push_back(wxColour(255, 30, 0));
1037 m_colourList.push_back(wxColour(0, 30, 255));
1038 m_colourList.push_back(wxColour(0, 128, 0));
1039 m_colourList.push_back(wxColour(100, 100, 100));
1040 m_colourList.push_back(wxColour(255, 128, 0));
1041 m_colourList.push_back(wxColour(128, 0, 255));
1042 m_colourList.push_back(wxColour(0, 255, 128));
1043 m_colourList.push_back(wxColour(255, 255, 0));
1044 m_colourList.push_back(wxColour(255, 0, 255));
1045 m_colourList.push_back(wxColour(0, 255, 255));
1046 m_colourList.push_back(wxColour(128, 255, 0));
1047 m_colourList.push_back(wxColour(255, 0, 128));
1048 m_colourList.push_back(wxColour(0, 128, 255));
1049 m_colourList.push_back(wxColour(128, 128, 128));
1050 m_colourList.push_back(*wxBLACK);
1051 m_itColourList = --m_colourList.end();
1054wxColour ControlEditor::GetNextColour()
1056 if (*m_itColourList == *wxBLACK)
1057 m_itColourList = m_colourList.begin();
1061 return *m_itColourList;
Class responsible for the correct visualization of the elements on screen.
This class is responsible to manage the charts generated in the transient electromechanical studies.
Connection between two control elements or other connection line and an element.
Solves in the time the control system. Can solve the control system directly from a ControlEditor or ...
Form to edit properties to test the control system created.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
virtual std::vector< Element * > GetParentList() const
Get the parent list.
virtual int GetID() const
Get the element ID.
virtual std::vector< Element * > GetChildList() const
Get the Child list.
virtual void RemoveChild(Element *child)
Remove a child from the list.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
bool IsSelected() const
Checks if the element is selected.
virtual void Rotate(bool clockwise=true)
Rotate the element.
Save and opens the projects created on disk.
Provides the communication with the power element.
Node of a control element. This class manages the user interaction with the connection and control el...