diff options
author | Thales Lima Oliveira <thaleslima.ufu@gmail.com> | 2020-07-07 23:12:04 -0300 |
---|---|---|
committer | Thales Lima Oliveira <thaleslima.ufu@gmail.com> | 2020-07-07 23:12:04 -0300 |
commit | ab30228b1a57053323363674fa7f137c0329a180 (patch) | |
tree | 50849a3680d61a2428665cc1035f1f4215870acb /Project/Workspace.cpp | |
parent | 6c0e98a2727d07e1fbb38b78c27d68e98ad09465 (diff) | |
download | PSP.git-ab30228b1a57053323363674fa7f137c0329a180.tar.gz PSP.git-ab30228b1a57053323363674fa7f137c0329a180.tar.xz PSP.git-ab30228b1a57053323363674fa7f137c0329a180.zip |
Voltage heat map implemented
Voltage heat map implemented using modern OpenGL =)
New external library required:
-GLEW
-GLFW
-GLM (incorporeted at the source)
Old memory leaks fixed =)
Diffstat (limited to 'Project/Workspace.cpp')
-rw-r--r-- | Project/Workspace.cpp | 1453 |
1 files changed, 840 insertions, 613 deletions
diff --git a/Project/Workspace.cpp b/Project/Workspace.cpp index bf0eee7..17c8134 100644 --- a/Project/Workspace.cpp +++ b/Project/Workspace.cpp @@ -18,7 +18,7 @@ #include "Camera.h" #include "Element.h" #include "Workspace.h" -//#include "Bus.h" + //#include "Bus.h" #include "Capacitor.h" #include "ElementDataObject.h" #include "HarmCurrent.h" @@ -44,6 +44,10 @@ #include "FrequencyResponseForm.h" +#include "HMPlane.h" +#include "Shader.h" +#include "Renderer.h" + // Workspace Workspace::Workspace() : WorkspaceBase(nullptr) {} Workspace::Workspace(wxWindow* parent, wxString name, wxStatusBar* statusBar, wxGLContext* sharedGLContext) @@ -56,60 +60,95 @@ Workspace::Workspace(wxWindow* parent, wxString name, wxStatusBar* statusBar, wx m_camera = new Camera(); m_selectionRect = wxRect2DDouble(0, 0, 0, 0); - for(int i = 0; i < NUM_ELEMENTS; ++i) { m_elementNumber[i] = 1; } + for (int i = 0; i < NUM_ELEMENTS; ++i) { m_elementNumber[i] = 1; } - const int widths[4] = {-3, -1, 100, 100}; + const int widths[4] = { -3, -1, 100, 100 }; m_statusBar->SetStatusWidths(4, widths); m_properties = new PropertiesData(); - + m_glCanvas->SetBackgroundStyle(wxBG_STYLE_CUSTOM); + + m_width = static_cast<float>(m_glCanvas->GetSize().x) - 1.0; + m_height = static_cast<float>(m_glCanvas->GetSize().y) - 1.0; + m_renderer = new Renderer(); } Workspace::~Workspace() { - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { - if(*it) delete *it; + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + if (*it) delete* it; } - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { - if(*it) delete *it; + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { + if (*it) delete* it; } - if(m_camera) delete m_camera; - if(m_glContext) delete m_glContext; - if(m_tipWindow) delete m_tipWindow; - if(m_properties) delete m_properties; + + delete m_hmPlane; + + if (m_camera) delete m_camera; + //if (m_isThisContextShared) { + delete m_glContext; + m_glContext = nullptr; + //} + if (m_tipWindow) delete m_tipWindow; + if (m_properties) delete m_properties; } void Workspace::OnPaint(wxPaintEvent& event) { - if(!m_glCanvas->IsShown()) return; + if (!m_glCanvas->IsShown()) return; + - //dc.Clear(); //m_glContext->SetCurrent(*m_glCanvas); m_glCanvas->SetCurrent(*m_glContext); wxPaintDC dc(m_glCanvas); - + SetViewport(); - // Set GLCanvas scale and translation. - glScaled(m_camera->GetScale(), m_camera->GetScale(), 0.0); // Scale + // Set GLCanvas scale and translation + // Legacy OpenGL + glScaled(m_camera->GetScale(), m_camera->GetScale(), 0.0); // Scale glTranslated(m_camera->GetTranslation().m_x, m_camera->GetTranslation().m_y, 0.0); // Translation + // Modern OpenGL + m_projMatrix = glm::ortho(0.0f, m_width, m_height, 0.0f, -1.0f, 1.0f); + //m_projMatrix = glm::scale(m_projMatrix, glm::vec3(m_camera->GetScale(), m_camera->GetScale(), 1.0)); + //m_projMatrix = glm::translate(m_projMatrix, glm::vec3(m_camera->GetTranslation().m_x, m_camera->GetTranslation().m_y, 0.0)); + + + m_renderer->Clear(); + // Draw + // HMPlane + if (m_hmPlane && m_showHM) { + m_hmPlane->Draw(*m_renderer, m_projMatrix); + } + // Elements - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { Element* element = *it; element->Draw(m_camera->GetTranslation(), m_camera->GetScale()); } // Texts - for(auto it = m_textList.begin(); it != m_textList.end(); ++it) { + for (auto it = m_textList.begin(); it != m_textList.end(); ++it) { Text* text = *it; text->Draw(m_camera->GetTranslation(), m_camera->GetScale()); } + + if (m_hmPlane && m_showHM) { + // Reset legacy OpenGL zoom/translation + glPushMatrix(); + glLoadIdentity(); + //m_projMatrix = glm::mat4(1.0); + //m_projMatrix = glm::ortho(0.0f, m_width, m_height, 0.0f, -1.0f, 1.0f); + m_hmPlane->DrawLabel(*m_renderer, m_projMatrix, 20.0f, 20.0f); + glPopMatrix(); + } + // Selection rectangle glLineWidth(1.0); glColor4d(0.0, 0.5, 1.0, 1.0); @@ -135,7 +174,7 @@ void Workspace::OnPaint(wxPaintEvent& event) void Workspace::SetViewport() { - + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glClearColor(1.0, 1.0, 1.0, 1.0); // White background. @@ -152,7 +191,7 @@ void Workspace::SetViewport() // Viewport fit the screen. glViewport(0, 0, width, height); - + // Set viewport to legacy OpenGL glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, width, height, 0.0); @@ -169,23 +208,24 @@ void Workspace::OnLeftClickDown(wxMouseEvent& event) bool showNewElementForm = false; bool clickOnSwitch = false; - if(m_mode == WorkspaceMode::MODE_INSERT_TEXT || m_mode == WorkspaceMode::MODE_PASTE || m_mode == WorkspaceMode::MODE_DRAG_PASTE) { + if (m_mode == WorkspaceMode::MODE_INSERT_TEXT || m_mode == WorkspaceMode::MODE_PASTE || m_mode == WorkspaceMode::MODE_DRAG_PASTE) { m_mode = WorkspaceMode::MODE_EDIT; - } else if(m_mode == WorkspaceMode::MODE_INSERT || m_mode == WorkspaceMode::MODE_DRAG_INSERT || m_mode == WorkspaceMode::MODE_DRAG_INSERT_TEXT) { + } + else if (m_mode == WorkspaceMode::MODE_INSERT || m_mode == WorkspaceMode::MODE_DRAG_INSERT || m_mode == WorkspaceMode::MODE_DRAG_INSERT_TEXT) { // Get the last element inserted on the list. newElement = *(m_elementList.end() - 1); - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { Element* element = *it; // Clicked in any element. - if(element->Contains(m_camera->ScreenToWorld(clickPoint))) { + if (element->Contains(m_camera->ScreenToWorld(clickPoint))) { // Click at a bus. - if(typeid(*element) == typeid(Bus)) { + if (typeid(*element) == typeid(Bus)) { // Select the bus. element->SetSelected(); foundElement = true; // Element found. // Add the new element's parent. If the element being inserted returns true, back to // edit mode. - if(newElement->AddParent(element, m_camera->ScreenToWorld(clickPoint))) { + if (newElement->AddParent(element, m_camera->ScreenToWorld(clickPoint))) { ValidateElementsVoltages(); m_timer->Stop(); showNewElementForm = true; @@ -195,13 +235,14 @@ void Workspace::OnLeftClickDown(wxMouseEvent& event) } } // The line element can have an undefined number of points. - if(!foundElement) { - if(typeid(*newElement) == typeid(Line)) { newElement->AddPoint(m_camera->ScreenToWorld(clickPoint)); } + if (!foundElement) { + if (typeid(*newElement) == typeid(Line)) { newElement->AddPoint(m_camera->ScreenToWorld(clickPoint)); } } foundElement = true; - } else { + } + else { bool clickPickbox = false; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { PowerElement* element = *it; element->ResetPickboxes(); // Reset pickbox state. @@ -209,44 +250,44 @@ void Workspace::OnLeftClickDown(wxMouseEvent& event) element->StartMove(m_camera->ScreenToWorld(clickPoint)); // Click in selected element node. - if(element->NodeContains(m_camera->ScreenToWorld(clickPoint)) != 0 && element->IsSelected()) { + if (element->NodeContains(m_camera->ScreenToWorld(clickPoint)) != 0 && element->IsSelected()) { m_mode = WorkspaceMode::MODE_MOVE_NODE; m_disconnectedElement = true; foundElement = true; } // Click in an element. - else if(element->Contains(m_camera->ScreenToWorld(clickPoint))) { - if(!foundElement) { + else if (element->Contains(m_camera->ScreenToWorld(clickPoint))) { + if (!foundElement) { // Select and show pickbox. element->SetSelected(); element->ShowPickbox(); foundElement = true; } // If pickbox contains the click, move the pickbox - if(element->PickboxContains(m_camera->ScreenToWorld(clickPoint))) { + if (element->PickboxContains(m_camera->ScreenToWorld(clickPoint))) { m_mode = WorkspaceMode::MODE_MOVE_PICKBOX; clickPickbox = true; } // If didn't found a pickbox, move the element - if(!clickPickbox) { m_mode = WorkspaceMode::MODE_MOVE_ELEMENT; } + if (!clickPickbox) { m_mode = WorkspaceMode::MODE_MOVE_ELEMENT; } } // Click in a switch. - else if(element->SwitchesContains(m_camera->ScreenToWorld(clickPoint))) { + else if (element->SwitchesContains(m_camera->ScreenToWorld(clickPoint))) { element->SetOnline(element->IsOnline() ? false : true); clickOnSwitch = true; } } // Text element - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { Text* text = *it; text->StartMove(m_camera->ScreenToWorld(clickPoint)); - if(text->Contains(m_camera->ScreenToWorld(clickPoint))) { - if(!foundElement) { + if (text->Contains(m_camera->ScreenToWorld(clickPoint))) { + if (!foundElement) { text->SetSelected(); m_mode = WorkspaceMode::MODE_MOVE_ELEMENT; foundElement = true; @@ -255,7 +296,7 @@ void Workspace::OnLeftClickDown(wxMouseEvent& event) } } - if(!foundElement) { + if (!foundElement) { m_mode = WorkspaceMode::MODE_SELECTION_RECT; m_startSelRect = m_camera->ScreenToWorld(clickPoint); } @@ -263,13 +304,13 @@ void Workspace::OnLeftClickDown(wxMouseEvent& event) Redraw(); UpdateStatusBar(); - if(showNewElementForm) { - if(newElement) { + if (showNewElementForm) { + if (newElement) { newElement->ShowForm(this, newElement); - if(m_continuousCalc) RunStaticStudies(); + if (m_continuousCalc) RunStaticStudies(); } } - if(clickOnSwitch && m_continuousCalc) RunStaticStudies(); + if (clickOnSwitch && m_continuousCalc) RunStaticStudies(); event.Skip(); } @@ -280,15 +321,15 @@ void Workspace::OnLeftDoubleClick(wxMouseEvent& event) bool clickOnSwitch = false; bool redraw = false; - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { PowerElement* element = *it; // Click in an element. - if(element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { + if (element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { bool elementIsBus = false; Bus oldBus; Bus* currentBus = nullptr; - if((currentBus = dynamic_cast<Bus*>(element))) { + if ((currentBus = dynamic_cast<Bus*>(element))) { elementIsBus = true; oldBus = *currentBus; } @@ -299,19 +340,19 @@ void Workspace::OnLeftDoubleClick(wxMouseEvent& event) // If the edited element is a bus and was changed the rated voltage, this voltage must be // propagated through the lines - if(elementIsBus) { + if (elementIsBus) { // The voltage was changed - if(oldBus.GetElectricalData().nominalVoltage != currentBus->GetElectricalData().nominalVoltage || - oldBus.GetElectricalData().nominalVoltageUnit != - currentBus->GetElectricalData().nominalVoltageUnit) { + if (oldBus.GetElectricalData().nominalVoltage != currentBus->GetElectricalData().nominalVoltage || + oldBus.GetElectricalData().nominalVoltageUnit != + currentBus->GetElectricalData().nominalVoltageUnit) { // Check if the bus has line as child. std::vector<Element*> childList = element->GetChildList(); - for(auto itc = childList.begin(), itcEnd = childList.end(); itc != itcEnd; ++itc) { + for (auto itc = childList.begin(), itcEnd = childList.end(); itc != itcEnd; ++itc) { Element* child = *itc; - if(typeid(*child) == typeid(Line)) { + if (typeid(*child) == typeid(Line)) { wxMessageDialog msgDialog(this, _("Do you want to change the rated voltage of the path?"), - _("Warning"), wxYES_NO | wxCENTRE | wxICON_WARNING); - if(msgDialog.ShowModal() == wxID_YES) + _("Warning"), wxYES_NO | wxCENTRE | wxICON_WARNING); + if (msgDialog.ShowModal() == wxID_YES) ValidateBusesVoltages(element); else { auto data = currentBus->GetElectricalData(); @@ -328,56 +369,56 @@ void Workspace::OnLeftDoubleClick(wxMouseEvent& event) } // Click in a switch. - else if(element->SwitchesContains(m_camera->ScreenToWorld(event.GetPosition()))) { + else if (element->SwitchesContains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetOnline(element->IsOnline() ? false : true); clickOnSwitch = true; } } // Text element - for(auto it = m_textList.begin(); it != m_textList.end(); ++it) { + for (auto it = m_textList.begin(); it != m_textList.end(); ++it) { Text* text = *it; - if(text->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { + if (text->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { text->ShowForm(this, GetElementList()); redraw = true; } } - if(elementEdited) { + if (elementEdited) { UpdateTextElements(); - if(m_continuousCalc) RunStaticStudies(); + if (m_continuousCalc) RunStaticStudies(); } - if(clickOnSwitch && m_continuousCalc) RunStaticStudies(); + if (clickOnSwitch && m_continuousCalc) RunStaticStudies(); - if(redraw) Redraw(); + if (redraw) Redraw(); m_timer->Start(); } void Workspace::OnRightClickDown(wxMouseEvent& event) { bool redraw = false; - if(m_mode == WorkspaceMode::MODE_EDIT) { - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + if (m_mode == WorkspaceMode::MODE_EDIT) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { Element* element = *it; - if(element->IsSelected()) { + if (element->IsSelected()) { // Show context menu. - if(element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { + if (element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->ShowPickbox(false); wxMenu menu; - if(element->GetContextMenu(menu)) { + if (element->GetContextMenu(menu)) { m_timer->Stop(); menu.SetClientData(element); menu.Bind(wxEVT_COMMAND_MENU_SELECTED, &Workspace::OnPopupClick, this); PopupMenu(&menu); redraw = true; - if(!menu.GetClientData()) break; + if (!menu.GetClientData()) break; } element->ResetPickboxes(); } } } } - if(redraw) Redraw(); + if (redraw) Redraw(); m_timer->Start(); } @@ -390,22 +431,22 @@ void Workspace::OnLeftClickUp(wxMouseEvent& event) bool updateVoltages = false; auto itnp = m_elementList.begin(); - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { Element* element = *it; // The user was moving a pickbox. - if(m_mode == WorkspaceMode::MODE_MOVE_PICKBOX) { + if (m_mode == WorkspaceMode::MODE_MOVE_PICKBOX) { // Catch only the element that have the pickbox shown. - if(element->IsPickboxShown()) { + if (element->IsPickboxShown()) { // If the element is a bus, check if a node is outside. - if(typeid(*element) == typeid(Bus)) { + if (typeid(*element) == typeid(Bus)) { // Get all the bus children. - for(int i = 0; i < (int)m_elementList.size(); i++) { + for (int i = 0; i < (int)m_elementList.size(); i++) { Element* child = m_elementList[i]; - for(int j = 0; j < (int)child->GetParentList().size(); j++) { + for (int j = 0; j < (int)child->GetParentList().size(); j++) { Element* parent = child->GetParentList()[j]; // The child have a parent that is the element. - if(parent == element) { + if (parent == element) { child->UpdateNodes(); m_disconnectedElement = true; } @@ -415,18 +456,20 @@ void Workspace::OnLeftClickUp(wxMouseEvent& event) } } - if(m_mode == WorkspaceMode::MODE_SELECTION_RECT) { - if(element->Intersects(m_selectionRect)) { + if (m_mode == WorkspaceMode::MODE_SELECTION_RECT) { + if (element->Intersects(m_selectionRect)) { element->SetSelected(); - } else if(!event.ControlDown()) { + } + else if (!event.ControlDown()) { element->SetSelected(false); } - } else if(m_mode == WorkspaceMode::MODE_MOVE_NODE) { - if(element->IsSelected()) { - for(int i = 0; i < (int)m_elementList.size(); i++) { + } + else if (m_mode == WorkspaceMode::MODE_MOVE_NODE) { + if (element->IsSelected()) { + for (int i = 0; i < (int)m_elementList.size(); i++) { Element* parent = m_elementList[i]; - if(typeid(*parent) == typeid(Bus)) { - if(element->SetNodeParent(parent)) { + if (typeid(*parent) == typeid(Bus)) { + if (element->SetNodeParent(parent)) { parent->AddChild(element); findNewParent = true; itnp = it; @@ -437,15 +480,17 @@ void Workspace::OnLeftClickUp(wxMouseEvent& event) } // element->ResetNodes(); } - } else { + } + else { // Deselect - if(!event.ControlDown()) { - if(!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetSelected(false); } + if (!event.ControlDown()) { + if (!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetSelected(false); } } - if(element->PickboxContains(m_camera->ScreenToWorld(event.GetPosition()))) { + if (element->PickboxContains(m_camera->ScreenToWorld(event.GetPosition()))) { foundPickbox = true; - } else { + } + else { element->ShowPickbox(false); element->ResetPickboxes(); } @@ -453,35 +498,43 @@ void Workspace::OnLeftClickUp(wxMouseEvent& event) } // Text element - for(auto it = m_textList.begin(); it != m_textList.end(); it++) { + for (auto it = m_textList.begin(); it != m_textList.end(); it++) { Text* text = *it; - if(m_mode == WorkspaceMode::MODE_SELECTION_RECT) { - if(text->Intersects(m_selectionRect)) { + if (m_mode == WorkspaceMode::MODE_SELECTION_RECT) { + if (text->Intersects(m_selectionRect)) { text->SetSelected(); - } else if(!event.ControlDown()) { + } + else if (!event.ControlDown()) { text->SetSelected(false); } - } else if(!event.ControlDown()) { - if(!text->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { text->SetSelected(false); } + } + else if (!event.ControlDown()) { + if (!text->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { text->SetSelected(false); } } } - if(findNewParent) { + if (findNewParent) { std::rotate(itnp, itnp + 1, m_elementList.end()); updateVoltages = true; } - if(!foundPickbox) { SetCursor(wxCURSOR_ARROW); } + if (!foundPickbox) { SetCursor(wxCURSOR_ARROW); } - if(m_mode != WorkspaceMode::MODE_INSERT) { m_mode = WorkspaceMode::MODE_EDIT; } + if (m_mode != WorkspaceMode::MODE_INSERT) { m_mode = WorkspaceMode::MODE_EDIT; } - if(updateVoltages) { ValidateElementsVoltages(); } + if (updateVoltages) { ValidateElementsVoltages(); } - if(m_continuousCalc && m_disconnectedElement) { + if (m_continuousCalc && m_disconnectedElement) { m_disconnectedElement = false; RunStaticStudies(); } m_selectionRect = wxRect2DDouble(0, 0, 0, 0); + + if (m_hmPlane && m_showHM) { + m_showHMTimer = true; + m_timerHeatMap->Start(); + } + Redraw(); UpdateStatusBar(); } @@ -489,124 +542,136 @@ void Workspace::OnLeftClickUp(wxMouseEvent& event) void Workspace::OnMouseMotion(wxMouseEvent& event) { bool redraw = false; - switch(m_mode) { - case WorkspaceMode::MODE_INSERT: { - Element* newElement = *(m_elementList.end() - 1); // Get the last element in the list. - newElement->SetPosition(m_camera->ScreenToWorld(event.GetPosition())); - redraw = true; - } break; - - case WorkspaceMode::MODE_INSERT_TEXT: { - Text* newText = *(m_textList.end() - 1); - newText->SetPosition(m_camera->ScreenToWorld(event.GetPosition())); - redraw = true; - } break; - - case WorkspaceMode::MODE_DRAG: - case WorkspaceMode::MODE_DRAG_INSERT: - case WorkspaceMode::MODE_DRAG_INSERT_TEXT: - case WorkspaceMode::MODE_DRAG_PASTE: { - m_camera->SetTranslation(event.GetPosition()); - redraw = true; - } break; - - case WorkspaceMode::MODE_EDIT: { - bool foundPickbox = false; - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { - Element* element = *it; - if(element->IsSelected()) { - // Show element pickbox (when it has) if the mouse is over the selected object. - if(element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { - element->ShowPickbox(); - redraw = true; - - // If the mouse is over a pickbox set correct mouse cursor. - if(element->PickboxContains(m_camera->ScreenToWorld(event.GetPosition()))) { - foundPickbox = true; - SetCursor(element->GetBestPickboxCursor()); - } else if(!foundPickbox) { - SetCursor(wxCURSOR_ARROW); - element->ResetPickboxes(); - } - } else if(!foundPickbox) { - if(element->IsPickboxShown()) redraw = true; + switch (m_mode) { + case WorkspaceMode::MODE_INSERT: { + Element* newElement = *(m_elementList.end() - 1); // Get the last element in the list. + newElement->SetPosition(m_camera->ScreenToWorld(event.GetPosition())); + redraw = true; + } break; + + case WorkspaceMode::MODE_INSERT_TEXT: { + Text* newText = *(m_textList.end() - 1); + newText->SetPosition(m_camera->ScreenToWorld(event.GetPosition())); + redraw = true; + } break; + + case WorkspaceMode::MODE_DRAG: + case WorkspaceMode::MODE_DRAG_INSERT: + case WorkspaceMode::MODE_DRAG_INSERT_TEXT: + case WorkspaceMode::MODE_DRAG_PASTE: { + m_camera->SetTranslation(event.GetPosition()); + redraw = true; + } break; + + case WorkspaceMode::MODE_EDIT: { + bool foundPickbox = false; + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + Element* element = *it; + if (element->IsSelected()) { + // Show element pickbox (when it has) if the mouse is over the selected object. + if (element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { + element->ShowPickbox(); + redraw = true; - element->ShowPickbox(false); - element->ResetPickboxes(); + // If the mouse is over a pickbox set correct mouse cursor. + if (element->PickboxContains(m_camera->ScreenToWorld(event.GetPosition()))) { + foundPickbox = true; + SetCursor(element->GetBestPickboxCursor()); + } + else if (!foundPickbox) { SetCursor(wxCURSOR_ARROW); + element->ResetPickboxes(); } } - } - } break; + else if (!foundPickbox) { + if (element->IsPickboxShown()) redraw = true; - case WorkspaceMode::MODE_MOVE_NODE: { - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { - Element* element = *it; - if(element->IsSelected()) { - element->MoveNode(nullptr, m_camera->ScreenToWorld(event.GetPosition())); - redraw = true; + element->ShowPickbox(false); + element->ResetPickboxes(); + SetCursor(wxCURSOR_ARROW); } } - } break; + } + } break; - case WorkspaceMode::MODE_MOVE_PICKBOX: { - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { - Element* element = *it; - if(element->IsSelected()) { - element->MovePickbox(m_camera->ScreenToWorld(event.GetPosition())); - redraw = true; - } + case WorkspaceMode::MODE_MOVE_NODE: { + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + Element* element = *it; + if (element->IsSelected()) { + element->MoveNode(nullptr, m_camera->ScreenToWorld(event.GetPosition())); + redraw = true; } - } break; + } + } break; - case WorkspaceMode::MODE_MOVE_ELEMENT: - case WorkspaceMode::MODE_PASTE: { - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { - Element* element = *it; - if(element->IsSelected()) { - element->Move(m_camera->ScreenToWorld(event.GetPosition())); - // Move child nodes - std::vector<Element*> childList = element->GetChildList(); - for(auto it = childList.begin(), itEnd = childList.end(); it != itEnd; ++it) { - (*it)->MoveNode(element, m_camera->ScreenToWorld(event.GetPosition())); - } - redraw = true; - } - } - // Text element motion - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; it++) { - Text* text = *it; - if(text->IsSelected()) { - text->Move(m_camera->ScreenToWorld(event.GetPosition())); - redraw = true; - } + case WorkspaceMode::MODE_MOVE_PICKBOX: { + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + Element* element = *it; + if (element->IsSelected()) { + element->MovePickbox(m_camera->ScreenToWorld(event.GetPosition())); + redraw = true; } - } break; + } + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + } + } break; - case WorkspaceMode::MODE_SELECTION_RECT: { - wxPoint2DDouble currentPos = m_camera->ScreenToWorld(event.GetPosition()); - double x, y, w, h; - if(currentPos.m_x < m_startSelRect.m_x) { - x = currentPos.m_x; - w = m_startSelRect.m_x - currentPos.m_x; - } else { - x = m_startSelRect.m_x; - w = currentPos.m_x - m_startSelRect.m_x; + case WorkspaceMode::MODE_MOVE_ELEMENT: + case WorkspaceMode::MODE_PASTE: { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + Element* element = *it; + if (element->IsSelected()) { + element->Move(m_camera->ScreenToWorld(event.GetPosition())); + // Move child nodes + std::vector<Element*> childList = element->GetChildList(); + for (auto it = childList.begin(), itEnd = childList.end(); it != itEnd; ++it) { + (*it)->MoveNode(element, m_camera->ScreenToWorld(event.GetPosition())); + } + redraw = true; } - if(currentPos.m_y < m_startSelRect.m_y) { - y = currentPos.m_y; - h = m_startSelRect.m_y - currentPos.m_y; - } else { - y = m_startSelRect.m_y; - h = currentPos.m_y - m_startSelRect.m_y; + } + // Text element motion + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; it++) { + Text* text = *it; + if (text->IsSelected()) { + text->Move(m_camera->ScreenToWorld(event.GetPosition())); + redraw = true; } + } + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + } + } break; + + case WorkspaceMode::MODE_SELECTION_RECT: { + wxPoint2DDouble currentPos = m_camera->ScreenToWorld(event.GetPosition()); + double x, y, w, h; + if (currentPos.m_x < m_startSelRect.m_x) { + x = currentPos.m_x; + w = m_startSelRect.m_x - currentPos.m_x; + } + else { + x = m_startSelRect.m_x; + w = currentPos.m_x - m_startSelRect.m_x; + } + if (currentPos.m_y < m_startSelRect.m_y) { + y = currentPos.m_y; + h = m_startSelRect.m_y - currentPos.m_y; + } + else { + y = m_startSelRect.m_y; + h = currentPos.m_y - m_startSelRect.m_y; + } - m_selectionRect = wxRect2DDouble(x, y, w, h); - redraw = true; - } break; + m_selectionRect = wxRect2DDouble(x, y, w, h); + redraw = true; + } break; } - if(redraw) Redraw(); + if (redraw) { + Redraw(); + } m_camera->UpdateMousePosition(event.GetPosition()); UpdateStatusBar(); m_timer->Start(); // Restart the timer. @@ -616,57 +681,74 @@ void Workspace::OnMouseMotion(wxMouseEvent& event) void Workspace::OnMiddleDown(wxMouseEvent& event) { // Set to drag mode. - switch(m_mode) { - case WorkspaceMode::MODE_INSERT: { - m_mode = WorkspaceMode::MODE_DRAG_INSERT; - } break; - case WorkspaceMode::MODE_INSERT_TEXT: { - m_mode = WorkspaceMode::MODE_DRAG_INSERT_TEXT; - } break; - case WorkspaceMode::MODE_PASTE: { - m_mode = WorkspaceMode::MODE_DRAG_PASTE; - } break; - default: { - m_mode = WorkspaceMode::MODE_DRAG; - } break; + switch (m_mode) { + case WorkspaceMode::MODE_INSERT: { + m_mode = WorkspaceMode::MODE_DRAG_INSERT; + } break; + case WorkspaceMode::MODE_INSERT_TEXT: { + m_mode = WorkspaceMode::MODE_DRAG_INSERT_TEXT; + } break; + case WorkspaceMode::MODE_PASTE: { + m_mode = WorkspaceMode::MODE_DRAG_PASTE; + } break; + default: { + m_mode = WorkspaceMode::MODE_DRAG; + } break; } m_camera->StartTranslation(m_camera->ScreenToWorld(event.GetPosition())); UpdateStatusBar(); + + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + } + event.Skip(); } void Workspace::OnMiddleUp(wxMouseEvent& event) { - switch(m_mode) { - case WorkspaceMode::MODE_DRAG_INSERT: { - m_mode = WorkspaceMode::MODE_INSERT; - } break; - case WorkspaceMode::MODE_DRAG_INSERT_TEXT: { - m_mode = WorkspaceMode::MODE_INSERT_TEXT; - } break; - case WorkspaceMode::MODE_DRAG_PASTE: { - m_mode = WorkspaceMode::MODE_PASTE; - } break; - case WorkspaceMode::MODE_INSERT: - case WorkspaceMode::MODE_INSERT_TEXT: - case WorkspaceMode::MODE_PASTE: { - // Does nothing. - } break; - default: { - m_mode = WorkspaceMode::MODE_EDIT; - } break; + switch (m_mode) { + case WorkspaceMode::MODE_DRAG_INSERT: { + m_mode = WorkspaceMode::MODE_INSERT; + } break; + case WorkspaceMode::MODE_DRAG_INSERT_TEXT: { + m_mode = WorkspaceMode::MODE_INSERT_TEXT; + } break; + case WorkspaceMode::MODE_DRAG_PASTE: { + m_mode = WorkspaceMode::MODE_PASTE; + } break; + case WorkspaceMode::MODE_INSERT: + case WorkspaceMode::MODE_INSERT_TEXT: + case WorkspaceMode::MODE_PASTE: { + // Does nothing. + } break; + default: { + m_mode = WorkspaceMode::MODE_EDIT; + } break; } UpdateStatusBar(); + + if (m_hmPlane && m_showHM) { + UpdateHeatMap(); + Redraw(); + } + event.Skip(); } void Workspace::OnScroll(wxMouseEvent& event) { - if(event.GetWheelRotation() > 0) + if (event.GetWheelRotation() > 0) m_camera->SetScale(event.GetPosition(), +0.05); else m_camera->SetScale(event.GetPosition(), -0.05); + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + m_showHMTimer = true; + m_timerHeatMap->Start(); + } + UpdateStatusBar(); Redraw(); } @@ -674,167 +756,181 @@ void Workspace::OnScroll(wxMouseEvent& event) void Workspace::OnKeyDown(wxKeyEvent& event) { bool insertingElement = false; - if(m_mode == WorkspaceMode::MODE_INSERT || m_mode == WorkspaceMode::MODE_INSERT_TEXT) insertingElement = true; + if (m_mode == WorkspaceMode::MODE_INSERT || m_mode == WorkspaceMode::MODE_INSERT_TEXT) insertingElement = true; char key = event.GetUnicodeKey(); - if(key != WXK_NONE) { - switch(key) { - case WXK_ESCAPE: // Cancel operations. - { - if(m_mode == WorkspaceMode::MODE_INSERT) { - m_elementList.pop_back(); // Removes the last element being inserted. - m_mode = WorkspaceMode::MODE_EDIT; - Redraw(); - } else if(m_mode == WorkspaceMode::MODE_INSERT_TEXT) { - m_textList.pop_back(); - m_mode = WorkspaceMode::MODE_EDIT; - Redraw(); - } - } break; - case WXK_DELETE: // Delete selected elements - { - DeleteSelectedElements(); - } break; - case 'A': { - if(!insertingElement) { - Text* newBus = new Text(m_camera->ScreenToWorld(event.GetPosition())); - m_textList.push_back(newBus); - m_mode = WorkspaceMode::MODE_INSERT_TEXT; - m_statusBar->SetStatusText(_("Insert Text: Click to insert, ESC to cancel.")); - Redraw(); - } - } break; - case 'F': { - if(event.GetModifiers() == wxMOD_SHIFT) { Fit(); } - } break; - case 'R': // Rotate the selected elements. - { - RotateSelectedElements(event.GetModifiers() != wxMOD_SHIFT); - } break; - case 'B': // Insert a bus. - { - if(!insertingElement) { - Bus* newBus = new Bus(m_camera->ScreenToWorld(event.GetPosition()), - wxString::Format(_("Bus %d"), GetElementNumber(ID_BUS))); - IncrementElementNumber(ID_BUS); - m_elementList.push_back(newBus); + if (key != WXK_NONE) { + switch (key) { + case WXK_ESCAPE: // Cancel operations. + { + if (m_mode == WorkspaceMode::MODE_INSERT) { + m_elementList.pop_back(); // Removes the last element being inserted. + m_mode = WorkspaceMode::MODE_EDIT; + Redraw(); + } + else if (m_mode == WorkspaceMode::MODE_INSERT_TEXT) { + m_textList.pop_back(); + m_mode = WorkspaceMode::MODE_EDIT; + Redraw(); + } + } break; + case WXK_DELETE: // Delete selected elements + { + DeleteSelectedElements(); + } break; + case 'A': { + if (!insertingElement) { + Text* newBus = new Text(m_camera->ScreenToWorld(event.GetPosition())); + m_textList.push_back(newBus); + m_mode = WorkspaceMode::MODE_INSERT_TEXT; + m_statusBar->SetStatusText(_("Insert Text: Click to insert, ESC to cancel.")); + Redraw(); + } + } break; + case 'F': { + if (event.GetModifiers() == wxMOD_SHIFT) { Fit(); } + } break; + case 'R': // Rotate the selected elements. + { + RotateSelectedElements(event.GetModifiers() != wxMOD_SHIFT); + } break; + case 'B': // Insert a bus. + { + if (!insertingElement) { + Bus* newBus = new Bus(m_camera->ScreenToWorld(event.GetPosition()), + wxString::Format(_("Bus %d"), GetElementNumber(ID_BUS))); + IncrementElementNumber(ID_BUS); + m_elementList.push_back(newBus); + m_mode = WorkspaceMode::MODE_INSERT; + m_statusBar->SetStatusText(_("Insert Bus: Click to insert, ESC to cancel.")); + Redraw(); + } + } break; + case 'L': { + if (!insertingElement) { + if (!event.ControlDown() && event.ShiftDown()) { // Insert a load. + Load* newLoad = new Load(wxString::Format(_("Load %d"), GetElementNumber(ID_LOAD))); + IncrementElementNumber(ID_LOAD); + m_elementList.push_back(newLoad); m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Bus: Click to insert, ESC to cancel.")); - Redraw(); + m_statusBar->SetStatusText(_("Insert Load: Click on a buses, ESC to cancel.")); } - } break; - case 'L': { - if(!insertingElement) { - if(!event.ControlDown() && event.ShiftDown()) { // Insert a load. - Load* newLoad = new Load(wxString::Format(_("Load %d"), GetElementNumber(ID_LOAD))); - IncrementElementNumber(ID_LOAD); - m_elementList.push_back(newLoad); - m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Load: Click on a buses, ESC to cancel.")); - } else if(!event.ControlDown() && !event.ShiftDown()) { // Insert a power line. - Line* newLine = new Line(wxString::Format(_("Line %d"), GetElementNumber(ID_LINE))); - IncrementElementNumber(ID_LINE); - m_elementList.push_back(newLine); - m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Line: Click on two buses, ESC to cancel.")); - } - Redraw(); - } - // Tests - Ctrl + Shift + L - } break; - case 'T': // Insert a transformer. - { - if(!insertingElement) { - Transformer* newTransformer = - new Transformer(wxString::Format(_("Transformer %d"), GetElementNumber(ID_TRANSFORMER))); - IncrementElementNumber(ID_TRANSFORMER); - m_elementList.push_back(newTransformer); + else if (!event.ControlDown() && !event.ShiftDown()) { // Insert a power line. + Line* newLine = new Line(wxString::Format(_("Line %d"), GetElementNumber(ID_LINE))); + IncrementElementNumber(ID_LINE); + m_elementList.push_back(newLine); m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Transformer: Click on two buses, ESC to cancel.")); - Redraw(); + m_statusBar->SetStatusText(_("Insert Line: Click on two buses, ESC to cancel.")); } - } break; - case 'G': // Insert a generator. - { - if(!insertingElement) { - SyncGenerator* newGenerator = - new SyncGenerator(wxString::Format(_("Generator %d"), GetElementNumber(ID_SYNCGENERATOR))); - IncrementElementNumber(ID_SYNCGENERATOR); - m_elementList.push_back(newGenerator); + Redraw(); + } + // Tests - Ctrl + Shift + L + } break; + case 'T': // Insert a transformer. + { + if (!insertingElement) { + Transformer* newTransformer = + new Transformer(wxString::Format(_("Transformer %d"), GetElementNumber(ID_TRANSFORMER))); + IncrementElementNumber(ID_TRANSFORMER); + m_elementList.push_back(newTransformer); + m_mode = WorkspaceMode::MODE_INSERT; + m_statusBar->SetStatusText(_("Insert Transformer: Click on two buses, ESC to cancel.")); + Redraw(); + } + } break; + case 'G': // Insert a generator. + { + if (!insertingElement) { + SyncGenerator* newGenerator = + new SyncGenerator(wxString::Format(_("Generator %d"), GetElementNumber(ID_SYNCGENERATOR))); + IncrementElementNumber(ID_SYNCGENERATOR); + m_elementList.push_back(newGenerator); + m_mode = WorkspaceMode::MODE_INSERT; + m_statusBar->SetStatusText(_("Insert Generator: Click on a buses, ESC to cancel.")); + Redraw(); + } + } break; + case 'I': { + if (!insertingElement) { + if (event.GetModifiers() == wxMOD_SHIFT) { // Insert an inductor. + Inductor* newInductor = + new Inductor(wxString::Format(_("Inductor %d"), GetElementNumber(ID_INDUCTOR))); + IncrementElementNumber(ID_INDUCTOR); + m_elementList.push_back(newInductor); m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Generator: Click on a buses, ESC to cancel.")); - Redraw(); + m_statusBar->SetStatusText(_("Insert Inductor: Click on a buses, ESC to cancel.")); } - } break; - case 'I': { - if(!insertingElement) { - if(event.GetModifiers() == wxMOD_SHIFT) { // Insert an inductor. - Inductor* newInductor = - new Inductor(wxString::Format(_("Inductor %d"), GetElementNumber(ID_INDUCTOR))); - IncrementElementNumber(ID_INDUCTOR); - m_elementList.push_back(newInductor); - m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Inductor: Click on a buses, ESC to cancel.")); - } else // Insert an induction motor. - { - IndMotor* newIndMotor = - new IndMotor(wxString::Format(_("Induction motor %d"), GetElementNumber(ID_INDMOTOR))); - IncrementElementNumber(ID_INDMOTOR); - m_elementList.push_back(newIndMotor); - m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Induction Motor: Click on a buses, ESC to cancel.")); - } - Redraw(); + else // Insert an induction motor. + { + IndMotor* newIndMotor = + new IndMotor(wxString::Format(_("Induction motor %d"), GetElementNumber(ID_INDMOTOR))); + IncrementElementNumber(ID_INDMOTOR); + m_elementList.push_back(newIndMotor); + m_mode = WorkspaceMode::MODE_INSERT; + m_statusBar->SetStatusText(_("Insert Induction Motor: Click on a buses, ESC to cancel.")); } - } break; - case 'K': // Insert a synchronous condenser. - { - if(!insertingElement) { - SyncMotor* newSyncCondenser = - new SyncMotor(wxString::Format(_("Synchronous condenser %d"), GetElementNumber(ID_SYNCMOTOR))); - IncrementElementNumber(ID_SYNCMOTOR); - m_elementList.push_back(newSyncCondenser); + Redraw(); + } + } break; + case 'K': // Insert a synchronous condenser. + { + if (!insertingElement) { + SyncMotor* newSyncCondenser = + new SyncMotor(wxString::Format(_("Synchronous condenser %d"), GetElementNumber(ID_SYNCMOTOR))); + IncrementElementNumber(ID_SYNCMOTOR); + m_elementList.push_back(newSyncCondenser); + m_mode = WorkspaceMode::MODE_INSERT; + m_statusBar->SetStatusText(_("Insert Synchronous Condenser: Click on a buses, ESC to cancel.")); + Redraw(); + } + } break; + case 'C': { + if (!insertingElement) { + if (event.GetModifiers() == wxMOD_SHIFT) { // Insert a capacitor. + Capacitor* newCapacitor = + new Capacitor(wxString::Format(_("Capacitor %d"), GetElementNumber(ID_CAPACITOR))); + IncrementElementNumber(ID_CAPACITOR); + m_elementList.push_back(newCapacitor); m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Synchronous Condenser: Click on a buses, ESC to cancel.")); + m_statusBar->SetStatusText(_("Insert Capacitor: Click on a buses, ESC to cancel.")); Redraw(); } - } break; - case 'C': { - if(!insertingElement) { - if(event.GetModifiers() == wxMOD_SHIFT) { // Insert a capacitor. - Capacitor* newCapacitor = - new Capacitor(wxString::Format(_("Capacitor %d"), GetElementNumber(ID_CAPACITOR))); - IncrementElementNumber(ID_CAPACITOR); - m_elementList.push_back(newCapacitor); - m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText(_("Insert Capacitor: Click on a buses, ESC to cancel.")); - Redraw(); - } else if(event.GetModifiers() == wxMOD_CONTROL) { // Copy. - CopySelection(); - } + else if (event.GetModifiers() == wxMOD_CONTROL) { // Copy. + CopySelection(); } - } break; - case 'H': { - if(!insertingElement) { - if(event.GetModifiers() == wxMOD_SHIFT) { // Insert an harmonic current source. - HarmCurrent* newHarmCurrent = new HarmCurrent( - wxString::Format(_("Harmonic Current %d"), GetElementNumber(ID_HARMCURRENT))); - IncrementElementNumber(ID_HARMCURRENT); - m_elementList.push_back(newHarmCurrent); - m_mode = WorkspaceMode::MODE_INSERT; - m_statusBar->SetStatusText( - _("Insert Harmonic Current Source: Click on a buses, ESC to cancel.")); + } + } break; + case 'H': { + if (!insertingElement) { + if (event.ShiftDown() && event.ControlDown()) { + if (!m_showHM) { + m_showHM = true; + UpdateHeatMap(); } - Redraw(); + else { + m_showHM = false; + } + } - } break; - case 'V': { - if(!insertingElement) { - if(event.GetModifiers() == wxMOD_CONTROL) { Paste(); } + else if (event.GetModifiers() == wxMOD_SHIFT) { // Insert an harmonic current source. + HarmCurrent* newHarmCurrent = new HarmCurrent( + wxString::Format(_("Harmonic Current %d"), GetElementNumber(ID_HARMCURRENT))); + IncrementElementNumber(ID_HARMCURRENT); + m_elementList.push_back(newHarmCurrent); + m_mode = WorkspaceMode::MODE_INSERT; + m_statusBar->SetStatusText( + _("Insert Harmonic Current Source: Click on a buses, ESC to cancel.")); } - } break; - default: - break; + Redraw(); + } + } break; + case 'V': { + if (!insertingElement) { + if (event.GetModifiers() == wxMOD_CONTROL) { Paste(); } + } + } break; + default: + break; } } @@ -844,31 +940,31 @@ void Workspace::OnKeyDown(wxKeyEvent& event) void Workspace::UpdateStatusBar() { - switch(m_mode) { - case WorkspaceMode::MODE_DRAG: { - m_statusBar->SetStatusText(_("MODE: DRAG"), 1); - } break; - - case WorkspaceMode::MODE_PASTE: - case WorkspaceMode::MODE_DRAG_PASTE: { - m_statusBar->SetStatusText(_("MODE: PASTE"), 1); - } - - case WorkspaceMode::MODE_INSERT: - case WorkspaceMode::MODE_INSERT_TEXT: - case WorkspaceMode::MODE_DRAG_INSERT: - case WorkspaceMode::MODE_DRAG_INSERT_TEXT: { - m_statusBar->SetStatusText(_("MODE: INSERT"), 1); - } break; + switch (m_mode) { + case WorkspaceMode::MODE_DRAG: { + m_statusBar->SetStatusText(_("MODE: DRAG"), 1); + } break; + + case WorkspaceMode::MODE_PASTE: + case WorkspaceMode::MODE_DRAG_PASTE: { + m_statusBar->SetStatusText(_("MODE: PASTE"), 1); + } - case WorkspaceMode::MODE_MOVE_ELEMENT: - case WorkspaceMode::MODE_MOVE_PICKBOX: - case WorkspaceMode::MODE_MOVE_NODE: - case WorkspaceMode::MODE_SELECTION_RECT: - case WorkspaceMode::MODE_EDIT: { - m_statusBar->SetStatusText(wxT("")); - m_statusBar->SetStatusText(_("MODE: EDIT"), 1); - } break; + case WorkspaceMode::MODE_INSERT: + case WorkspaceMode::MODE_INSERT_TEXT: + case WorkspaceMode::MODE_DRAG_INSERT: + case WorkspaceMode::MODE_DRAG_INSERT_TEXT: { + m_statusBar->SetStatusText(_("MODE: INSERT"), 1); + } break; + + case WorkspaceMode::MODE_MOVE_ELEMENT: + case WorkspaceMode::MODE_MOVE_PICKBOX: + case WorkspaceMode::MODE_MOVE_NODE: + case WorkspaceMode::MODE_SELECTION_RECT: + case WorkspaceMode::MODE_EDIT: { + m_statusBar->SetStatusText(wxT("")); + m_statusBar->SetStatusText(_("MODE: EDIT"), 1); + } break; } m_statusBar->SetStatusText(wxString::Format(_("ZOOM: %d%%"), (int)(m_camera->GetScale() * 100.0)), 2); @@ -877,95 +973,162 @@ void Workspace::UpdateStatusBar() 3); } +void Workspace::UpdateHeatMap() +{ + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + + wxRect2DDouble screenRect(-100, -100, m_width + 200.0, m_height + 200.0); + + // Get new voltage range + std::vector<Bus*> busList; + float minVoltage, maxVoltage; + if (m_hmAutomaticLabel) { + minVoltage = 10.0f; + maxVoltage = 0.0f; + } + else { + minVoltage = m_hmPlane->GetMinLimit(); + maxVoltage = m_hmPlane->GetMaxLimit(); + } + + for (auto* element : m_elementList) { + if (Bus* bus = dynamic_cast<Bus*>(element)) { + if (m_hmAutomaticLabel) { + const float voltage = std::abs(bus->GetElectricalData().voltage); + if (minVoltage > voltage) minVoltage = voltage; + if (maxVoltage < voltage) maxVoltage = voltage; + } + busList.push_back(bus); + } + } + if (m_hmAutomaticLabel) { + m_hmPlane->SetLabelLimits(minVoltage, maxVoltage); + } + + for (Bus* bus : busList) { + const float voltage = std::abs(bus->GetElectricalData().voltage); + float depth = 2.0f * (voltage - (maxVoltage + minVoltage) / 2.0f) / (maxVoltage - minVoltage); + if (depth < -1.0) depth = -1.0; + if (depth > 1.0) depth = 1.0; + + wxRect2DDouble rect = bus->GetRect(); + rect = wxRect2DDouble( + (rect.m_x - 100.0f) * m_camera->GetScale() + m_camera->GetTranslation().m_x * m_camera->GetScale(), + (rect.m_y - 50.0f) * m_camera->GetScale() + m_camera->GetTranslation().m_y * m_camera->GetScale(), + (rect.m_width + 200.0f) * m_camera->GetScale(), + (rect.m_height + 100.0f) * m_camera->GetScale()); + + if (screenRect.Contains(rect)) + m_hmPlane->SetRectSlope(rect, M_PI * static_cast<float>(bus->GetAngle()) / 180.0f, depth); + } + + m_hmPlane->UpdateCoords(); + + int iterations = std::lround(3.3 * std::powf(m_camera->GetScale(), 0.62)); + if (iterations < 1) iterations = 1; + m_hmPlane->SmoothPlane(iterations); + } +} + void Workspace::OnPopupClick(wxCommandEvent& event) { + bool redrawHM = false; + wxMenu* menu = static_cast<wxMenu*>(event.GetEventObject()); Element* element = static_cast<Element*>(menu->GetClientData()); - switch(event.GetId()) { - case ID_EDIT_ELEMENT: { - if(element->ShowForm(this, element)) UpdateTextElements(); - } break; - case ID_LINE_ADD_NODE: { - Line* line = static_cast<Line*>(element); - line->AddNode(m_camera->GetMousePosition()); - Redraw(); - } break; - case ID_LINE_REMOVE_NODE: { - Line* line = static_cast<Line*>(element); - line->RemoveNode(m_camera->GetMousePosition()); - Redraw(); - } break; - case ID_ROTATE_CLOCK: { - element->Rotate(); - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { - Element* iElement = *it; - // Parent's element rotating... - for(int i = 0; i < (int)iElement->GetParentList().size(); i++) { - Element* parent = iElement->GetParentList()[i]; - if(parent == element) { iElement->RotateNode(parent); } - } + switch (event.GetId()) { + case ID_EDIT_ELEMENT: { + if (element->ShowForm(this, element)) UpdateTextElements(); + } break; + case ID_LINE_ADD_NODE: { + Line* line = static_cast<Line*>(element); + line->AddNode(m_camera->GetMousePosition()); + Redraw(); + } break; + case ID_LINE_REMOVE_NODE: { + Line* line = static_cast<Line*>(element); + line->RemoveNode(m_camera->GetMousePosition()); + Redraw(); + } break; + case ID_ROTATE_CLOCK: { + element->Rotate(); + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + Element* iElement = *it; + // Parent's element rotating... + for (int i = 0; i < (int)iElement->GetParentList().size(); i++) { + Element* parent = iElement->GetParentList()[i]; + if (parent == element) { iElement->RotateNode(parent); } } - Redraw(); - } break; - case ID_ROTATE_COUNTERCLOCK: { - element->Rotate(false); - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { - Element* iElement = *it; - // Parent's element rotating... - for(int i = 0; i < (int)iElement->GetParentList().size(); i++) { - Element* parent = iElement->GetParentList()[i]; - if(parent == element) { iElement->RotateNode(parent, false); } - } + } + redrawHM = true; + Redraw(); + } break; + case ID_ROTATE_COUNTERCLOCK: { + element->Rotate(false); + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + Element* iElement = *it; + // Parent's element rotating... + for (int i = 0; i < (int)iElement->GetParentList().size(); i++) { + Element* parent = iElement->GetParentList()[i]; + if (parent == element) { iElement->RotateNode(parent, false); } } - Redraw(); - } break; - case ID_DELETE: { - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { - Element* iElement = *it; - - if(element == iElement) { - // Remove child/parent. - std::vector<Element*> childList = element->GetChildList(); - for(auto itc = childList.begin(), itEnd = childList.end(); itc != itEnd; ++itc) { - Element* child = *itc; - if(child) { - child->RemoveParent(element); - element->RemoveChild(child); - } - } - std::vector<Element*> parentList = element->GetParentList(); - for(auto itp = parentList.begin(), itEnd = parentList.end(); itp != itEnd; ++itp) { - Element* parent = *itp; - if(parent) { parent->RemoveChild(element); } + } + redrawHM = true; + Redraw(); + } break; + case ID_DELETE: { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + Element* iElement = *it; + + if (element == iElement) { + // Remove child/parent. + std::vector<Element*> childList = element->GetChildList(); + for (auto itc = childList.begin(), itEnd = childList.end(); itc != itEnd; ++itc) { + Element* child = *itc; + if (child) { + child->RemoveParent(element); + element->RemoveChild(child); } + } + std::vector<Element*> parentList = element->GetParentList(); + for (auto itp = parentList.begin(), itEnd = parentList.end(); itp != itEnd; ++itp) { + Element* parent = *itp; + if (parent) { parent->RemoveChild(element); } + } - for(auto itt = m_textList.begin(); itt != m_textList.end(); ++itt) { - Text* text = *itt; - if(text->GetElement() == element) { - m_textList.erase(itt--); - if(text) delete text; - } + for (auto itt = m_textList.begin(); itt != m_textList.end(); ++itt) { + Text* text = *itt; + if (text->GetElement() == element) { + m_textList.erase(itt--); + if (text) delete text; } - - m_elementList.erase(it); - if(element) delete element; - menu->SetClientData(nullptr); - break; } + + m_elementList.erase(it); + if (element) delete element; + menu->SetClientData(nullptr); + break; } - } break; + } + } break; + } + if (redrawHM && m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + m_showHMTimer = true; + m_timerHeatMap->Start(); } } void Workspace::RotateSelectedElements(bool clockwise) { - for(auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { + for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) { Element* element = *it; // Parent's element rotating... - for(int i = 0; i < (int)element->GetParentList().size(); i++) { + for (int i = 0; i < (int)element->GetParentList().size(); i++) { Element* parent = element->GetParentList()[i]; - if(parent) { // Check if parent is not null - if(parent->IsSelected()) { + if (parent) { // Check if parent is not null + if (parent->IsSelected()) { element->RotateNode(parent, clockwise); // Update the positions used on motion action, the element will not be necessarily // moved. @@ -973,87 +1136,96 @@ void Workspace::RotateSelectedElements(bool clockwise) } } } - if(element->IsSelected()) { + if (element->IsSelected()) { element->Rotate(clockwise); element->StartMove(m_camera->GetMousePosition()); } } // Rotate text element - for(auto it = m_textList.begin(); it != m_textList.end(); it++) { + for (auto it = m_textList.begin(); it != m_textList.end(); it++) { Text* text = *it; - if(text->IsSelected()) { + if (text->IsSelected()) { text->Rotate(clockwise); text->StartMove(m_camera->GetMousePosition()); } } + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + m_showHMTimer = true; + m_timerHeatMap->Start(); + } Redraw(); } void Workspace::DeleteSelectedElements() { // Don't set the end of the list at the loop's begin. - for(auto it = m_elementList.begin(); it != m_elementList.end();) { + for (auto it = m_elementList.begin(); it != m_elementList.end();) { Element* element = *it; - if(element->IsSelected()) { + if (element->IsSelected()) { // Remove child/parent. std::vector<Element*> childList = element->GetChildList(); - for(auto itc = childList.begin(), itEnd = childList.end(); itc != itEnd; ++itc) { + for (auto itc = childList.begin(), itEnd = childList.end(); itc != itEnd; ++itc) { Element* child = *itc; - if(child) { + if (child) { child->RemoveParent(element); element->RemoveChild(child); } } std::vector<Element*> parentList = element->GetParentList(); - for(auto itp = parentList.begin(), itEnd = parentList.end(); itp != itEnd; ++itp) { + for (auto itp = parentList.begin(), itEnd = parentList.end(); itp != itEnd; ++itp) { Element* parent = *itp; - if(parent) { parent->RemoveChild(element); } + if (parent) { parent->RemoveChild(element); } } - for(auto itt = m_textList.begin(); itt != m_textList.end(); ++itt) { + for (auto itt = m_textList.begin(); itt != m_textList.end(); ++itt) { Text* text = *itt; - if(text->GetElement() == element) { + if (text->GetElement() == element) { m_textList.erase(itt--); - if(text) delete text; + if (text) delete text; } } it = m_elementList.erase(it); - if(element) delete element; + if (element) delete element; } else it++; } - for(auto it = m_textList.begin(); it != m_textList.end(); ++it) { + for (auto it = m_textList.begin(); it != m_textList.end(); ++it) { Text* text = *it; - if(text->IsSelected()) { + if (text->IsSelected()) { m_textList.erase(it--); - if(text) delete text; + if (text) delete text; } } - + if (m_hmPlane && m_showHM) { + m_hmPlane->Clear(); + m_showHMTimer = true; + m_timerHeatMap->Start(); + } Redraw(); } bool Workspace::GetElementsCorners(wxPoint2DDouble& leftUpCorner, - wxPoint2DDouble& rightDownCorner, - std::vector<Element*> elementList) + wxPoint2DDouble& rightDownCorner, + std::vector<Element*> elementList) { - if(elementList.size() == 0) return false; + if (elementList.size() == 0) return false; elementList[0]->CalculateBoundaries(leftUpCorner, rightDownCorner); - for(auto it = elementList.begin() + 1, itEnd = elementList.end(); it != itEnd; it++) { + for (auto it = elementList.begin() + 1, itEnd = elementList.end(); it != itEnd; it++) { Element* element = *it; wxPoint2DDouble leftUp; wxPoint2DDouble rightDown; element->CalculateBoundaries(leftUp, rightDown); - if(leftUp.m_x < leftUpCorner.m_x) leftUpCorner.m_x = leftUp.m_x; - if(leftUp.m_y < leftUpCorner.m_y) leftUpCorner.m_y = leftUp.m_y; - if(rightDown.m_x > rightDownCorner.m_x) rightDownCorner.m_x = rightDown.m_x; - if(rightDown.m_y > rightDownCorner.m_y) rightDownCorner.m_y = rightDown.m_y; + if (leftUp.m_x < leftUpCorner.m_x) leftUpCorner.m_x = leftUp.m_x; + if (leftUp.m_y < leftUpCorner.m_y) leftUpCorner.m_y = leftUp.m_y; + if (rightDown.m_x > rightDownCorner.m_x) rightDownCorner.m_x = rightDown.m_x; + if (rightDown.m_y > rightDownCorner.m_y) rightDownCorner.m_y = rightDown.m_y; } return true; } @@ -1063,9 +1235,9 @@ void Workspace::Fit() wxPoint2DDouble leftUpCorner(0, 0); wxPoint2DDouble rightDownCorner(0, 0); std::vector<Element*> elementList = GetElementList(); - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { elementList.push_back(*it); } + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { elementList.push_back(*it); } - if(!GetElementsCorners(leftUpCorner, rightDownCorner, elementList)) return; + if (!GetElementsCorners(leftUpCorner, rightDownCorner, elementList)) return; wxPoint2DDouble middleCoords = (leftUpCorner + rightDownCorner) / 2.0; int width = 0.0; @@ -1076,13 +1248,18 @@ void Workspace::Fit() double scaleY = double(height) / (rightDownCorner.m_y - leftUpCorner.m_y); double scale = scaleX < scaleY ? scaleX : scaleY; - if(scale > m_camera->GetZoomMax()) scale = m_camera->GetZoomMax(); - if(scale < m_camera->GetZoomMin()) scale = m_camera->GetZoomMin(); + if (scale > m_camera->GetZoomMax()) scale = m_camera->GetZoomMax(); + if (scale < m_camera->GetZoomMin()) scale = m_camera->GetZoomMin(); m_camera->SetScale(scale); m_camera->StartTranslation(middleCoords); m_camera->SetTranslation(wxPoint2DDouble(width / 2, height / 2)); + + if (m_hmPlane && m_showHM) { + UpdateHeatMap(); + } + Redraw(); } @@ -1091,16 +1268,16 @@ void Workspace::ValidateBusesVoltages(Element* initialBus) double nominalVoltage = static_cast<Bus*>(initialBus)->GetElectricalData().nominalVoltage; ElectricalUnit nominalVoltageUnit = static_cast<Bus*>(initialBus)->GetElectricalData().nominalVoltageUnit; - for(auto it = m_elementList.begin(); it != m_elementList.end(); it++) { + for (auto it = m_elementList.begin(); it != m_elementList.end(); it++) { Element* child = *it; - if(typeid(*child) == typeid(Line)) { - if(child->GetParentList()[0] && child->GetParentList()[1]) { + if (typeid(*child) == typeid(Line)) { + if (child->GetParentList()[0] && child->GetParentList()[1]) { BusElectricalData data1 = static_cast<Bus*>(child->GetParentList()[0])->GetElectricalData(); BusElectricalData data2 = static_cast<Bus*>(child->GetParentList()[1])->GetElectricalData(); - if(data1.nominalVoltage != data2.nominalVoltage || - data1.nominalVoltageUnit != data2.nominalVoltageUnit) { + if (data1.nominalVoltage != data2.nominalVoltage || + data1.nominalVoltageUnit != data2.nominalVoltageUnit) { data1.nominalVoltage = nominalVoltage; data2.nominalVoltage = nominalVoltage; data1.nominalVoltageUnit = nominalVoltageUnit; @@ -1120,14 +1297,14 @@ void Workspace::ValidateBusesVoltages(Element* initialBus) void Workspace::ValidateElementsVoltages() { - for(auto it = m_elementList.begin(); it != m_elementList.end(); it++) { + for (auto it = m_elementList.begin(); it != m_elementList.end(); it++) { PowerElement* child = *it; std::vector<double> nominalVoltage; std::vector<ElectricalUnit> nominalVoltageUnit; - for(int i = 0; i < (int)child->GetParentList().size(); i++) { + for (int i = 0; i < (int)child->GetParentList().size(); i++) { Bus* parent = static_cast<Bus*>(child->GetParentList()[i]); - if(parent) { + if (parent) { nominalVoltage.push_back(parent->GetElectricalData().nominalVoltage); nominalVoltageUnit.push_back(parent->GetElectricalData().nominalVoltageUnit); } @@ -1140,38 +1317,40 @@ bool Workspace::RunPowerFlow() { auto simProp = m_properties->GetSimulationPropertiesData(); double basePower = simProp.basePower; - if(simProp.basePowerUnit == ElectricalUnit::UNIT_MVA) + if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA) basePower *= 1e6; - else if(simProp.basePowerUnit == ElectricalUnit::UNIT_kVA) + else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA) basePower *= 1e3; PowerFlow pf(GetElementList()); bool result = false; wxStopWatch sw; - switch(simProp.powerFlowMethod) { - case GAUSS_SEIDEL: { - result = pf.RunGaussSeidel(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance, - simProp.initAngle, simProp.accFator); - } break; - case NEWTON_RAPHSON: { - result = pf.RunNewtonRaphson(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance, - simProp.initAngle, simProp.newtonInertia); - } break; - case GAUSS_NEWTON: { - result = - pf.RunGaussNewton(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance, - simProp.initAngle, simProp.accFator, simProp.gaussTolerance, simProp.newtonInertia); - } break; + switch (simProp.powerFlowMethod) { + case GAUSS_SEIDEL: { + result = pf.RunGaussSeidel(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance, + simProp.initAngle, simProp.accFator); + } break; + case NEWTON_RAPHSON: { + result = pf.RunNewtonRaphson(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance, + simProp.initAngle, simProp.newtonInertia); + } break; + case GAUSS_NEWTON: { + result = + pf.RunGaussNewton(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance, + simProp.initAngle, simProp.accFator, simProp.gaussTolerance, simProp.newtonInertia); + } break; } sw.Pause(); - if(!result) { + if (!result) { wxMessageDialog msgDialog(this, pf.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR); msgDialog.ShowModal(); - } else { + } + else { m_statusBar->SetStatusText( wxString::Format(_("Power flow converge with %d iterations (%ld ms)"), pf.GetIterations(), sw.Time())); } UpdateTextElements(); + UpdateHeatMap(); Redraw(); return result; @@ -1181,14 +1360,14 @@ bool Workspace::UpdateTextElements() { bool isTexturesOK = true; double basePower = m_properties->GetSimulationPropertiesData().basePower; - if(m_properties->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_kVA) + if (m_properties->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_kVA) basePower *= 1e3; - else if(m_properties->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_MVA) + else if (m_properties->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_MVA) basePower *= 1e6; - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { Text* text = *it; text->UpdateText(basePower); - if(!text->IsGLTextOK()) isTexturesOK = false; + if (!text->IsGLTextOK()) isTexturesOK = false; } return isTexturesOK; } @@ -1199,23 +1378,23 @@ void Workspace::CopySelection() std::vector<Element*> selectedElements; // The buses need to be numerated to associate the child's parents to the copies. int busNumber = 0; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { Element* element = *it; - if(typeid(*element) == typeid(Bus)) { + if (typeid(*element) == typeid(Bus)) { Bus* bus = static_cast<Bus*>(element); auto data = bus->GetElectricalData(); data.number = busNumber; bus->SetElectricalData(data); busNumber++; } - if(element->IsSelected()) { selectedElements.push_back(element); } + if (element->IsSelected()) { selectedElements.push_back(element); } } - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { Text* text = *it; - if(text->IsSelected()) { selectedElements.push_back(text); } + if (text->IsSelected()) { selectedElements.push_back(text); } } ElementDataObject* dataObject = new ElementDataObject(selectedElements); - if(wxTheClipboard->Open()) { + if (wxTheClipboard->Open()) { wxTheClipboard->SetData(dataObject); wxTheClipboard->Close(); } @@ -1223,18 +1402,19 @@ void Workspace::CopySelection() bool Workspace::Paste() { - if(wxTheClipboard->Open()) { + if (wxTheClipboard->Open()) { ElementDataObject dataObject; - if(wxTheClipboard->IsSupported(dataObject.GetFormat())) { - if(!wxTheClipboard->GetData(dataObject)) { + if (wxTheClipboard->IsSupported(dataObject.GetFormat())) { + if (!wxTheClipboard->GetData(dataObject)) { wxMessageDialog dialog(this, _("It was not possible to paste from clipboard."), _("Error"), - wxOK | wxCENTER | wxICON_ERROR, wxDefaultPosition); + wxOK | wxCENTER | wxICON_ERROR, wxDefaultPosition); dialog.ShowModal(); wxTheClipboard->Close(); return false; } - } else { + } + else { wxTheClipboard->Close(); return false; } @@ -1248,9 +1428,9 @@ bool Workspace::Paste() // Paste buses (parents). auto parentList = elementsLists->parentList; std::vector<Bus*> pastedBusList; // To set new parents; - for(auto it = parentList.begin(), itEnd = parentList.end(); it != itEnd; ++it) { + for (auto it = parentList.begin(), itEnd = parentList.end(); it != itEnd; ++it) { Element* copy = (*it)->GetCopy(); - if(copy) { + if (copy) { pastedElements.push_back(copy); pastedBusList.push_back(static_cast<Bus*>(copy)); m_elementList.push_back(static_cast<PowerElement*>(copy)); @@ -1259,39 +1439,40 @@ bool Workspace::Paste() // Paste other elements. auto elementLists = elementsLists->elementList; - for(auto it = elementLists.begin(), itEnd = elementLists.end(); it != itEnd; ++it) { + for (auto it = elementLists.begin(), itEnd = elementLists.end(); it != itEnd; ++it) { Element* copy = (*it)->GetCopy(); - if(copy) { + if (copy) { // Check if is text element - if(Text* text = dynamic_cast<Text*>(copy)) { + if (Text* text = dynamic_cast<Text*>(copy)) { // Check if element associated with the text exists. bool elementExist = false; - for(int i = 0; i < (int)m_elementList.size(); i++) { - if(text->GetElement() == m_elementList[i]) { + for (int i = 0; i < (int)m_elementList.size(); i++) { + if (text->GetElement() == m_elementList[i]) { elementExist = true; break; } } - if(elementExist) { + if (elementExist) { pastedElements.push_back(copy); m_textList.push_back(text); } - } else { + } + else { // Change the parent if copied, otherwise remove it. - for(unsigned int j = 0; j < copy->GetParentList().size(); j++) { + for (unsigned int j = 0; j < copy->GetParentList().size(); j++) { Bus* currentParent = static_cast<Bus*>(copy->GetParentList()[j]); - if(currentParent) { + if (currentParent) { int parentID = currentParent->GetID(); bool parentCopied = false; - for(int k = 0; k < (int)pastedBusList.size(); k++) { + for (int k = 0; k < (int)pastedBusList.size(); k++) { Bus* newParent = pastedBusList[k]; - if(parentID == newParent->GetID()) { + if (parentID == newParent->GetID()) { parentCopied = true; copy->ReplaceParent(currentParent, newParent); break; } } - if(!parentCopied) copy->RemoveParent(currentParent); + if (!parentCopied) copy->RemoveParent(currentParent); } } @@ -1302,22 +1483,22 @@ bool Workspace::Paste() } // Update buses childs - for(auto it = pastedBusList.begin(), itEnd = pastedBusList.end(); it != itEnd; ++it) { + for (auto it = pastedBusList.begin(), itEnd = pastedBusList.end(); it != itEnd; ++it) { Bus* bus = *it; std::vector<Element*> childList = bus->GetChildList(); - for(auto it = childList.begin(), itEnd = childList.end(); it != itEnd; ++it) { + for (auto it = childList.begin(), itEnd = childList.end(); it != itEnd; ++it) { Element* currentChild = *it; int childID = currentChild->GetID(); bool childCopied = false; - for(int i = 0; i < (int)pastedElements.size(); i++) { + for (int i = 0; i < (int)pastedElements.size(); i++) { Element* newChild = pastedElements[i]; - if(childID == newChild->GetID()) { + if (childID == newChild->GetID()) { childCopied = true; bus->ReplaceChild(currentChild, newChild); break; } } - if(!childCopied) bus->RemoveChild(currentChild); + if (!childCopied) bus->RemoveChild(currentChild); } } @@ -1326,18 +1507,19 @@ bool Workspace::Paste() wxPoint2DDouble leftUpCorner, rightDownCorner; GetElementsCorners(leftUpCorner, rightDownCorner, pastedElements); wxPoint2DDouble startPosition = (leftUpCorner + rightDownCorner) / 2.0; - for(auto it = pastedElements.begin(), itEnd = pastedElements.end(); it != itEnd; ++it) { + for (auto it = pastedElements.begin(), itEnd = pastedElements.end(); it != itEnd; ++it) { Element* element = *it; element->StartMove(startPosition); element->Move(m_camera->GetMousePosition()); - for(int i = 0; i < (int)element->GetParentList().size(); i++) { + for (int i = 0; i < (int)element->GetParentList().size(); i++) { Element* parent = element->GetParentList()[i]; element->MoveNode(parent, m_camera->GetMousePosition()); } } - } else { + } + else { wxMessageDialog dialog(this, _("It was not possible to paste from clipboard."), _("Error"), - wxOK | wxCENTER | wxICON_ERROR, wxDefaultPosition); + wxOK | wxCENTER | wxICON_ERROR, wxDefaultPosition); dialog.ShowModal(); return false; } @@ -1352,25 +1534,34 @@ bool Workspace::Paste() void Workspace::UnselectAll() { - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; it++) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; it++) { Element* element = *it; element->SetSelected(false); } - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; it++) { + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; it++) { Text* text = *it; text->SetSelected(false); } } +void Workspace::EnableHeatMap(const bool& enable) +{ + m_showHM = enable; + if (m_showHM) { + UpdateHeatMap(); + } + Redraw(); +} + void Workspace::UpdateElementsID() { int id = 0; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { Element* element = *it; element->SetID(id); id++; } - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) { Text* text = *it; text->SetID(id); id++; @@ -1378,16 +1569,16 @@ void Workspace::UpdateElementsID() } void Workspace::OnTimer(wxTimerEvent& event) { - if(m_tipWindow) { + if (m_tipWindow) { m_tipWindow->Close(); m_tipWindow = nullptr; } - if(m_mode == WorkspaceMode::MODE_EDIT) { - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + if (m_mode == WorkspaceMode::MODE_EDIT) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { Element* element = *it; - if(element->Contains(m_camera->GetMousePosition())) { + if (element->Contains(m_camera->GetMousePosition())) { wxString tipText = element->GetTipText(); - if(!tipText.IsEmpty()) { + if (!tipText.IsEmpty()) { m_tipWindow = new wxTipWindow(this, tipText, 10000, &m_tipWindow); // Creates a very tiny bounding rect to remove the tip on any mouse movement. m_tipWindow->SetBoundingRect(wxRect(wxGetMousePosition(), wxSize(1, 1))); @@ -1403,7 +1594,7 @@ void Workspace::OnTimer(wxTimerEvent& event) void Workspace::SetTextList(std::vector<Text*> textList) { m_textList.clear(); - for(auto it = textList.begin(), itEnd = textList.end(); it != itEnd; ++it) m_textList.push_back(*it); + for (auto it = textList.begin(), itEnd = textList.end(); it != itEnd; ++it) m_textList.push_back(*it); UpdateTextElements(); } @@ -1411,16 +1602,27 @@ void Workspace::SetTextList(std::vector<Text*> textList) void Workspace::SetElementList(std::vector<Element*> elementList) { m_elementList.clear(); - for(auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) + for (auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) m_elementList.push_back(static_cast<PowerElement*>(*it)); } void Workspace::OnIdle(wxIdleEvent& event) { - // The OpenGL element (m_glCanvas) must be completely initialized (showed) to draw properly the textures. + // The OpenGL element (m_glCanvas) must be completely initialized (showed) to draw properly the textures and init glew. // TODO(?): Find other solution to text displayed wrong on opened file. - if(m_justOpened) { - if(UpdateTextElements()) m_justOpened = false; + if (m_justOpened) { + if (UpdateTextElements()) m_justOpened = false; + if (glewInit() != GLEW_OK) + wxMessageBox("Erro ao iniciar glew ='("); + else + { + // Load and create shader + m_basicShader = new Shader("..//data//shaders//Basic.shader"); + m_hmLabelShader = new Shader("..//data//shaders//HMLabel.shader"); + float limits[2] = { 1.05, 0.95 }; + m_hmPlane = new HMPlane(m_basicShader, m_hmLabelShader, m_width, m_height, limits); + } + Redraw(); } } @@ -1429,8 +1631,8 @@ std::vector<Element*> Workspace::GetAllElements() const { std::vector<Element*> allElements; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) allElements.push_back(*it); - for(auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) allElements.push_back(*it); + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) allElements.push_back(*it); + for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) allElements.push_back(*it); return allElements; } @@ -1439,7 +1641,7 @@ bool Workspace::RunFault() { Fault fault(GetElementList()); bool result = fault.RunFaultCalculation(100e6); - if(!result) { + if (!result) { wxMessageDialog msgDialog(this, fault.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR); msgDialog.ShowModal(); } @@ -1453,7 +1655,7 @@ bool Workspace::RunFault() std::vector<Element*> Workspace::GetElementList() const { std::vector<Element*> elementList; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) elementList.push_back(*it); + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) elementList.push_back(*it); return elementList; } @@ -1461,7 +1663,7 @@ bool Workspace::RunSCPower() { Fault fault(GetElementList()); bool result = fault.RunSCPowerCalcutation(100e6); - if(!result) { + if (!result) { wxMessageDialog msgDialog(this, fault.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR); msgDialog.ShowModal(); } @@ -1481,7 +1683,7 @@ bool Workspace::RunStability() wxStopWatch sw; bool result = stability.RunStabilityCalculation(); sw.Pause(); - if(!result) { + if (!result) { wxMessageDialog msgDialog(this, stability.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR); msgDialog.ShowModal(); } @@ -1494,14 +1696,14 @@ bool Workspace::RunStability() wxMessageDialog msgDialog( this, wxString::Format(_("The program took %ld ms to run this system.\nDo you wish to open the stability graphics?"), - sw.Time()), + sw.Time()), _("Question"), wxYES_NO | wxCENTRE | wxICON_QUESTION); - if(msgDialog.ShowModal() == wxID_YES) { + if (msgDialog.ShowModal() == wxID_YES) { std::vector<ElementPlotData> plotDataList; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { PowerElement* element = *it; ElementPlotData plotData; - if(element->GetPlotData(plotData)) plotDataList.push_back(plotData); + if (element->GetPlotData(plotData)) plotDataList.push_back(plotData); } ElementPlotData plotData; @@ -1529,25 +1731,28 @@ bool Workspace::RunStaticStudies() pfStatus = RunPowerFlow(); - if(m_properties->GetSimulationPropertiesData().faultAfterPowerFlow) { - if(pfStatus) faultStatus = RunFault(); - } else { + if (m_properties->GetSimulationPropertiesData().faultAfterPowerFlow) { + if (pfStatus) faultStatus = RunFault(); + } + else { faultStatus = true; } - if(m_properties->GetSimulationPropertiesData().scPowerAfterPowerFlow) { - if(pfStatus) scStatus = RunSCPower(); - } else { + if (m_properties->GetSimulationPropertiesData().scPowerAfterPowerFlow) { + if (pfStatus) scStatus = RunSCPower(); + } + else { scStatus = true; } - if(m_properties->GetSimulationPropertiesData().harmDistortionAfterPowerFlow) { - if(pfStatus) harmStatus = RunHarmonicDistortion(); - } else { + if (m_properties->GetSimulationPropertiesData().harmDistortionAfterPowerFlow) { + if (pfStatus) harmStatus = RunHarmonicDistortion(); + } + else { harmStatus = true; } - if(pfStatus && faultStatus && scStatus && harmStatus) return true; + if (pfStatus && faultStatus && scStatus && harmStatus) return true; return false; } @@ -1556,11 +1761,11 @@ bool Workspace::RunHarmonicDistortion() { auto simProp = m_properties->GetSimulationPropertiesData(); double basePower = simProp.basePower; - if(simProp.basePowerUnit == ElectricalUnit::UNIT_MVA) + if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA) basePower *= 1e6; - else if(simProp.basePowerUnit == ElectricalUnit::UNIT_kVA) + else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA) basePower *= 1e3; - if(!RunPowerFlow()) return false; + if (!RunPowerFlow()) return false; PowerQuality pq(GetElementList()); bool result = pq.CalculateDistortions(basePower); @@ -1574,42 +1779,43 @@ bool Workspace::RunFrequencyResponse() { // Get bus list std::vector<Bus*> busList; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { - if(Bus* bus = dynamic_cast<Bus*>(*it)) { busList.push_back(bus); } + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + if (Bus* bus = dynamic_cast<Bus*>(*it)) { busList.push_back(bus); } } auto data = m_properties->GetFreqRespData(); FrequencyResponseForm frForm(this, busList, data.injBusNumber, data.initFreq, data.finalFreq, data.stepFreq); - if(frForm.ShowModal() == wxID_OK) { + if (frForm.ShowModal() == wxID_OK) { data.initFreq = frForm.GetInitFreq(); data.finalFreq = frForm.GetEndFreq(); data.stepFreq = frForm.GetStepFreq(); data.injBusNumber = frForm.GetInjBusNumber(); m_properties->SetFreqRespData(data); - } else + } + else return false; auto simProp = m_properties->GetSimulationPropertiesData(); double basePower = simProp.basePower; - if(simProp.basePowerUnit == ElectricalUnit::UNIT_MVA) + if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA) basePower *= 1e6; - else if(simProp.basePowerUnit == ElectricalUnit::UNIT_kVA) + else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA) basePower *= 1e3; PowerQuality pq(GetElementList()); bool result = pq.CalculateFrequencyResponse(simProp.stabilityFrequency, data.initFreq, data.finalFreq, - data.stepFreq, data.injBusNumber, basePower); + data.stepFreq, data.injBusNumber, basePower); wxMessageDialog msgDialog( this, wxString::Format(_("Calculations done.\nDo you wish to open the frequency response graphics?")), _("Question"), wxYES_NO | wxCENTRE | wxICON_QUESTION); - if(msgDialog.ShowModal() == wxID_YES) { + if (msgDialog.ShowModal() == wxID_YES) { std::vector<ElementPlotData> plotDataList; - for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { + for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) { PowerElement* element = *it; ElementPlotData plotData; - if(element->GetPlotData(plotData, PlotStudy::FREQRESPONSE)) plotDataList.push_back(plotData); + if (element->GetPlotData(plotData, PlotStudy::FREQRESPONSE)) plotDataList.push_back(plotData); } ChartView* cView = new ChartView(this, plotDataList, pq.GetFrequencies()); @@ -1621,3 +1827,24 @@ bool Workspace::RunFrequencyResponse() return result; } +void Workspace::OnResize(wxSizeEvent& event) +{ + m_width = static_cast<float>(m_glCanvas->GetSize().x) - 1.0f; + m_height = static_cast<float>(m_glCanvas->GetSize().y) - 1.0f; + + if (m_hmPlane && m_showHM) { + m_hmPlane->Resize(m_width, m_height); + m_showHMTimer = true; + m_timerHeatMap->Start(); + } + + event.Skip(); +} +void Workspace::OnHeatMapTime(wxTimerEvent& event) +{ + if (m_showHMTimer) { + UpdateHeatMap(); + Redraw(); + m_showHMTimer = false; + } +} |