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"
43#include "../utils/ElementPlotData.h"
45ControlElementButton::ControlElementButton(wxWindow* parent, wxString label, wxImage image, wxWindowID
id)
46 : wxWindow(parent, id)
48 SetBackgroundColour(*wxWHITE);
49 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
52 m_imageSize = wxSize(image.GetWidth(), image.GetHeight());
57 wxSize textSize = dc.GetTextExtent(label);
60 if (textSize.GetWidth() > m_imageSize.GetWidth()) {
61 buttonWidth = textSize.GetWidth();
62 m_imagePosition = wxPoint((buttonWidth - m_imageSize.GetWidth()) / 2 + m_borderSize, m_borderSize);
63 m_labelPosition = wxPoint(m_borderSize, m_imageSize.GetHeight() + m_borderSize);
66 buttonWidth = m_imageSize.GetWidth();
67 m_imagePosition = wxPoint(m_borderSize, m_borderSize);
69 wxPoint((buttonWidth - textSize.GetWidth()) / 2 + m_borderSize, m_imageSize.GetHeight() + m_borderSize);
72 wxSize(buttonWidth + 2 * m_borderSize, textSize.GetHeight() + m_imageSize.GetHeight() + 2 * m_borderSize);
73 SetMinSize(m_buttonSize + wxSize(m_borderSize, m_borderSize));
76 Bind(wxEVT_PAINT, &ControlElementButton::OnPaint,
this);
77 Bind(wxEVT_ENTER_WINDOW, &ControlElementButton::OnMouseEnter,
this);
78 Bind(wxEVT_LEAVE_WINDOW, &ControlElementButton::OnMouseLeave,
this);
79 Bind(wxEVT_LEFT_DOWN, &ControlElementButton::OnLeftClickDown,
this);
80 Bind(wxEVT_LEFT_UP, &ControlElementButton::OnLeftClickUp,
this);
83ControlElementButton::~ControlElementButton() {}
84void ControlElementButton::OnPaint(wxPaintEvent& event)
87 wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
91 gc->SetPen(wxPen(wxColour(0, 125, 255, 255), m_borderSize - 1));
92 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 100)));
95 gc->SetPen(*wxTRANSPARENT_PEN);
96 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 70)));
98 gc->DrawRectangle(m_borderSize / 2, m_borderSize / 2, m_buttonSize.GetWidth(), m_buttonSize.GetHeight());
100 gc->DrawBitmap(gc->CreateBitmapFromImage(m_image), m_imagePosition.x, m_imagePosition.y, m_imageSize.GetWidth(),
101 m_imageSize.GetHeight());
102 gc->SetFont(m_font, *wxBLACK);
103 gc->DrawText(m_label, m_labelPosition.x, m_labelPosition.y);
108void ControlElementButton::OnMouseEnter(wxMouseEvent& event)
115void ControlElementButton::OnMouseLeave(wxMouseEvent& event)
117 m_mouseAbove =
false;
122void ControlElementButton::OnLeftClickDown(wxMouseEvent& event)
129void ControlElementButton::OnLeftClickUp(wxMouseEvent& event)
136ControlEditor::ControlEditor(wxWindow* parent,
int ioflags) : ControlEditorBase(parent)
138 BuildControlElementPanel();
142 m_selectionRect = wxRect2DDouble(0, 0, 0, 0);
143 m_cePanel->SetBackgroundColour(wxColour(255, 255, 255));
144 m_cePanel->SetBackgroundStyle(wxBG_STYLE_PAINT);
150ControlEditor::~ControlEditor()
155void ControlEditor::BuildControlElementPanel()
157 m_panelControlElements->SetDoubleBuffered(
true);
158 wxWrapSizer* wrapSizer =
new wxWrapSizer();
159 m_panelControlElements->SetSizer(wrapSizer);
161 wxFileName exeFileName(wxStandardPaths::Get().GetExecutablePath());
162 wxString exePath = exeFileName.GetPath();
165 m_panelControlElements, _(
"In/Out"),
166 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\io.png", wxPATH_WIN).GetPath()),
167 static_cast<int>(ControlElementButtonID::ID_IO));
168 wrapSizer->Add(ioButton, 0, wxALL, 5);
169 ioButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
172 m_panelControlElements, _(
"Transfer fcn"),
173 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\transferFunc.png", wxPATH_WIN).GetPath()),
174 static_cast<int>(ControlElementButtonID::ID_TF));
175 wrapSizer->Add(tfButton, 0, wxALL, 5);
176 tfButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
179 m_panelControlElements, _(
"Sum"),
180 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\sum.png", wxPATH_WIN).GetPath()),
181 static_cast<int>(ControlElementButtonID::ID_SUM));
182 wrapSizer->Add(sumButton, 0, wxALL, 5);
183 sumButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
186 m_panelControlElements, _(
"Constant"),
187 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\value.png", wxPATH_WIN).GetPath()),
188 static_cast<int>(ControlElementButtonID::ID_CONST));
189 wrapSizer->Add(constButton, 0, wxALL, 5);
190 constButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
193 m_panelControlElements, _(
"Gain"),
194 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\gain.png", wxPATH_WIN).GetPath()),
195 static_cast<int>(ControlElementButtonID::ID_GAIN));
196 wrapSizer->Add(gainButton, 0, wxALL, 5);
197 gainButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
200 m_panelControlElements, _(
"Limiter"),
201 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\limiter.png", wxPATH_WIN).GetPath()),
202 static_cast<int>(ControlElementButtonID::ID_LIMITER));
203 wrapSizer->Add(limButton, 0, wxALL, 5);
204 limButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
207 m_panelControlElements, _(
"Rate limiter"),
208 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\rateLimiter.png", wxPATH_WIN).GetPath()),
209 static_cast<int>(ControlElementButtonID::ID_RATELIM));
210 wrapSizer->Add(rateLimButton, 0, wxALL, 5);
211 rateLimButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
214 m_panelControlElements, _(
"Multiplier"),
215 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\mult.png", wxPATH_WIN).GetPath()),
216 static_cast<int>(ControlElementButtonID::ID_MULT));
217 wrapSizer->Add(multButton, 0, wxALL, 5);
218 multButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
221 m_panelControlElements, _(
"Divider"),
222 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\div.png", wxPATH_WIN).GetPath()),
223 static_cast<int>(ControlElementButtonID::ID_MATH_DIV));
224 wrapSizer->Add(divButton, 0, wxALL, 5);
225 divButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
228 m_panelControlElements, _(
"Math Expression"),
229 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\mathExpr.png", wxPATH_WIN).GetPath()),
230 static_cast<int>(ControlElementButtonID::ID_MATH_EXPR));
231 wrapSizer->Add(mathExprButton, 0, wxALL, 5);
232 mathExprButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
235 m_panelControlElements, _(
"Exponential"),
236 wxImage(exePath + wxFileName::DirName(
"\\..\\data\\images\\control\\sat.png", wxPATH_WIN).GetPath()),
237 static_cast<int>(ControlElementButtonID::ID_EXP));
238 wrapSizer->Add(satButton, 0, wxALL, 5);
239 satButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown,
this);
242void ControlEditor::LeftClickDown(wxMouseEvent& event)
244 AddElement(
static_cast<ControlElementButtonID
>(event.GetId()));
273void ControlEditor::AddElement(ControlElementButtonID
id)
276 case ControlElementButtonID::ID_IO: {
277 m_mode = ControlEditorMode::MODE_INSERT;
278 auto io = std::make_shared<IOControl>(m_ioFlags, GetNextID());
279 m_elementList.push_back(io);
281 case ControlElementButtonID::ID_TF: {
282 m_mode = ControlEditorMode::MODE_INSERT;
283 auto tf = std::make_shared<TransferFunction>(GetNextID());
284 m_elementList.push_back(tf);
286 case ControlElementButtonID::ID_SUM: {
287 m_mode = ControlEditorMode::MODE_INSERT;
288 auto sum = std::make_shared<Sum>(GetNextID());
289 m_elementList.push_back(sum);
291 case ControlElementButtonID::ID_CONST: {
292 m_mode = ControlEditorMode::MODE_INSERT;
293 auto constant = std::make_shared<Constant>(GetNextID());
294 m_elementList.push_back(constant);
296 case ControlElementButtonID::ID_LIMITER: {
297 m_mode = ControlEditorMode::MODE_INSERT;
298 auto limiter = std::make_shared<Limiter>(GetNextID());
299 m_elementList.push_back(limiter);
301 case ControlElementButtonID::ID_GAIN: {
302 m_mode = ControlEditorMode::MODE_INSERT;
303 auto gain = std::make_shared<Gain>(GetNextID());
304 m_elementList.push_back(gain);
306 case ControlElementButtonID::ID_MULT: {
307 m_mode = ControlEditorMode::MODE_INSERT;
308 auto mult = std::make_shared<Multiplier>(GetNextID());
309 m_elementList.push_back(mult);
311 case ControlElementButtonID::ID_EXP: {
312 m_mode = ControlEditorMode::MODE_INSERT;
313 auto exp = std::make_shared<Exponential>(GetNextID());
314 m_elementList.push_back(exp);
316 case ControlElementButtonID::ID_RATELIM: {
317 m_mode = ControlEditorMode::MODE_INSERT;
318 auto rateLim = std::make_shared<RateLimiter>(GetNextID());
319 m_elementList.push_back(rateLim);
321 case ControlElementButtonID::ID_MATH_DIV: {
322 m_mode = ControlEditorMode::MODE_INSERT;
323 auto divider = std::make_shared<Divider>(GetNextID());
324 m_elementList.push_back(divider);
326 case ControlElementButtonID::ID_MATH_EXPR: {
327 m_mode = ControlEditorMode::MODE_INSERT;
328 auto mathExpr = std::make_shared<MathExpression>(GetNextID());
329 m_elementList.push_back(mathExpr);
334void ControlEditor::OnPaint(wxPaintEvent& event)
374 wxBufferedPaintDC dc(m_cePanel);
376 wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
381 gc->Scale(m_camera->GetScale(), m_camera->GetScale());
382 gc->Translate(m_camera->GetTranslation().m_x, m_camera->GetTranslation().m_y);
384 for (
auto line : m_connectionList) {
386 line->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
389 for (
auto element : m_elementList) {
390 element->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
394 gc->SetPen(wxPen(wxColour(0, 125, 255, 255)));
395 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 125)));
396 gc->DrawRectangle(m_selectionRect.m_x, m_selectionRect.m_y, m_selectionRect.m_width, m_selectionRect.m_height);
403void ControlEditor::OnDoubleClick(wxMouseEvent& event)
405 wxPoint2DDouble clickPoint =
event.GetPosition();
408 if (m_mode == ControlEditor::ControlEditorMode::MODE_EDIT) {
409 for (
auto& element : m_elementList) {
410 if (element->Contains(m_camera->ScreenToWorld(clickPoint))) {
411 element->ShowForm(
this, element.get());
413 auto childList = element->GetChildList();
414 for (
auto itC = childList.begin(), itEndC = childList.end(); itC != itEndC; ++itC) {
416 line->UpdatePoints();
423 if (redraw) Redraw();
426void ControlEditor::OnLeftClickDown(wxMouseEvent& event)
428 wxPoint2DDouble clickPoint =
event.GetPosition();
429 bool foundElement =
false;
431 if (m_mode == ControlEditorMode::MODE_INSERT) {
432 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
435 for (
auto& element : m_elementList) {
436 bool foundNode =
false;
437 auto nodeList = element->GetNodeList();
438 for (
auto itN = nodeList.begin(), itNEnd = nodeList.end(); itN != itNEnd; ++itN) {
440 if (node->Contains(m_camera->ScreenToWorld(clickPoint))) {
441 m_mode = ControlEditorMode::MODE_INSERT_LINE;
442 auto line = std::make_shared<ConnectionLine>(node, GetNextID());
443 m_connectionList.push_back(line);
444 element->AddChild(line.get());
445 line->AddParent(element.get());
453 element->StartMove(m_camera->ScreenToWorld(clickPoint));
456 if (element->Contains(m_camera->ScreenToWorld(clickPoint))) {
458 element->SetSelected();
461 m_mode = ControlEditor::ControlEditorMode::MODE_MOVE_ELEMENT;
465 if (m_mode != ControlEditorMode::MODE_INSERT_LINE) {
466 for (
auto& line : m_connectionList) {
467 line->StartMove(m_camera->ScreenToWorld(clickPoint));
468 if (line->Contains(m_camera->ScreenToWorld(clickPoint))) {
471 m_mode = ControlEditorMode::MODE_MOVE_LINE;
478 m_mode = ControlEditorMode::MODE_SELECTION_RECT;
479 m_startSelRect = m_camera->ScreenToWorld(clickPoint);
486void ControlEditor::OnLeftClickUp(wxMouseEvent& event)
488 bool foundNode =
false;
489 for (
auto& element : m_elementList) {
490 if (m_mode == ControlEditorMode::MODE_INSERT_LINE) {
491 auto nodeList = element->GetNodeList();
492 for (
auto node : nodeList) {
493 if (node->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
495 auto line = m_connectionList.back();
496 if (line->AppendNode(node, element.get())) {
497 line->AddParent(element.get());
498 element->AddChild(line.get());
499 line->UpdatePoints();
500 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
506 else if (m_mode == ControlEditorMode::MODE_SELECTION_RECT) {
507 if (element->Intersects(m_selectionRect)) {
508 element->SetSelected();
510 else if (!event.ControlDown()) {
511 element->SetSelected(
false);
514 else if (!event.ControlDown()) {
515 if (!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetSelected(
false); }
519 auto& lastLine = m_connectionList.back();
520 for (
auto& cLine : m_connectionList) {
521 if (m_mode == ControlEditorMode::MODE_INSERT_LINE && !foundNode && cLine.get() != lastLine.get()) {
522 if (cLine->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
524 auto iLine = m_connectionList.back();
525 if (iLine->SetParentLine(cLine.get())) {
526 cLine->AddChild(iLine.get());
527 iLine->UpdatePoints();
528 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
533 else if (m_mode == ControlEditorMode::MODE_SELECTION_RECT) {
534 if (cLine->Intersects(m_selectionRect)) {
535 cLine->SetSelected();
537 else if (!event.ControlDown()) {
538 cLine->SetSelected(
false);
541 else if (!event.ControlDown()) {
542 if (!cLine->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { cLine->SetSelected(
false); }
546 m_selectionRect = wxRect2DDouble(0, 0, 0, 0);
548 if (m_mode == ControlEditorMode::MODE_INSERT_LINE && !foundNode) {
550 auto cLine = m_connectionList.back();
552 auto nodeList = cLine->GetNodeList();
553 for (
auto itN = nodeList.begin(), itEndN = nodeList.end(); itN != itEndN; ++itN) {
555 node->SetConnected(
false);
558 auto parentList = cLine->GetParentList();
559 for (
auto it = parentList.begin(), itEnd = parentList.end(); it != itEnd; ++it) {
563 m_connectionList.pop_back();
565 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
567 else if (m_mode != ControlEditorMode::MODE_INSERT) {
568 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
575void ControlEditor::OnMiddleDown(wxMouseEvent& event)
579 case ControlEditorMode::MODE_INSERT: {
580 m_mode = ControlEditorMode::MODE_DRAG_INSERT;
582 case ControlEditorMode::MODE_PASTE: {
583 m_mode = ControlEditorMode::MODE_DRAG_PASTE;
586 m_mode = ControlEditorMode::MODE_DRAG;
589 m_camera->StartTranslation(m_camera->ScreenToWorld(event.GetPosition()));
592void ControlEditor::OnMiddleUp(wxMouseEvent& event)
595 case ControlEditorMode::MODE_DRAG_INSERT: {
596 m_mode = ControlEditorMode::MODE_INSERT;
598 case ControlEditorMode::MODE_DRAG_PASTE: {
599 m_mode = ControlEditorMode::MODE_PASTE;
601 case ControlEditorMode::MODE_INSERT:
602 case ControlEditorMode::MODE_PASTE: {
606 m_mode = ControlEditor::ControlEditorMode::MODE_EDIT;
611void ControlEditor::OnMouseMotion(wxMouseEvent& event)
613 wxPoint2DDouble clickPoint =
event.GetPosition();
617 case ControlEditorMode::MODE_INSERT: {
619 auto newElement = m_elementList.back();
620 newElement->Move(m_camera->ScreenToWorld(clickPoint));
623 case ControlEditorMode::MODE_INSERT_LINE: {
625 auto line = m_connectionList.back();
626 line->SetTemporarySecondPoint(m_camera->ScreenToWorld(clickPoint));
627 line->UpdatePoints();
630 case ControlEditorMode::MODE_DRAG:
631 case ControlEditorMode::MODE_DRAG_INSERT:
632 case ControlEditorMode::MODE_DRAG_PASTE: {
633 m_camera->SetTranslation(clickPoint);
636 case ControlEditor::ControlEditorMode::MODE_MOVE_ELEMENT: {
637 for (
auto& element : m_elementList) {
639 element->
Move(m_camera->ScreenToWorld(clickPoint));
641 for (
auto itC = childList.begin(), itEndC = childList.end(); itC != itEndC; itC++) {
643 line->UpdatePoints();
649 case ControlEditorMode::MODE_MOVE_LINE: {
650 for (
auto& line : m_connectionList) {
651 if (line->IsSelected()) {
652 line->Move(m_camera->ScreenToWorld(clickPoint));
657 case ControlEditorMode::MODE_SELECTION_RECT: {
658 wxPoint2DDouble currentPos = m_camera->ScreenToWorld(clickPoint);
660 if (currentPos.m_x < m_startSelRect.m_x) {
662 w = m_startSelRect.m_x - currentPos.m_x;
665 x = m_startSelRect.m_x;
666 w = currentPos.m_x - m_startSelRect.m_x;
668 if (currentPos.m_y < m_startSelRect.m_y) {
670 h = m_startSelRect.m_y - currentPos.m_y;
673 y = m_startSelRect.m_y;
674 h = currentPos.m_y - m_startSelRect.m_y;
677 m_selectionRect = wxRect2DDouble(x, y, w, h);
684 if (redraw) Redraw();
688void ControlEditor::OnScroll(wxMouseEvent& event)
690 if (event.GetWheelRotation() > 0)
691 m_camera->SetScale(event.GetPosition(), +0.05);
693 m_camera->SetScale(event.GetPosition(), -0.05);
698void ControlEditor::OnIdle(wxIdleEvent& event)
712void ControlEditor::OnKeyDown(wxKeyEvent& event)
714 char key =
event.GetUnicodeKey();
715 if (key != WXK_NONE) {
719 DeleteSelectedElements();
723 RotateSelectedElements(event.GetModifiers() != wxMOD_SHIFT);
732void ControlEditor::RotateSelectedElements(
bool clockwise)
734 for (
auto& element : m_elementList) {
736 element->
Rotate(clockwise);
738 for (
auto itC = childList.begin(), itEndC = childList.end(); itC != itEndC; itC++) {
740 line->UpdatePoints();
747void ControlEditor::DeleteSelectedElements()
749 for (
auto it = m_elementList.begin(); it != m_elementList.end();) {
754 for (
auto child : childList) {
759 for (
auto itCo = m_connectionList.begin(); itCo != m_connectionList.end(); ) {
760 if (itCo->get() == childLine)
761 itCo = DeleteLineFromList(itCo);
768 m_elementList.erase(it);
776 for (
auto it = m_connectionList.begin(); it != m_connectionList.end(); ) {
779 it = DeleteLineFromList(it);
786std::vector< std::shared_ptr<ConnectionLine> >::iterator ControlEditor::DeleteLineFromList(std::vector< std::shared_ptr<ConnectionLine> >::iterator& it)
791 auto childList = cLine->GetLineChildList();
792 for (
auto child : childList) {
793 for (
auto itL = m_connectionList.begin(); itL != m_connectionList.end(); ) {
794 if (itL->get() == child)
795 itL = DeleteLineFromList(itL);
802 for (
auto parent : parentList) {
803 if (parent) parent->RemoveChild(cLine);
805 if (cLine->GetParentLine()) cLine->GetParentLine()->
RemoveChild(cLine);
808 auto nodeList = cLine->GetNodeList();
809 for (
auto node : nodeList)
810 node->SetConnected(false);
812 return m_connectionList.erase(it);
815void ControlEditor::CheckConnections()
817 for (
auto it = m_connectionList.begin(); it != m_connectionList.end(); ++it) {
819 if (cLine->GetType() == ConnectionLine::ConnectionLineType::ELEMENT_ELEMENT) {
820 if (cLine->
GetParentList().size() < 2) { it = DeleteLineFromList(it); }
823 it = DeleteLineFromList(it);
828void ControlEditor::OnExportClick(wxCommandEvent& event)
832 wxFileDialog saveFileDialog(
this, _(
"Save CTL file"),
"",
"",
"CTL files (*.ctl)|*.ctl",
833 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
834 if (saveFileDialog.ShowModal() == wxID_CANCEL)
return;
836 fileHandling.SaveControl(saveFileDialog.GetPath());
837 wxFileName fileName(saveFileDialog.GetPath());
841void ControlEditor::OnImportClick(wxCommandEvent& event)
843 wxFileDialog openFileDialog(
this, _(
"Open CTL file"),
"",
"",
"CTL files (*.ctl)|*.ctl",
844 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
845 if (openFileDialog.ShowModal() == wxID_CANCEL)
return;
847 wxFileName fileName(openFileDialog.GetPath());
850 if (!fileHandling.OpenControl(fileName, m_elementList, m_connectionList)) {
851 wxMessageDialog msgDialog(
this, _(
"It was not possible to open the selected file."), _(
"Error"),
852 wxOK | wxCENTRE | wxICON_ERROR);
853 msgDialog.ShowModal();
859void ControlEditor::OnTestClick(wxCommandEvent& event)
862 m_itColourList = --m_colourList.end();
864 std::vector<IOControl*> ioList;
866 for (
auto& element : m_elementList) {
867 if (
auto io =
dynamic_cast<IOControl*
>(element.get())) {
868 ioList.push_back(io);
872 ControlSystemTest csTest(
this, ioList, &m_inputType, &m_startTime, &m_slope, &m_timeStep, &m_simTime);
873 if (csTest.ShowModal() == wxID_OK) {
874 double printStep = 1e-3;
875 double pdbStep = 1e-1;
879 std::vector<double> values;
882 std::vector<InputData> inputList;
885 std::vector<IOControl::IOFlags> realFlagValue;
886 for (
auto* io : ioList) {
887 realFlagValue.push_back(io->GetValue());
888 if (io->GetType() == Node::NodeType::NODE_OUT) {
890 io->SetValue(IOControl::IN_TEST);
891 io->SetTestValue(testData.initialValue);
892 inputList.push_back({ io->GetName(), {} });
896 wxProgressDialog pbd(_(
"Test"), _(
"Initializing..."), 100,
this,
897 wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_SMOOTH);
899 solver.InitializeValues(
false);
901 bool simStopped =
false;
902 double currentTime = 0.0;
903 double printTime = 0.0;
904 double pdbTime = 0.0;
905 std::vector<double> time;
906 std::vector<double> solution;
908 while (currentTime <= m_simTime) {
909 for (
auto* io : ioList) {
911 if (currentTime >= testData.startTime) {
912 switch (testData.type) {
914 io->SetTestValue(testData.slope);
917 io->SetTestValue(testData.slope * (currentTime - testData.startTime));
920 io->SetTestValue(testData.slope * std::pow(currentTime - testData.startTime, 2));
923 io->SetTestValue(0.0);
930 solver.SetCurrentTime(currentTime);
931 solver.SolveNextStep();
932 if (!solver.IsOK()) {
933 wxString msg = wxString::Format(_(
"Failed to solve the control system.\n%s"), solver.GetErrorMessage());
934 wxMessageDialog msgDialog(
this, msg, _(
"Error"), wxOK | wxCENTRE | wxICON_ERROR);
935 msgDialog.ShowModal();
937 currentTime = m_simTime;
940 if (printTime >= printStep) {
941 time.push_back(currentTime);
942 solution.push_back(solver.GetLastSolution());
945 for (
auto* io : ioList) {
946 if (io->GetType() == Node::NodeType::NODE_OUT) {
947 inputList[i].values.push_back(io->GetTestValue());
954 if (pdbTime > pdbStep) {
955 if (!pbd.Update((currentTime / m_simTime) * 100, wxString::Format(
"Time = %.2fs", currentTime))) {
958 currentTime = m_simTime;
963 printTime += m_timeStep;
964 currentTime += m_timeStep;
965 pdbTime += m_timeStep;
969 std::vector<ElementPlotData> epdList;
970 ElementPlotData curveData(_(
"I/O"), ElementPlotData::CurveType::CT_TEST);
972 for (
const auto& input : inputList) {
973 curveData.AddData(input.values, input.name);
974 curveData.SetPlot(i);
975 curveData.SetColour(i, GetNextColour());
979 curveData.AddData(solution, _(
"Output"));
980 curveData.SetPlot(i);
981 curveData.SetColour(i, GetNextColour());
988 epdList.push_back(curveData);
990 ChartView* cView =
new ChartView(
this, epdList, time,
static_cast<PlotLib
>(m_plotLib));
996 wxMessageDialog msgDialog(
998 wxString::Format(_(
"Failed to solve the control system.\n%s"), solver.GetErrorMessage()),
1000 wxOK | wxCENTRE | wxICON_ERROR
1003 msgDialog.ShowModal();
1007 for (
size_t i = 0; i < ioList.size(); i++) {
1008 if (ioList[i]->GetType() == Node::NodeType::NODE_OUT)
1009 ioList[i]->SetValue(realFlagValue[i]);
1014void ControlEditor::OnClose(wxCloseEvent& event)
1016 if (m_ctrlContainer) { m_ctrlContainer->FillContainer(
this); }
1020int ControlEditor::GetNextID()
1023 for (
auto& element : m_elementList) {
1024 if (element->
GetID() >
id)
id = element->
GetID();
1026 for (
auto& line : m_connectionList) {
1033void ControlEditor::BuildColourList()
1035 m_colourList.push_back(wxColour(255, 30, 0));
1036 m_colourList.push_back(wxColour(0, 30, 255));
1037 m_colourList.push_back(wxColour(0, 128, 0));
1038 m_colourList.push_back(wxColour(100, 100, 100));
1039 m_colourList.push_back(wxColour(255, 128, 0));
1040 m_colourList.push_back(wxColour(128, 0, 255));
1041 m_colourList.push_back(wxColour(0, 255, 128));
1042 m_colourList.push_back(wxColour(255, 255, 0));
1043 m_colourList.push_back(wxColour(255, 0, 255));
1044 m_colourList.push_back(wxColour(0, 255, 255));
1045 m_colourList.push_back(wxColour(128, 255, 0));
1046 m_colourList.push_back(wxColour(255, 0, 128));
1047 m_colourList.push_back(wxColour(0, 128, 255));
1048 m_colourList.push_back(wxColour(128, 128, 128));
1049 m_colourList.push_back(*wxBLACK);
1050 m_itColourList = --m_colourList.end();
1053wxColour ControlEditor::GetNextColour()
1055 if (*m_itColourList == *wxBLACK)
1056 m_itColourList = m_colourList.begin();
1060 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...