Power System Platform  2026w11a-beta
Loading...
Searching...
No Matches
Workspace Class Reference

This class manages the graphical and power elements. It is responsible for handling the user's interaction with the elements. More...

#include <Workspace.h>

Inheritance diagram for Workspace:
Collaboration diagram for Workspace:

Public Types

enum class  WorkspaceMode : int {
  MODE_EDIT = 0 , MODE_MOVE_ELEMENT , MODE_MOVE_PICKBOX , MODE_MOVE_NODE ,
  MODE_DRAG , MODE_DRAG_INSERT , MODE_DRAG_INSERT_TEXT , MODE_INSERT ,
  MODE_INSERT_TEXT , MODE_SELECTION_RECT , MODE_PASTE , MODE_DRAG_PASTE
}
 

Public Member Functions

 Workspace (wxWindow *parent, wxString name=wxEmptyString, wxStatusBar *statusBar=nullptr, wxAuiNotebook *auiNotebook=nullptr)
 
wxString GetName () const
 
std::vector< Element * > GetElementList () const
 
std::vector< std::shared_ptr< PowerElement > > GetElementSharedList () const
 
std::vector< std::shared_ptr< Text > > GetTextList () const
 
std::vector< Element * > GetAllElements () const
 
WorkspaceMode GetWorkspaceMode () const
 
CameraGetCamera () const
 
void CopySelection ()
 
bool Paste ()
 
void SaveCurrentState ()
 
void SetNextState ()
 
void SetPreviousState ()
 
void CopyToClipboard ()
 
void ExportAsSVG (wxString path)
 
wxFileName GetSavedPath () const
 
void SetName (wxString name)
 
void SetElementList (std::vector< std::shared_ptr< PowerElement > > elementList)
 
void SetElementList (std::vector< Element * > elementList)
 
void SetTextList (const std::vector< std::shared_ptr< Text > > &textList)
 
void SetStatusBarText (wxString text)
 
void SetWorkspaceMode (WorkspaceMode mode)
 
void SetSavedPath (wxFileName savedPath)
 
void SetJustOpened (bool justOpened)
 
virtual void Redraw ()
 
void RotateSelectedElements (bool clockwise=true)
 
void DeleteSelectedElements ()
 
bool GetElementsCorners (wxPoint2DDouble &leftUpCorner, wxPoint2DDouble &rightDownCorner, std::vector< Element * > elementList)
 
void Fit ()
 
void UnselectAll ()
 
void EnableHeatMap (const bool &enable=true)
 
bool IsHeatMapEnable () const
 
HMPlaneGetHeatMap () const
 
void EnableAutoHeatMapLabel (const bool &enable=true)
 
bool IsHeatMapAutoLabelEnable () const
 
bool InsertTextElement (int textID, Element *parentElement, ElectricalUnit unit=ElectricalUnit::UNIT_NONE, int precision=2)
 
ElementFindTextElement (Element *parentElement, int dataType)
 
void RemoveAllTextElements ()
 
void CheckSlackBusDuplication (Element *newSlackBus)
 
void ValidateBusesVoltages (Element *initialBus)
 
void ValidateElementsVoltages ()
 
void UpdateElementsID ()
 
bool UpdateTextElements ()
 
void UpdateHeatMap ()
 
int GetElementNumber (ElementID elementID)
 
void IncrementElementNumber (ElementID elementID)
 
PropertiesDataGetProperties () const
 
std::vector< double > GetStabilityTimeVector () const
 
bool IsContinuousCalculationActive () const
 
void SetContinuousCalculationActive (bool value=true)
 
void ResetAllVoltages ()
 
bool RunPowerFlow (bool resetVoltages=false, bool showBusyInfo=true)
 
bool RunFault ()
 
bool RunSCPower ()
 
bool RunStaticStudies ()
 
bool RunStability ()
 
bool RunHarmonicDistortion (bool runPowerFlowBefore=true)
 
bool RunFrequencyResponse ()
 
virtual void OnMiddleDoubleClick (wxMouseEvent &event)
 
virtual void OnIdle (wxIdleEvent &event)
 
virtual void OnTimer (wxTimerEvent &event)
 
virtual void OnLeftDoubleClick (wxMouseEvent &event)
 
virtual void OnRightClickDown (wxMouseEvent &event)
 
virtual void OnLeftClickUp (wxMouseEvent &event)
 
virtual void OnScroll (wxMouseEvent &event)
 
virtual void OnMiddleDown (wxMouseEvent &event)
 
virtual void OnMiddleUp (wxMouseEvent &event)
 
virtual void OnMouseMotion (wxMouseEvent &event)
 
virtual void OnKeyDown (wxKeyEvent &event)
 
virtual void OnLeftClickDown (wxMouseEvent &event)
 
virtual void OnPaint (wxPaintEvent &event)
 
virtual void OnPopupClick (wxCommandEvent &event)
 
virtual void OnResize (wxSizeEvent &event)
 

Protected Member Functions

virtual void OnHeatMapTime (wxTimerEvent &event)
 
void UpdateStatusBar ()
 
int GetElementNumberFromList (Element *element)
 
void GetStateListsCopy (const std::vector< std::shared_ptr< PowerElement > > &elementsList, const std::vector< std::shared_ptr< Text > > &textList, std::vector< std::shared_ptr< PowerElement > > &elementsListCopy, std::vector< std::shared_ptr< Text > > &textListCopy)
 
void DrawScene (wxGraphicsContext *gc)
 
void DrawScene (wxDC &dc)
 

Protected Attributes

wxStatusBar * m_statusBar = nullptr
 
wxAuiNotebook * m_auiNotebook = nullptr
 
Cameram_camera = nullptr
 
wxTipWindow * m_tipWindow = nullptr
 
wxString m_name
 
WorkspaceMode m_mode = WorkspaceMode::MODE_EDIT
 
WorkspaceMode m_oldStatusMode = WorkspaceMode::MODE_EDIT
 
std::vector< std::shared_ptr< PowerElement > > m_elementList
 
int m_elementNumber [NUM_ELEMENTS]
 
std::vector< std::shared_ptr< Text > > m_textList
 
std::vector< std::vector< std::shared_ptr< PowerElement > > > m_elementListState
 
std::vector< std::vector< std::shared_ptr< Text > > > m_textListState
 
int m_currenteState = -1
 
int m_maxStates = 100
 
wxFileName m_savedPath
 
wxRect2DDouble m_selectionRect
 
wxPoint2DDouble m_startSelRect
 
PropertiesDatam_properties = nullptr
 
std::vector< double > m_stabilityTimeVector
 
bool m_continuousCalc = false
 
bool m_disconnectedElement = false
 
bool m_justOpened = false
 
float m_width = 0.0
 
float m_height = 0.0
 
HMPlanem_hmPlane = nullptr
 
bool m_showHM = false
 
bool m_showHMTimer = false
 
bool m_hmAutomaticLabel = false
 

Detailed Description

This class manages the graphical and power elements. It is responsible for handling the user's interaction with the elements.

Author
Thales Lima Oliveira thale.nosp@m.s@uf.nosp@m.u.br
Date
19/09/2017

Definition at line 102 of file Workspace.h.

Member Enumeration Documentation

◆ WorkspaceMode

enum class Workspace::WorkspaceMode : int
strong

Definition at line 105 of file Workspace.h.

105 : int {
106 MODE_EDIT = 0,
107 MODE_MOVE_ELEMENT,
108 MODE_MOVE_PICKBOX,
109 MODE_MOVE_NODE,
110 MODE_DRAG,
111 MODE_DRAG_INSERT,
112 MODE_DRAG_INSERT_TEXT,
113 MODE_INSERT,
114 MODE_INSERT_TEXT,
115 MODE_SELECTION_RECT,
116 MODE_PASTE,
117 MODE_DRAG_PASTE
118 };

Constructor & Destructor Documentation

◆ Workspace() [1/2]

Workspace::Workspace ( )

Definition at line 82 of file Workspace.cpp.

82 : WorkspaceBase(nullptr)
83{
84#ifdef _DEBUG
85#ifdef SHOW_DEBUG_PANEL
86 m_debugFrame = new DebugMainFrame(this);
87 m_debugFrame->SetTitle(_("Debug window: ") + m_name);
88 m_debugFrame->Show();
89 //m_debugFrame->SetSize(m_debugFrame->GetBestVirtualSize());
90#endif
91#endif
92 SetBackgroundColour(wxColour(255, 255, 255));
93 SetBackgroundStyle(wxBG_STYLE_PAINT); // To allow wxBufferedPaintDC works properly.
94}

◆ Workspace() [2/2]

Workspace::Workspace ( wxWindow *  parent,
wxString  name = wxEmptyString,
wxStatusBar *  statusBar = nullptr,
wxAuiNotebook *  auiNotebook = nullptr 
)

Definition at line 96 of file Workspace.cpp.

97 : WorkspaceBase(parent)
98{
99#ifdef _DEBUG
100#ifdef SHOW_DEBUG_PANEL
101 m_debugFrame = new DebugMainFrame(this);
102 m_debugFrame->SetTitle(_("Debug window: ") + m_name);
103 m_debugFrame->Show();
104 //m_debugFrame->SetSize(m_debugFrame->GetBestVirtualSize());
105#endif
106#endif
107
108 m_timer->Start();
109 m_name = name;
110 m_statusBar = statusBar;
111 m_auiNotebook = auiNotebook;
112 //m_glContext = new wxGLContext(m_glCanvas, sharedGLContext);
113 m_camera = new Camera();
114 m_selectionRect = wxRect2DDouble(0, 0, 0, 0);
115
116 for (int i = 0; i < NUM_ELEMENTS; ++i) { m_elementNumber[i] = 1; }
117
118 const int widths[4] = { -3, -1, 100, 100 };
119 m_statusBar->SetStatusWidths(4, widths);
120
121 m_properties = new PropertiesData();
122
123 //m_glCanvas->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
124 m_workspacePanel->SetBackgroundColour(wxColour(255, 255, 255));
125 m_workspacePanel->SetBackgroundStyle(wxBG_STYLE_PAINT); // To allow wxBufferedPaintDC works properly.
126
127 //m_width = static_cast<float>(m_glCanvas->GetSize().x) - 1.0;
128 //m_height = static_cast<float>(m_glCanvas->GetSize().y) - 1.0;
129 m_width = static_cast<float>(m_workspacePanel->GetSize().x) - 1.0;
130 m_height = static_cast<float>(m_workspacePanel->GetSize().y) - 1.0;
131 //m_renderer = new Renderer();
132
133 SaveCurrentState();
134}
Class responsible for the correct visualization of the elements on screen.
Definition Camera.h:31
General and simulation data manager.

◆ ~Workspace()

Workspace::~Workspace ( )
virtual

Definition at line 136 of file Workspace.cpp.

137{
138 //for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) {
139 // if (*it) delete* it;
140 //}
141 //for (auto it = m_textList.begin(), itEnd = m_textList.end(); it != itEnd; ++it) {
142 // if (*it) delete* it;
143 //}
144
145 if (m_hmPlane) delete m_hmPlane;
146
147 if (m_camera) delete m_camera;
148 //if (m_isThisContextShared) {
149 //delete m_glContext;
150 //m_glContext = nullptr;
151 //}
152 if (m_tipWindow) delete m_tipWindow;
153 if (m_properties) delete m_properties;
154}

Member Function Documentation

◆ CheckSlackBusDuplication()

void Workspace::CheckSlackBusDuplication ( Element newSlackBus)

Definition at line 2021 of file Workspace.cpp.

2022{
2023 Bus* newBus = dynamic_cast<Bus*>(newSlackBus);
2024 if (newBus) {
2025 if (!newBus->GetElectricalData().slackBus) return; // If the new bus is not set as slack bus, no need to check for duplication.
2026
2027 for (auto& element : m_elementList) {
2028 Bus* bus = dynamic_cast<Bus*>(element.get());
2029 if (!bus) continue;
2030 if (bus->GetElectricalData().slackBus && bus != newSlackBus) {
2031 wxMessageDialog msgDialog(this,
2032 wxString::Format(_("The system already has %s as the slack bus.\nDo you want to set %s as the new slack bus?"), bus->GetElectricalData().name, newBus->GetElectricalData().name),
2033 _("Warning"), wxYES_NO | wxCENTRE | wxICON_WARNING);
2034 if (msgDialog.ShowModal() == wxID_YES) {
2035 auto data = bus->GetElectricalData();
2036 data.slackBus = false;
2037 bus->SetElectricalData(data);
2038 return;
2039 }
2040 else {
2041 auto data = newBus->GetElectricalData();
2042 data.slackBus = false;
2043 newBus->SetElectricalData(data);
2044 return;
2045 }
2046 }
2047 }
2048 }
2049}
Node for power elements. All others power elements are connected through this.
Definition Bus.h:86

◆ CopySelection()

void Workspace::CopySelection ( )

Definition at line 2213 of file Workspace.cpp.

2214{
2215 UpdateElementsID();
2216 std::vector<Element*> selectedElements;
2217 // The buses need to be numerated to associate the child's parents to the copies.
2218 int busNumber = 0;
2219 for (auto& element : m_elementList) {
2220 if (auto bus = dynamic_cast<Bus*>(element.get())) {
2221 auto data = bus->GetElectricalData();
2222 data.number = busNumber;
2223 bus->SetElectricalData(data);
2224 busNumber++;
2225 }
2226 if (element->IsSelected()) { selectedElements.push_back(element.get()); }
2227 }
2228 for (auto& text : m_textList) {
2229 if (text->IsSelected()) { selectedElements.push_back(text.get()); }
2230 }
2231 ElementDataObject* dataObject = new ElementDataObject(selectedElements);
2232 if (wxTheClipboard->Open()) {
2233 wxTheClipboard->SetData(dataObject);
2234 wxTheClipboard->Close();
2235 }
2236}
Class to store the elements in the clipboard.

◆ CopyToClipboard()

void Workspace::CopyToClipboard ( )

Definition at line 287 of file Workspace.cpp.

288{
289 wxSize size = GetClientSize();
290
291 int scale = 2;
292
293 wxBitmap bitmap(size.x * scale, size.y * scale);
294 wxMemoryDC memDC(bitmap);
295
296 memDC.SetBackground(*wxWHITE_BRUSH);
297 memDC.Clear();
298
299 wxGraphicsContext* gc = wxGraphicsContext::Create(memDC);
300 if (!gc) return;
301 gc->Scale(scale, scale); // Increase the scale to improve the quality of the copied image.
302
303 DrawScene(gc);
304 delete gc;
305
306 memDC.SelectObject(wxNullBitmap);
307
308 if (wxTheClipboard->Open())
309 {
310 wxTheClipboard->SetData(new wxBitmapDataObject(bitmap));
311 wxTheClipboard->Close();
312 }
313}

◆ DeleteSelectedElements()

void Workspace::DeleteSelectedElements ( )

Definition at line 1629 of file Workspace.cpp.

1630{
1631 // Don't set the end of the list at the loop's begin.
1632 for (auto it = m_elementList.begin(); it != m_elementList.end();) {
1633 Element* element = it->get();
1634
1635 if (element->IsSelected()) {
1636 // Remove child/parent.
1637 std::vector<Element*> childList = element->GetChildList();
1638 for (auto itc = childList.begin(), itEnd = childList.end(); itc != itEnd; ++itc) {
1639 Element* child = *itc;
1640 if (child) {
1641 child->RemoveParent(element);
1642 element->RemoveChild(child);
1643 }
1644 }
1645 std::vector<Element*> parentList = element->GetParentList();
1646 for (auto itp = parentList.begin(), itEnd = parentList.end(); itp != itEnd; ++itp) {
1647 Element* parent = *itp;
1648 if (parent) { parent->RemoveChild(element); }
1649 }
1650
1651 //for (auto& text : m_textList) {
1652 // if (text->GetElement() == element) {
1653 // if (m_textList.size() == 1) {
1654 // m_textList.erase(itt);
1655 // break;
1656 // }
1657 // else m_textList.erase(itt--);
1658 // if (text) delete text;
1659 // }
1660 //}
1661 std::erase_if(m_textList, [&](const auto& text) {
1662 return text->GetElement() == element;
1663 });
1664
1665 it = m_elementList.erase(it);
1666 //if (element) delete element;
1667 }
1668 else it++;
1669 }
1670
1671 //for (auto it = m_textList.begin(); it != m_textList.end(); ++it) {
1672 // Text* text = *it;
1673 // if (text->IsSelected()) {
1674 // if (m_textList.size() == 1) {
1675 // m_textList.erase(it);
1676 // break;
1677 // }
1678 // else m_textList.erase(it--);
1679 // if (text) delete text;
1680 // }
1681 //}
1682 std::erase_if(m_textList, [](const auto& text) {
1683 return text->IsSelected();
1684 });
1685
1686 if (m_hmPlane && m_showHM) {
1687 m_hmPlane->Clear();
1688 m_showHMTimer = true;
1689 m_timerHeatMap->Start();
1690 }
1691 SaveCurrentState();
1692 Redraw();
1693}
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
virtual std::vector< Element * > GetParentList() const
Get the parent list.
Definition Element.h:559
virtual std::vector< Element * > GetChildList() const
Get the Child list.
Definition Element.h:564
virtual void RemoveChild(Element *child)
Remove a child from the list.
Definition Element.cpp:495
virtual void RemoveParent(Element *parent)
Remove a parent.
Definition Element.h:371
bool IsSelected() const
Checks if the element is selected.
Definition Element.h:201

◆ DrawScene() [1/2]

void Workspace::DrawScene ( wxDC &  dc)
protected

Definition at line 254 of file Workspace.cpp.

255{
256 // HMPlane
257 if (m_hmPlane && m_showHM) {
258 m_hmPlane->DrawDC(dc);
259 }
260
261 dc.SetUserScale(m_camera->GetScale(), m_camera->GetScale());
262 dc.SetDeviceOrigin(m_camera->GetTranslation().m_x * m_camera->GetScale(), m_camera->GetTranslation().m_y * m_camera->GetScale());
263 //dc.SetLogicalOrigin(-m_camera->GetTranslation().m_x, -m_camera->GetTranslation().m_y);
264
265 // Elements
266 for (auto& element : m_elementList) {
267 element->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), dc);
268 }
269
270 // Dummy Text to set correct context
271 // TODO: Find a better way to do this.
272 Text* text = new Text(wxPoint2DDouble(0.0, 0.0), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
273 text->SetText("");
274 text->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), dc);
275 delete text;
276
277 // Texts
278 for (auto& text : m_textList) {
279 text->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), dc);
280 }
281
282 if (m_hmPlane && m_showHM) {
283 m_hmPlane->DrawLabelDC(dc);
284 }
285}
Element that shows power element informations in workspace.
Definition Text.h:70

◆ DrawScene() [2/2]

void Workspace::DrawScene ( wxGraphicsContext *  gc)
protected

Definition at line 177 of file Workspace.cpp.

178{
179 // Draw
180 if (gc) {
181
182 // HMPlane
183 if (m_hmPlane && m_showHM) {
184#ifdef __WXMSW__
185 const DWORD beforeHMPlane = GetWorkspaceGDIObjects();
186#endif
187 m_hmPlane->DrawDC(gc);
188#ifdef __WXMSW__
189 LogWorkspaceGDIDelta("Workspace::DrawScene HMPlane", beforeHMPlane);
190#endif
191 }
192
193 gc->Scale(m_camera->GetScale(), m_camera->GetScale());
194 gc->Translate(m_camera->GetTranslation().m_x, m_camera->GetTranslation().m_y);
195
196 // Elements
197 for (auto& element : m_elementList) {
198#ifdef __WXMSW__
199 const DWORD beforeElement = GetWorkspaceGDIObjects();
200#endif
201 element->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
202#ifdef __WXMSW__
203 LogWorkspaceGDIDelta(wxString::Format("Workspace::DrawScene element type %d", element->GetElementType()), beforeElement);
204#endif
205 }
206
207 // Dummy Text to set correct context
208 // TODO: Find a better way to do this.
209#ifdef __WXMSW__
210 const DWORD beforeDummyText = GetWorkspaceGDIObjects();
211#endif
212 Text* text = new Text(wxPoint2DDouble(0.0, 0.0), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
213 text->SetText("");
214 text->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
215 delete text;
216#ifdef __WXMSW__
217 LogWorkspaceGDIDelta("Workspace::DrawScene dummy text", beforeDummyText);
218#endif
219
220 // Texts
221 for (auto& text : m_textList) {
222#ifdef __WXMSW__
223 const DWORD beforeText = GetWorkspaceGDIObjects();
224#endif
225 text->DrawDC(m_camera->GetTranslation(), m_camera->GetScale(), gc);
226#ifdef __WXMSW__
227 LogWorkspaceGDIDelta("Workspace::DrawScene text", beforeText);
228#endif
229 }
230
231 // Selection rectangle
232#ifdef __WXMSW__
233 const DWORD beforeSelectionRect = GetWorkspaceGDIObjects();
234#endif
235 gc->SetPen(wxPen(wxColour(0, 125, 255, 255)));
236 gc->SetBrush(wxBrush(wxColour(0, 125, 255, 125)));
237 gc->DrawRectangle(m_selectionRect.m_x, m_selectionRect.m_y, m_selectionRect.m_width, m_selectionRect.m_height);
238#ifdef __WXMSW__
239 LogWorkspaceGDIDelta("Workspace::DrawScene selection rectangle", beforeSelectionRect);
240#endif
241
242 if (m_hmPlane && m_showHM) {
243#ifdef __WXMSW__
244 const DWORD beforeHMLabel = GetWorkspaceGDIObjects();
245#endif
246 m_hmPlane->DrawLabelDC(gc);
247#ifdef __WXMSW__
248 LogWorkspaceGDIDelta("Workspace::DrawScene heatmap label", beforeHMLabel);
249#endif
250 }
251 }
252}

◆ EnableAutoHeatMapLabel()

void Workspace::EnableAutoHeatMapLabel ( const bool &  enable = true)
inline

Definition at line 161 of file Workspace.h.

161{ m_hmAutomaticLabel = enable; }

◆ EnableHeatMap()

void Workspace::EnableHeatMap ( const bool &  enable = true)

Definition at line 2535 of file Workspace.cpp.

2536{
2537 m_showHM = enable;
2538 if (m_showHM) {
2539 UpdateHeatMap();
2540 }
2541 Redraw();
2542}

◆ ExportAsSVG()

void Workspace::ExportAsSVG ( wxString  path)

Definition at line 315 of file Workspace.cpp.

316{
317 wxSize size = GetClientSize();
318
319 wxSVGFileDC svgDC(path, size.x, size.y);
320
321 svgDC.SetClippingRegion(wxRect(0, 0, size.x, size.y));
322
323 DrawScene(svgDC);
324}

◆ FindTextElement()

Element * Workspace::FindTextElement ( Element parentElement,
int  dataType 
)

Definition at line 2003 of file Workspace.cpp.

2004{
2005 for (auto& text : m_textList) {
2006 if (text->GetElement() == parentElement && text->GetDataType() == dataType)
2007 return text.get();
2008 }
2009 return nullptr;
2010}

◆ Fit()

void Workspace::Fit ( )

Definition at line 1716 of file Workspace.cpp.

1717{
1718 wxPoint2DDouble leftUpCorner(0, 0);
1719 wxPoint2DDouble rightDownCorner(0, 0);
1720 std::vector<Element*> elementList = GetElementList();
1721 for (const auto& text : m_textList) { elementList.push_back(text.get()); }
1722
1723 if (!GetElementsCorners(leftUpCorner, rightDownCorner, elementList)) return;
1724 wxPoint2DDouble middleCoords = (leftUpCorner + rightDownCorner) / 2.0;
1725
1726 int width = 0.0;
1727 int height = 0.0;
1728 GetSize(&width, &height);
1729
1730 double scaleX = double(width) / (rightDownCorner.m_x - leftUpCorner.m_x);
1731 double scaleY = double(height) / (rightDownCorner.m_y - leftUpCorner.m_y);
1732
1733 double scale = scaleX < scaleY ? scaleX : scaleY;
1734 if (scale > m_camera->GetZoomMax()) scale = m_camera->GetZoomMax();
1735 if (scale < m_camera->GetZoomMin()) scale = m_camera->GetZoomMin();
1736
1737 m_camera->SetScale(scale);
1738
1739 m_camera->StartTranslation(middleCoords);
1740 m_camera->SetTranslation(wxPoint2DDouble(width / 2, height / 2));
1741
1742 if (m_hmPlane && m_showHM) {
1743 UpdateHeatMap();
1744 }
1745
1746 Redraw();
1747}

◆ GetAllElements()

std::vector< Element * > Workspace::GetAllElements ( ) const

Definition at line 2640 of file Workspace.cpp.

2641{
2642 std::vector<Element*> allElements;
2643
2644 for (auto& element : m_elementList) allElements.push_back(element.get());
2645 for (auto& text : m_textList) allElements.push_back(text.get());
2646
2647 return allElements;
2648}

◆ GetCamera()

Camera * Workspace::GetCamera ( ) const
inline

Definition at line 130 of file Workspace.h.

130{ return m_camera; }

◆ GetElementList()

std::vector< Element * > Workspace::GetElementList ( ) const

Definition at line 2672 of file Workspace.cpp.

2673{
2674 std::vector<Element*> elementList;
2675 for (auto& element : m_elementList) elementList.push_back(element.get());
2676 return elementList;
2677}

◆ GetElementNumber()

int Workspace::GetElementNumber ( ElementID  elementID)
inline

Definition at line 175 of file Workspace.h.

175{ return m_elementNumber[elementID]; }

◆ GetElementNumberFromList()

int Workspace::GetElementNumberFromList ( Element element)
protected

Definition at line 1310 of file Workspace.cpp.

1311{
1312 int elementNum = 0;
1313 for (auto& elementFromList : m_elementList) {
1314 if (element->GetElementType() == elementFromList->GetElementType()) {
1315 if (element == elementFromList.get()) return elementNum;
1316 elementNum++;
1317 }
1318 }
1319 return 0;
1320}

◆ GetElementsCorners()

bool Workspace::GetElementsCorners ( wxPoint2DDouble &  leftUpCorner,
wxPoint2DDouble &  rightDownCorner,
std::vector< Element * >  elementList 
)

Definition at line 1695 of file Workspace.cpp.

1698{
1699 if (elementList.size() == 0) return false;
1700
1701 elementList[0]->CalculateBoundaries(leftUpCorner, rightDownCorner);
1702
1703 for (auto it = elementList.begin() + 1, itEnd = elementList.end(); it != itEnd; it++) {
1704 Element* element = *it;
1705 wxPoint2DDouble leftUp;
1706 wxPoint2DDouble rightDown;
1707 element->CalculateBoundaries(leftUp, rightDown);
1708 if (leftUp.m_x < leftUpCorner.m_x) leftUpCorner.m_x = leftUp.m_x;
1709 if (leftUp.m_y < leftUpCorner.m_y) leftUpCorner.m_y = leftUp.m_y;
1710 if (rightDown.m_x > rightDownCorner.m_x) rightDownCorner.m_x = rightDown.m_x;
1711 if (rightDown.m_y > rightDownCorner.m_y) rightDownCorner.m_y = rightDown.m_y;
1712 }
1713 return true;
1714}
virtual void CalculateBoundaries(wxPoint2DDouble &leftUp, wxPoint2DDouble &rightBottom) const
Calculate the element boundaries.
Definition Element.cpp:406

◆ GetElementSharedList()

std::vector< std::shared_ptr< PowerElement > > Workspace::GetElementSharedList ( ) const
inline

Definition at line 126 of file Workspace.h.

126{ return m_elementList; }

◆ GetHeatMap()

HMPlane * Workspace::GetHeatMap ( ) const
inline

Definition at line 160 of file Workspace.h.

160{ return m_hmPlane; }

◆ GetName()

wxString Workspace::GetName ( ) const
inline

Definition at line 124 of file Workspace.h.

124{ return m_name; }

◆ GetProperties()

PropertiesData * Workspace::GetProperties ( ) const
inline

Definition at line 177 of file Workspace.h.

177{ return m_properties; }

◆ GetSavedPath()

wxFileName Workspace::GetSavedPath ( ) const
inline

Definition at line 139 of file Workspace.h.

139{ return m_savedPath; }

◆ GetStabilityTimeVector()

std::vector< double > Workspace::GetStabilityTimeVector ( ) const
inline

Definition at line 178 of file Workspace.h.

178{ return m_stabilityTimeVector; }

◆ GetStateListsCopy()

void Workspace::GetStateListsCopy ( const std::vector< std::shared_ptr< PowerElement > > &  elementsList,
const std::vector< std::shared_ptr< Text > > &  textList,
std::vector< std::shared_ptr< PowerElement > > &  elementsListCopy,
std::vector< std::shared_ptr< Text > > &  textListCopy 
)
protected

Definition at line 1322 of file Workspace.cpp.

1326{
1327 // Free copy lists first
1328 //for (auto& element : elementsListCopy) delete element;
1329 //for (auto& text : textListCopy) delete text;
1330 elementsListCopy.clear();
1331 textListCopy.clear();
1332
1333 std::map<Element*, Element*> elementMap;
1334
1335 for (auto& element : elementsList) {
1336#ifdef __WXMSW__
1337 const DWORD beforeElementCopy = GetWorkspaceGDIObjects();
1338#endif
1339 PowerElement* copyElement = static_cast<PowerElement*>(element->GetCopy());
1340#ifdef __WXMSW__
1341 LogWorkspaceGDIDelta(wxString::Format("Workspace::GetStateListsCopy element copy type %d", element->GetElementType()), beforeElementCopy);
1342#endif
1343 elementsListCopy.emplace_back(copyElement);
1344 elementMap[element.get()] = copyElement;
1345 }
1346 // Correct the parent and child pointers
1347 for (auto& copyElement : elementsListCopy) {
1348 // Parent
1349 int i = 0;
1350 for (Element* parent : copyElement->GetParentList()) {
1351 auto it = elementMap.find(parent);
1352
1353 if (it != elementMap.end())
1354 copyElement->SetParent(it->second, i);
1355
1356 i++;
1357 }
1358 // Child
1359 i = 0;
1360 for (Element* child : copyElement->GetChildList()) {
1361 auto it = elementMap.find(child);
1362
1363 if (it != elementMap.end())
1364 copyElement->SetChild(it->second, i);
1365
1366 i++;
1367 }
1368 }
1369
1370 for (const auto& text : textList) {
1371#ifdef __WXMSW__
1372 const DWORD beforeTextCopy = GetWorkspaceGDIObjects();
1373#endif
1374 auto copyText = static_cast<Text*>(text->GetCopy());
1375#ifdef __WXMSW__
1376 LogWorkspaceGDIDelta("Workspace::GetStateListsCopy text copy", beforeTextCopy);
1377#endif
1378 // Set text the correct element associated with the text
1379 auto it = elementMap.find(copyText->GetElement());
1380
1381 if (it != elementMap.end())
1382 copyText->SetElement(it->second);
1383 else
1384 copyText->SetElement(nullptr);
1385 textListCopy.emplace_back(copyText);
1386 }
1387}
Abstract class of power elements.

◆ GetTextList()

std::vector< std::shared_ptr< Text > > Workspace::GetTextList ( ) const
inline

Definition at line 127 of file Workspace.h.

127{ return m_textList; }

◆ GetWorkspaceMode()

WorkspaceMode Workspace::GetWorkspaceMode ( ) const
inline

Definition at line 129 of file Workspace.h.

129{ return m_mode; }

◆ IncrementElementNumber()

void Workspace::IncrementElementNumber ( ElementID  elementID)
inline

Definition at line 176 of file Workspace.h.

176{ m_elementNumber[elementID]++; }

◆ InsertTextElement()

bool Workspace::InsertTextElement ( int  textID,
Element parentElement,
ElectricalUnit  unit = ElectricalUnit::UNIT_NONE,
int  precision = 2 
)

Definition at line 1749 of file Workspace.cpp.

1750{
1751 switch (textID) {
1752 case ID_TXT_NAME: {
1753 if (FindTextElement(parentElement, DATA_NAME)) return false; // Avoid inserting more than one text element of the same type for an element.
1754 //Text* newText = new Text(parentElement->GetPosition() + wxPoint2DDouble(40, -30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1755 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(40, -30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1756 newText->SetElement(parentElement);
1757 newText->SetDataType(DATA_NAME);
1758 newText->SetElementTypeText(parentElement->GetElementType());
1759 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1760
1761 m_textList.push_back(newText);
1762 } break;
1763 case ID_TXT_VOLTAGE: {
1764 if (FindTextElement(parentElement, DATA_VOLTAGE)) return false;
1765 //Text* newText = new Text(parentElement->GetPosition() + wxPoint2DDouble(40, 15), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1766 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(40, 15), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1767 newText->SetElement(parentElement);
1768 newText->SetDataType(DATA_VOLTAGE);
1769 if (unit == ElectricalUnit::UNIT_NONE)
1770 newText->SetUnit(ElectricalUnit::UNIT_PU);
1771 else
1772 newText->SetUnit(unit);
1773 newText->SetDecimalPlaces(precision);
1774 newText->SetElementTypeText(parentElement->GetElementType());
1775 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1776
1777 m_textList.emplace_back(newText);
1778 } break;
1779 case ID_TXT_ANGLE: {
1780 if (FindTextElement(parentElement, DATA_ANGLE)) return false;
1781 //Text* newText = new Text(parentElement->GetPosition() + wxPoint2DDouble(40, 30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1782 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(40, 30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1783 newText->SetElement(parentElement);
1784 newText->SetDataType(DATA_ANGLE);
1785 if (unit == ElectricalUnit::UNIT_NONE)
1786 newText->SetUnit(ElectricalUnit::UNIT_DEGREE);
1787 else
1788 newText->SetUnit(unit);
1789 newText->SetDecimalPlaces(precision);
1790 newText->SetElementTypeText(parentElement->GetElementType());
1791 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1792
1793 m_textList.emplace_back(newText);
1794 } break;
1795 case ID_TXT_FAULTCURRENT: {
1796 if (FindTextElement(parentElement, DATA_SC_CURRENT)) return false;
1797 //Text* newText = new Text(parentElement->GetPosition() + wxPoint2DDouble(-70, 30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1798 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(-70, 30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1799 newText->SetElement(parentElement);
1800 newText->SetDataType(DATA_SC_CURRENT);
1801 if (unit == ElectricalUnit::UNIT_NONE)
1802 newText->SetUnit(ElectricalUnit::UNIT_A);
1803 else
1804 newText->SetUnit(unit);
1805 newText->SetDecimalPlaces(precision);
1806 newText->SetElementTypeText(parentElement->GetElementType());
1807 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1808
1809 m_textList.emplace_back(newText);
1810 } break;
1811 case ID_TXT_FAULTVOLTAGE: {
1812 if (FindTextElement(parentElement, DATA_SC_VOLTAGE)) return false;
1813 //Text* newText = new Text(parentElement->GetPosition() + wxPoint2DDouble(-70, 75), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1814 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(-70, 75), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1815 newText->SetElement(parentElement);
1816 newText->SetDataType(DATA_SC_VOLTAGE);
1817 if (unit == ElectricalUnit::UNIT_NONE)
1818 newText->SetUnit(ElectricalUnit::UNIT_PU);
1819 else
1820 newText->SetUnit(unit);
1821 newText->SetDecimalPlaces(precision);
1822 newText->SetElementTypeText(parentElement->GetElementType());
1823 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1824
1825 m_textList.emplace_back(newText);
1826 } break;
1827 case ID_TXT_SCC: {
1828 if (FindTextElement(parentElement, DATA_SC_POWER)) return false;
1829 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(-50, -30), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1830 newText->SetElement(parentElement);
1831 newText->SetDataType(DATA_SC_POWER);
1832 newText->SetUnit(ElectricalUnit::UNIT_MVA);
1833 if (unit == ElectricalUnit::UNIT_NONE)
1834 newText->SetUnit(ElectricalUnit::UNIT_MVA);
1835 else
1836 newText->SetUnit(unit);
1837 newText->SetDecimalPlaces(precision);
1838 newText->SetElementTypeText(parentElement->GetElementType());
1839 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1840
1841 m_textList.emplace_back(newText);
1842 } break;
1843 case ID_TXT_THD: {
1844 if (FindTextElement(parentElement, DATA_PQ_THD)) return false;
1845 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(-50, -15), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1846 newText->SetElement(parentElement);
1847 newText->SetDataType(DATA_PQ_THD);
1848 newText->SetDecimalPlaces(precision);
1849 newText->SetElementTypeText(parentElement->GetElementType());
1850 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1851
1852 m_textList.emplace_back(newText);
1853 } break;
1854 case ID_TXT_ACTIVE_POWER: {
1855 if (FindTextElement(parentElement, DATA_ACTIVE_POWER)) return false;
1856 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(0, 35), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1857 newText->SetElement(parentElement);
1858 newText->SetDataType(DATA_ACTIVE_POWER);
1859 if (unit == ElectricalUnit::UNIT_NONE)
1860 newText->SetUnit(ElectricalUnit::UNIT_MW);
1861 else
1862 newText->SetUnit(unit);
1863 newText->SetDecimalPlaces(precision);
1864 newText->SetElementTypeText(parentElement->GetElementType());
1865 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1866
1867 m_textList.emplace_back(newText);
1868 } break;
1869 case ID_TXT_REACTIVE_POWER: {
1870 if (FindTextElement(parentElement, DATA_REACTIVE_POWER)) return false;
1871 auto newText = std::make_shared<Text>(parentElement->GetPosition() + wxPoint2DDouble(0, 50), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1872 newText->SetElement(parentElement);
1873 newText->SetDataType(DATA_REACTIVE_POWER);
1874 if (unit == ElectricalUnit::UNIT_NONE)
1875 newText->SetUnit(ElectricalUnit::UNIT_Mvar);
1876 else
1877 newText->SetUnit(unit);
1878 newText->SetDecimalPlaces(precision);
1879 newText->SetElementTypeText(parentElement->GetElementType());
1880 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1881
1882 m_textList.emplace_back(newText);
1883 } break;
1884 case ID_TXT_BRANCH_ACTIVE_POWER_1_2:
1885 case ID_TXT_BRANCH_ACTIVE_POWER_2_1: {
1886 if (FindTextElement(parentElement, DATA_PF_ACTIVE)) return false;
1887 wxPoint2DDouble position(0.0, -10.0);
1888 if (textID == ID_TXT_BRANCH_ACTIVE_POWER_1_2)
1889 position += 2.0 * parentElement->GetPointList()[1] - parentElement->GetPointList()[0];
1890 else
1891 position += 2.0 * parentElement->GetPointList()[parentElement->GetPointList().size() - 2] - parentElement->GetPointList()[parentElement->GetPointList().size() - 1];
1892
1893 auto newText = std::make_shared<Text>(position, m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1894 newText->SetElement(parentElement);
1895 newText->SetDataType(DATA_PF_ACTIVE);
1896 if (unit == ElectricalUnit::UNIT_NONE)
1897 newText->SetUnit(ElectricalUnit::UNIT_MW);
1898 else
1899 newText->SetUnit(unit);
1900 newText->SetDecimalPlaces(precision);
1901 newText->SetElementTypeText(parentElement->GetElementType());
1902 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1903 if (textID == ID_TXT_BRANCH_ACTIVE_POWER_2_1)
1904 newText->SetDirection(1); // std is 0
1905
1906 m_textList.emplace_back(newText);
1907 } break;
1908 case ID_TXT_BRANCH_REACTIVE_POWER_1_2:
1909 case ID_TXT_BRANCH_REACTIVE_POWER_2_1: {
1910 if (FindTextElement(parentElement, DATA_PF_REACTIVE)) return false;
1911 wxPoint2DDouble position(0.0, 10.0);
1912 if (textID == ID_TXT_BRANCH_REACTIVE_POWER_1_2)
1913 position += 2.0 * parentElement->GetPointList()[1] - parentElement->GetPointList()[0];
1914 else
1915 position += 2.0 * parentElement->GetPointList()[parentElement->GetPointList().size() - 2] - parentElement->GetPointList()[parentElement->GetPointList().size() - 1];
1916
1917 auto newText = std::make_shared<Text>(position, m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1918 newText->SetElement(parentElement);
1919 newText->SetDataType(DATA_PF_REACTIVE);
1920 if (unit == ElectricalUnit::UNIT_NONE)
1921 newText->SetUnit(ElectricalUnit::UNIT_Mvar);
1922 else
1923 newText->SetUnit(unit);
1924 newText->SetDecimalPlaces(precision);
1925 newText->SetElementTypeText(parentElement->GetElementType());
1926 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1927 if (textID == ID_TXT_BRANCH_REACTIVE_POWER_2_1)
1928 newText->SetDirection(1); // std is 0
1929
1930 m_textList.emplace_back(newText);
1931 } break;
1932 case ID_TXT_BRANCH_LOSSES: {
1933 if (FindTextElement(parentElement, DATA_PF_LOSSES)) return false;
1934 wxPoint2DDouble position = wxPoint2DDouble(0, 35) + (parentElement->GetPointList()[0] + parentElement->GetPointList()[parentElement->GetPointList().size() - 1]) / 2.0;
1935 auto newText = std::make_shared<Text>(position, m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1936 newText->SetElement(parentElement);
1937 newText->SetDataType(DATA_PF_LOSSES);
1938 if (unit == ElectricalUnit::UNIT_NONE)
1939 newText->SetUnit(ElectricalUnit::UNIT_MW);
1940 else
1941 newText->SetUnit(unit);
1942 newText->SetDecimalPlaces(precision);
1943 newText->SetElementTypeText(parentElement->GetElementType());
1944 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1945
1946 m_textList.emplace_back(newText);
1947 } break;
1948 case ID_TXT_BRANCH_CURRENT_1_2:
1949 case ID_TXT_BRANCH_CURRENT_2_1: {
1950 if (FindTextElement(parentElement, DATA_PF_CURRENT)) return false;
1951 wxPoint2DDouble position(0.0, 10.0);
1952 if (textID == ID_TXT_BRANCH_CURRENT_1_2)
1953 position += 2.0 * parentElement->GetPointList()[1] - parentElement->GetPointList()[0];
1954 else
1955 position += 2.0 * parentElement->GetPointList()[parentElement->GetPointList().size() - 2] - parentElement->GetPointList()[parentElement->GetPointList().size() - 1];
1956
1957 auto newText = std::make_shared<Text>(position, m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1958 newText->SetElement(parentElement);
1959 newText->SetDataType(DATA_PF_CURRENT);
1960 if (unit == ElectricalUnit::UNIT_NONE)
1961 newText->SetUnit(ElectricalUnit::UNIT_A);
1962 else
1963 newText->SetUnit(unit);
1964 newText->SetDecimalPlaces(precision);
1965 newText->SetElementTypeText(parentElement->GetElementType());
1966 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1967 if (textID == ID_TXT_BRANCH_CURRENT_2_1)
1968 newText->SetDirection(1); // std is 0
1969
1970 m_textList.emplace_back(newText);
1971 } break;
1972 case ID_TXT_BRANCH_FAULT_CURRENT_1_2:
1973 case ID_TXT_BRANCH_FAULT_CURRENT_2_1: {
1974 if (FindTextElement(parentElement, DATA_SC_CURRENT)) return false;
1975 wxPoint2DDouble position(0.0, 25.0);
1976 if (textID == ID_TXT_BRANCH_FAULT_CURRENT_1_2)
1977 position += 2.0 * parentElement->GetPointList()[1] - parentElement->GetPointList()[0];
1978 else
1979 position += 2.0 * parentElement->GetPointList()[parentElement->GetPointList().size() - 2] - parentElement->GetPointList()[parentElement->GetPointList().size() - 1];
1980
1981 auto newText = std::make_shared<Text>(position, m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1982 newText->SetElement(parentElement);
1983 newText->SetDataType(DATA_SC_CURRENT);
1984 if (unit == ElectricalUnit::UNIT_NONE)
1985 newText->SetUnit(ElectricalUnit::UNIT_kA);
1986 else
1987 newText->SetUnit(unit);
1988 newText->SetDecimalPlaces(precision);
1989 newText->SetElementTypeText(parentElement->GetElementType());
1990 newText->SetElementNumber(GetElementNumberFromList(parentElement));
1991 if (textID == ID_TXT_BRANCH_FAULT_CURRENT_2_1)
1992 newText->SetDirection(1); // std is 0
1993
1994 m_textList.emplace_back(newText);
1995 } break;
1996 default:
1997 return false;
1998 break;
1999 }
2000 return true;
2001}
virtual std::vector< wxPoint2DDouble > GetPointList() const
Get the list of points that connect the element to bus.
Definition Element.h:231
wxPoint2DDouble GetPosition() const
Get the element position.
Definition Element.h:186

◆ IsContinuousCalculationActive()

bool Workspace::IsContinuousCalculationActive ( ) const
inline

Definition at line 179 of file Workspace.h.

179{ return m_continuousCalc; }

◆ IsHeatMapAutoLabelEnable()

bool Workspace::IsHeatMapAutoLabelEnable ( ) const
inline

Definition at line 162 of file Workspace.h.

162{ return m_hmAutomaticLabel; }

◆ IsHeatMapEnable()

bool Workspace::IsHeatMapEnable ( ) const
inline

Definition at line 159 of file Workspace.h.

159{ return m_showHM; }

◆ OnHeatMapTime()

void Workspace::OnHeatMapTime ( wxTimerEvent &  event)
protectedvirtual

Definition at line 2932 of file Workspace.cpp.

2933{
2934 if (m_showHMTimer) {
2935 UpdateHeatMap();
2936 Redraw();
2937 m_showHMTimer = false;
2938 }
2939}

◆ OnIdle()

void Workspace::OnIdle ( wxIdleEvent &  event)
virtual

Definition at line 2610 of file Workspace.cpp.

2611{
2612 /*
2613 // The OpenGL element (m_glCanvas) must be completely initialized (showed) to draw properly the textures and init glew.
2614 // TODO(?): Find other solution to text displayed wrong on opened file.
2615 if (m_justOpened) {
2616 if (UpdateTextElements()) m_justOpened = false;
2617 if (glewInit() != GLEW_OK)
2618 wxMessageBox("Erro ao iniciar glew ='(");
2619 else
2620 {
2621 // Load and create shader
2622 m_basicShader = new Shader("..//data//shaders//Basic.shader");
2623 m_hmLabelShader = new Shader("..//data//shaders//HMLabel.shader");
2624 float limits[2] = { 1.05, 0.95 };
2625 m_hmPlane = new HMPlane(m_basicShader, m_hmLabelShader, m_width, m_height, limits);
2626 }
2627
2628 Redraw();
2629 }
2630 */
2631 if (m_justOpened) {
2632 m_justOpened = false;
2633 double limits[2] = { 1.05, 0.95 };
2634 m_hmPlane = new HMPlane(m_width, m_height, limits);
2635
2636 Redraw();
2637 }
2638}

◆ OnKeyDown()

void Workspace::OnKeyDown ( wxKeyEvent &  event)
virtual

Definition at line 992 of file Workspace.cpp.

993{
994 bool insertingElement = false;
995 if (m_mode == WorkspaceMode::MODE_INSERT || m_mode == WorkspaceMode::MODE_INSERT_TEXT) insertingElement = true;
996
997 char key = event.GetUnicodeKey();
998 if (key != WXK_NONE) {
999 switch (key) {
1000 case WXK_ESCAPE: // Cancel operations.
1001 {
1002 if (m_mode == WorkspaceMode::MODE_INSERT) {
1003 //Element* elementToDelete = m_elementList[m_elementList.size() - 1];
1004 auto elementToDelete = m_elementList.back();
1005
1006 // Remove child element that has to be deleted (specially buses)
1007 for (auto& element : m_elementList) {
1008 element->RemoveChild(elementToDelete.get());
1009 }
1010
1011 m_elementList.pop_back(); // Removes the last element being inserted.
1012 m_mode = WorkspaceMode::MODE_EDIT;
1013 Redraw();
1014 }
1015 else if (m_mode == WorkspaceMode::MODE_INSERT_TEXT) {
1016 m_textList.pop_back();
1017 m_mode = WorkspaceMode::MODE_EDIT;
1018 Redraw();
1019 }
1020 } break;
1021 case WXK_DELETE: // Delete selected elements
1022 {
1023 DeleteSelectedElements();
1024 } break;
1025 case 'A': {
1026 if (!insertingElement) {
1027 //Text* newText = new Text(m_camera->ScreenToWorld(event.GetPosition()), m_properties->GetGeneralPropertiesData().labelFont, m_properties->GetGeneralPropertiesData().labelFontSize);
1028 auto newText = std::make_shared<Text>(
1029 m_camera->ScreenToWorld(event.GetPosition()),
1030 m_properties->GetGeneralPropertiesData().labelFont,
1031 m_properties->GetGeneralPropertiesData().labelFontSize);
1032 m_textList.push_back(newText);
1033 m_mode = WorkspaceMode::MODE_INSERT_TEXT;
1034 m_statusBar->SetStatusText(_("Insert Text: Click to insert, ESC to cancel."));
1035 if (m_hmPlane && m_showHM) {
1036 m_hmPlane->Clear();
1037 }
1038 Redraw();
1039 }
1040 } break;
1041 case 'F': {
1042 if (event.GetModifiers() == wxMOD_SHIFT) { Fit(); }
1043 } break;
1044 case 'R': // Rotate the selected elements.
1045 {
1046 RotateSelectedElements(event.GetModifiers() != wxMOD_SHIFT);
1047 } break;
1048 case 'B': // Insert a bus.
1049 {
1050 if (!insertingElement) {
1051 auto newBus = std::make_shared<Bus>(m_camera->ScreenToWorld(event.GetPosition()),
1052 wxString::Format(_("Bus %d"), GetElementNumber(ID_BUS)));
1053 IncrementElementNumber(ID_BUS);
1054 m_elementList.push_back(newBus);
1055 m_mode = WorkspaceMode::MODE_INSERT;
1056 m_statusBar->SetStatusText(_("Insert Bus: Click to insert, ESC to cancel."));
1057 if (m_hmPlane && m_showHM) {
1058 m_hmPlane->Clear();
1059 }
1060 Redraw();
1061 }
1062 } break;
1063 case 'L': {
1064 if (!insertingElement) {
1065 if (!event.ControlDown() && event.ShiftDown()) { // Insert a load.
1066 auto newLoad = std::make_shared<Load>(wxString::Format(_("Load %d"), GetElementNumber(ID_LOAD)));
1067 IncrementElementNumber(ID_LOAD);
1068 m_elementList.push_back(newLoad);
1069 m_mode = WorkspaceMode::MODE_INSERT;
1070 m_statusBar->SetStatusText(_("Insert Load: Click on a bus, ESC to cancel."));
1071 }
1072 else if (!event.ControlDown() && !event.ShiftDown()) { // Insert a power line.
1073 auto newLine = std::make_shared<Line>(wxString::Format(_("Line %d"), GetElementNumber(ID_LINE)));
1074 IncrementElementNumber(ID_LINE);
1075 m_elementList.push_back(newLine);
1076 m_mode = WorkspaceMode::MODE_INSERT;
1077 m_statusBar->SetStatusText(_("Insert Line: Click on two buses, ESC to cancel."));
1078 }
1079 if (m_hmPlane && m_showHM) {
1080 m_hmPlane->Clear();
1081 }
1082 Redraw();
1083 }
1084 // Tests - Ctrl + Shift + L
1085 } break;
1086 case 'T': // Insert a transformer.
1087 {
1088 if (!insertingElement) {
1089 auto newTransformer = std::make_shared<Transformer>(wxString::Format(_("Transformer %d"), GetElementNumber(ID_TRANSFORMER)));
1090 IncrementElementNumber(ID_TRANSFORMER);
1091 m_elementList.push_back(newTransformer);
1092 m_mode = WorkspaceMode::MODE_INSERT;
1093 m_statusBar->SetStatusText(_("Insert Transformer: Click on two buses, ESC to cancel."));
1094 if (m_hmPlane && m_showHM) {
1095 m_hmPlane->Clear();
1096 }
1097 Redraw();
1098 }
1099 } break;
1100 case 'G': // Insert a generator.
1101 {
1102 if (!insertingElement) {
1103 auto newGenerator = std::make_shared<SyncGenerator>(wxString::Format(_("Generator %d"), GetElementNumber(ID_SYNCGENERATOR)));
1104 IncrementElementNumber(ID_SYNCGENERATOR);
1105 m_elementList.push_back(newGenerator);
1106 m_mode = WorkspaceMode::MODE_INSERT;
1107 m_statusBar->SetStatusText(_("Insert Generator: Click on a bus, ESC to cancel."));
1108 if (m_hmPlane && m_showHM) {
1109 m_hmPlane->Clear();
1110 }
1111 Redraw();
1112 }
1113 } break;
1114 case 'I': {
1115 if (!insertingElement) {
1116 if (event.GetModifiers() == wxMOD_SHIFT) { // Insert an inductor.
1117 auto newInductor = std::make_shared<Inductor>(wxString::Format(_("Inductor %d"), GetElementNumber(ID_INDUCTOR)));
1118 IncrementElementNumber(ID_INDUCTOR);
1119 m_elementList.push_back(newInductor);
1120 m_mode = WorkspaceMode::MODE_INSERT;
1121 m_statusBar->SetStatusText(_("Insert Inductor: Click on a bus, ESC to cancel."));
1122 }
1123 else // Insert an induction motor.
1124 {
1125 auto newIndMotor = std::make_shared<IndMotor>(wxString::Format(_("Induction motor %d"), GetElementNumber(ID_INDMOTOR)));
1126 IncrementElementNumber(ID_INDMOTOR);
1127 m_elementList.push_back(newIndMotor);
1128 m_mode = WorkspaceMode::MODE_INSERT;
1129 m_statusBar->SetStatusText(_("Insert Induction Motor: Click on a bus, ESC to cancel."));
1130 }
1131 if (m_hmPlane && m_showHM) {
1132 m_hmPlane->Clear();
1133 }
1134 Redraw();
1135 }
1136 } break;
1137 case 'K': // Insert a synchronous condenser.
1138 {
1139 if (!insertingElement) {
1140 auto newSyncCondenser = std::make_shared<SyncMotor>(wxString::Format(_("Synchronous condenser %d"), GetElementNumber(ID_SYNCMOTOR)));
1141 IncrementElementNumber(ID_SYNCMOTOR);
1142 m_elementList.push_back(newSyncCondenser);
1143 m_mode = WorkspaceMode::MODE_INSERT;
1144 m_statusBar->SetStatusText(_("Insert Synchronous Condenser: Click on a bus, ESC to cancel."));
1145 if (m_hmPlane && m_showHM) {
1146 m_hmPlane->Clear();
1147 }
1148 Redraw();
1149 }
1150 } break;
1151 case 'C': {
1152 if (!insertingElement) {
1153 if (event.GetModifiers() == wxMOD_SHIFT) { // Insert a capacitor.
1154 auto newCapacitor = std::make_shared<Capacitor>(wxString::Format(_("Capacitor %d"), GetElementNumber(ID_CAPACITOR)));
1155 IncrementElementNumber(ID_CAPACITOR);
1156 m_elementList.push_back(newCapacitor);
1157 m_mode = WorkspaceMode::MODE_INSERT;
1158 m_statusBar->SetStatusText(_("Insert Capacitor: Click on a bus, ESC to cancel."));
1159 if (m_hmPlane && m_showHM) {
1160 m_hmPlane->Clear();
1161 }
1162 Redraw();
1163 }
1164 else if (event.GetModifiers() == wxMOD_CONTROL) { // Copy.
1165 CopySelection();
1166 }
1167 }
1168 } break;
1169 case 'H': {
1170 if (!insertingElement) {
1171 if (event.ShiftDown() && event.ControlDown()) {
1172 if (!m_showHM) {
1173 m_showHM = true;
1174 UpdateHeatMap();
1175 }
1176 else {
1177 m_showHM = false;
1178 }
1179
1180 }
1181 else if (event.GetModifiers() == wxMOD_SHIFT) { // Insert an harmonic current source.
1182 auto newHarmCurrent = std::make_shared<HarmCurrent>(
1183 wxString::Format(_("Harmonic Current %d"), GetElementNumber(ID_HARMCURRENT)));
1184 IncrementElementNumber(ID_HARMCURRENT);
1185 m_elementList.push_back(newHarmCurrent);
1186 m_mode = WorkspaceMode::MODE_INSERT;
1187 m_statusBar->SetStatusText(
1188 _("Insert Harmonic Current Source: Click on a bus, ESC to cancel."));
1189 }
1190 if (m_hmPlane && m_showHM) {
1191 m_hmPlane->Clear();
1192 }
1193 Redraw();
1194 }
1195 } break;
1196 case 'V': {
1197 if (!insertingElement) {
1198 if (event.GetModifiers() == wxMOD_CONTROL) { Paste(); }
1199 }
1200 } break;
1201 case 'S': {
1202 if (!insertingElement) {
1203 if (event.GetModifiers() == wxMOD_CONTROL) {
1204 // Save the workspace.
1205 FileHanding fileHandling(this);
1206
1207 if (GetSavedPath().IsOk()) {
1208 fileHandling.SaveProject(GetSavedPath());
1209 }
1210 else {
1211 wxFileDialog saveFileDialog(this, _("Save PSP file"), "", "", "PSP files (*.psp)|*.psp",
1212 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1213 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
1214
1215 fileHandling.SaveProject(saveFileDialog.GetPath());
1216 wxFileName fileName(saveFileDialog.GetPath());
1217 SetName(fileName.GetName());
1218 if (m_auiNotebook) m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(this), GetName());
1219 SetSavedPath(fileName);
1220 }
1221 }
1222 }
1223 } break;
1224 case 'Z': {
1225 if (!insertingElement) {
1226 if (event.ControlDown() && !event.ShiftDown()) { SetPreviousState(); }
1227 if (event.ControlDown() && event.ShiftDown()) { SetNextState(); }
1228 }
1229 } break;
1230 case 'Y': {
1231 if (!insertingElement) {
1232 if (event.GetModifiers() == wxMOD_CONTROL) { SetNextState(); }
1233 }
1234 } break;
1235 case 'E': {
1236 if (!insertingElement) {
1237 if (event.GetModifiers() == wxMOD_SHIFT) {
1238
1239 if (!insertingElement) {
1240 auto newEMTElement = std::make_shared<EMTElement>(wxString::Format(_("Electromagnetic Element %d"), GetElementNumber(ID_EMTELEMENT)));
1241 IncrementElementNumber(ID_EMTELEMENT);
1242 m_elementList.push_back(newEMTElement);
1243 m_mode = WorkspaceMode::MODE_INSERT;
1244 m_statusBar->SetStatusText(_("Insert Electromagnetic Transient Element: Click on a bus, ESC to cancel."));
1245 if (m_hmPlane && m_showHM) {
1246 m_hmPlane->Clear();
1247 }
1248 Redraw();
1249 }
1250 }
1251 }
1252 } break;
1253#ifdef _DEBUG
1254#ifdef SHOW_DEBUG_PANEL
1255 case 'D': {
1256 if (event.GetModifiers() == wxMOD_CONTROL) {
1257 if (m_debugFrame) {
1258 m_debugFrame->SetFocus();
1259 }
1260 }
1261 } break;
1262#endif
1263#endif
1264 default:
1265 break;
1266 }
1267 }
1268
1269 UpdateStatusBar();
1270 event.Skip();
1271}
Save and opens the projects created on disk.
Definition FileHanding.h:43

◆ OnLeftClickDown()

void Workspace::OnLeftClickDown ( wxMouseEvent &  event)
virtual

Definition at line 326 of file Workspace.cpp.

327{
328 wxWindow* dialogParent = wxGetTopLevelParent(this);
329 if (!dialogParent) dialogParent = this;
330 //wxWindow* dialogParent = this;
331
332 wxPoint clickPoint = event.GetPosition();
333 bool foundElement = false;
334 Element* newElement = nullptr;
335 bool showNewElementForm = false;
336 bool clickOnSwitch = false;
337 bool unselectAll = true;
338 std::vector<Element*> notUnselectElementList;
339 std::vector<Text*> notUnselectTextList;
340
341 if (m_mode == WorkspaceMode::MODE_INSERT_TEXT || m_mode == WorkspaceMode::MODE_PASTE || m_mode == WorkspaceMode::MODE_DRAG_PASTE) {
342 m_mode = WorkspaceMode::MODE_EDIT;
343 SaveCurrentState();
344 }
345 else if (m_mode == WorkspaceMode::MODE_INSERT || m_mode == WorkspaceMode::MODE_DRAG_INSERT || m_mode == WorkspaceMode::MODE_DRAG_INSERT_TEXT) {
346 wxPoint2DDouble clickPointWorld = m_camera->ScreenToWorld(clickPoint);
347
348 if (!m_elementList.empty()) {
349 // Get the last element inserted on the list.
350 newElement = m_elementList.back().get();
351 for (auto& element : m_elementList) {
352 // Clicked in any element.
353 if (element->Contains(clickPointWorld)) {
354 // Click at a bus.
355 if (auto bus = dynamic_cast<Bus*>(element.get())) {
356 // Select the bus.
357 bus->SetSelected();
358 foundElement = true; // Element found.
359 // Add the new element's parent. If the element being inserted returns true, back to
360 // edit mode.
361 if (newElement->AddParent(bus, clickPointWorld)) {
362 ValidateElementsVoltages();
363 m_timer->Stop();
364 showNewElementForm = true;
365 m_mode = WorkspaceMode::MODE_EDIT;
366 bus->SetInserted();
367 }
368 }
369 }
370 }
371
372 // The line element can have an undefined number of points.
373 if (!foundElement) {
374 if (auto line = dynamic_cast<Line*>(newElement)) { line->AddPoint(clickPointWorld); }
375 }
376 foundElement = true;
377 unselectAll = false;
378 }
379 }
380 else {
381
382 bool clickPickbox = false;
383
384 for (auto& element : m_elementList) {
385 element->ResetPickboxes(); // Reset pickbox state.
386
387 // Set movement initial position (not necessarily will be moved).
388 element->StartMove(m_camera->ScreenToWorld(clickPoint));
389
390 // Click in selected element node.
391 if (element->NodeContains(m_camera->ScreenToWorld(clickPoint)) != 0 && element->IsSelected()) {
392 m_mode = WorkspaceMode::MODE_MOVE_NODE;
393 m_disconnectedElement = true;
394 foundElement = true;
395 unselectAll = false;
396 if (m_hmPlane && m_showHM) {
397 m_hmPlane->Clear();
398 }
399 }
400
401 // Click in an element.
402 else if (element->Contains(m_camera->ScreenToWorld(clickPoint))) {
403 notUnselectElementList.emplace_back(element.get());
404 if (!foundElement) {
405 if (element->IsSelected()) unselectAll = false;
406 // Select and show pickbox.
407 element->SetSelected();
408 element->ShowPickbox();
409 foundElement = true;
410 // Select the associated text
411 for (auto& text : m_textList) {
412 if (text->GetElement() == element.get()) {
413 notUnselectTextList.emplace_back(text.get());
414 text->SetSelected();
415 text->SetAllowRotation(false);
416 if (unselectAll) text->SetAltSelectionColour();
417 }
418 }
419 }
420 // If pickbox contains the click, move the pickbox
421 if (element->PickboxContains(m_camera->ScreenToWorld(clickPoint))) {
422 m_mode = WorkspaceMode::MODE_MOVE_PICKBOX;
423 clickPickbox = true;
424 }
425 // If didn't found a pickbox, move the element
426 if (!clickPickbox) { m_mode = WorkspaceMode::MODE_MOVE_ELEMENT; }
427
428 if (m_hmPlane && m_showHM) {
429 m_hmPlane->Clear();
430 }
431 }
432
433 // Click in a switch.
434 else if (element->SwitchesContains(m_camera->ScreenToWorld(clickPoint))) {
435 element->SetOnline(element->IsOnline() ? false : true);
436 clickOnSwitch = true;
437 }
438 }
439
440 // Text element
441 for (auto& text : m_textList) {
442 text->StartMove(m_camera->ScreenToWorld(clickPoint));
443
444 if (text->Contains(m_camera->ScreenToWorld(clickPoint))) {
445 notUnselectTextList.emplace_back(text.get());
446 if (!foundElement) {
447 if (text->IsSelected()) unselectAll = false;
448 text->SetSelected();
449 text->SetAltSelectionColour(false);
450 text->SetAllowRotation();
451 m_mode = WorkspaceMode::MODE_MOVE_ELEMENT;
452 foundElement = true;
453 if (m_hmPlane && m_showHM) {
454 m_hmPlane->Clear();
455 }
456 }
457 }
458 }
459 }
460
461 // Unselect all elements
462 if (!event.ControlDown() && unselectAll) {
463 for (auto& element : m_elementList) {
464 bool select = false;
465 for (Element* notUnselectElement : notUnselectElementList) {
466 if (notUnselectElement == element.get()) select = true;
467 }
468 element->SetSelected(select);
469 }
470 for (auto& text : m_textList) {
471 bool select = false;
472 for (auto& notUnselectText : notUnselectTextList) {
473 if (notUnselectText == text.get()) select = true;
474 }
475 text->SetSelected(select);
476 }
477 }
478
479 if (!foundElement && !clickOnSwitch) {
480 m_mode = WorkspaceMode::MODE_SELECTION_RECT;
481 m_startSelRect = m_camera->ScreenToWorld(clickPoint);
482 if (m_hmPlane && m_showHM) {
483 m_hmPlane->Clear();
484 }
485 }
486
487 Redraw();
488 UpdateStatusBar();
489
490 if (showNewElementForm) {
491 if (newElement) {
492 newElement->ShowForm(dialogParent, newElement, this);
493 // Modal dialogs can steal focus; restore it to the workspace panel to keep mouse/keyboard handling consistent.
494 if (m_workspacePanel) m_workspacePanel->SetFocus();
495 CheckSlackBusDuplication(newElement);
496 SaveCurrentState();
497 if (m_continuousCalc) RunStaticStudies();
498 }
499 }
500 if (clickOnSwitch && m_continuousCalc) RunStaticStudies();
501
502 event.Skip();
503}
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Element.h:239
virtual bool ShowForm(wxWindow *parent, Element *element, wxWindow *workspace=nullptr)
Show element data form.
Definition Element.h:587
Power line element.
Definition Line.h:64

◆ OnLeftClickUp()

void Workspace::OnLeftClickUp ( wxMouseEvent &  event)
virtual

Definition at line 625 of file Workspace.cpp.

626{
627 // This event (under certain conditions) deselects the elements and back to edit mode or select the elements using
628 // the selection rectangle.
629 bool foundPickbox = false;
630 bool findNewParent = false;
631 bool updateVoltages = false;
632 bool saveCurrentState = false;
633 auto itnp = m_elementList.begin();
634
635 for (auto it = m_elementList.begin(); it != m_elementList.end(); ++it) {
636 auto& element = *it;
637 // The user was moving a pickbox.
638 if (m_mode == WorkspaceMode::MODE_MOVE_PICKBOX) {
639 // Catch only the element that have the pickbox shown.
640 if (element->IsPickboxShown()) {
641 saveCurrentState = true;
642 // If the element is a bus, check if a node is outside.
643 if (auto bus = dynamic_cast<Bus*>(element.get())) {
644 // Get all the bus children.
645 for (auto child : m_elementList) {
646 for (auto parent : child->GetParentList()) {
647 // The child have a parent that is the element (bus).
648 if (parent == bus) {
649 child->UpdateNodes();
650 m_disconnectedElement = true;
651 }
652 }
653 }
654 //for (int i = 0; i < (int)m_elementList.size(); i++) {
655 // Element* child = m_elementList[i];
656 // for (int j = 0; j < (int)child->GetParentList().size(); j++) {
657 // Element* parent = child->GetParentList()[j];
658 // // The child have a parent that is the element.
659 // if (parent == element) {
660 // child->UpdateNodes();
661 // m_disconnectedElement = true;
662 // }
663 // }
664 //}
665 }
666 }
667 }
668
669 if (m_mode == WorkspaceMode::MODE_SELECTION_RECT) {
670 if (element->Intersects(m_selectionRect)) {
671 element->SetSelected();
672 // Select the associated text
673 for (auto& text : m_textList) {
674 if (text->GetElement() == element.get()) {
675 text->SetSelected();
676 text->SetAltSelectionColour(false);
677 text->SetAllowRotation();
678 }
679 }
680 }
681 //else if (!event.ControlDown()) {
682 // element->SetSelected(false);
683 //}
684 }
685 else if (m_mode == WorkspaceMode::MODE_MOVE_NODE) {
686 if (element->IsSelected()) {
687 saveCurrentState = true;
688 for (auto parent : m_elementList) {
689 if (auto bus = dynamic_cast<Bus*>(parent.get())) {
690 if (element->SetNodeParent(bus)) {
691 parent->AddChild(element.get());
692 findNewParent = true;
693 itnp = it;
694 element->ResetNodes();
695 break;
696 }
697 }
698 }
699 // element->ResetNodes();
700 }
701 }
702 else {
703 // Deselect
704 //if (!event.ControlDown()) {
705 // if (!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetSelected(false); }
706 //}
707
708 if (element->PickboxContains(m_camera->ScreenToWorld(event.GetPosition()))) {
709 foundPickbox = true;
710 }
711 else {
712 element->ShowPickbox(false);
713 element->ResetPickboxes();
714 }
715 }
716 }
717
718 // Text element
719 for (auto& text : m_textList) {
720 if (m_mode == WorkspaceMode::MODE_SELECTION_RECT) {
721 if (text->Intersects(m_selectionRect)) {
722 text->SetSelected();
723 text->SetAltSelectionColour(false);
724 text->SetAllowRotation();
725 }
726 //else if (!event.ControlDown()) {
727 // text->SetSelected(false);
728 //}
729 }
730 //else if (!event.ControlDown()) {
731 // if (!text->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { text->SetSelected(false); }
732 //}
733 }
734 if (m_mode == WorkspaceMode::MODE_MOVE_ELEMENT) saveCurrentState = true;
735
736 if (findNewParent) {
737 std::rotate(itnp, itnp + 1, m_elementList.end());
738 updateVoltages = true;
739 }
740 if (!foundPickbox) { SetCursor(wxCURSOR_ARROW); }
741
742 if (m_mode != WorkspaceMode::MODE_INSERT) { m_mode = WorkspaceMode::MODE_EDIT; }
743
744 if (updateVoltages) { ValidateElementsVoltages(); }
745
746 if (saveCurrentState) SaveCurrentState();
747
748 if (m_continuousCalc && m_disconnectedElement) {
749 m_disconnectedElement = false;
750 RunStaticStudies();
751 }
752
753 m_selectionRect = wxRect2DDouble(0, 0, 0, 0);
754
755 if (m_hmPlane && m_showHM) {
756 m_showHMTimer = true;
757 m_timerHeatMap->Start();
758 }
759
760 Redraw();
761 UpdateStatusBar();
762}

◆ OnLeftDoubleClick()

void Workspace::OnLeftDoubleClick ( wxMouseEvent &  event)
virtual

Definition at line 505 of file Workspace.cpp.

506{
507 wxWindow* dialogParent = wxGetTopLevelParent(this);
508 if (!dialogParent) dialogParent = this;
509 //wxWindow* dialogParent = this;
510
511 bool elementEdited = false;
512 bool clickOnSwitch = false;
513 bool redraw = false;
514
515 for (auto& element : m_elementList) {
516 // Click in an element.
517 if (element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
518 bool elementIsBus = false;
519 Bus oldBus;
520 Bus* currentBus = nullptr;
521 if ((currentBus = dynamic_cast<Bus*>(element.get()))) {
522 elementIsBus = true;
523 oldBus = *currentBus;
524 }
525 m_timer->Stop();
526 if (element->ShowForm(dialogParent, element.get(), this)) {
527 CheckSlackBusDuplication(element.get());
528 SaveCurrentState();
529 }
530 // Modal dialogs can steal focus; restore it to the workspace panel to keep mouse/keyboard handling consistent.
531 if (m_workspacePanel) m_workspacePanel->SetFocus();
532 elementEdited = true;
533 redraw = true;
534
535 // If the edited element is a bus and was changed the rated voltage, this voltage must be
536 // propagated through the lines
537 if (elementIsBus) {
538 // The voltage was changed
539 if (oldBus.GetElectricalData().nominalVoltage != currentBus->GetElectricalData().nominalVoltage ||
540 oldBus.GetElectricalData().nominalVoltageUnit !=
541 currentBus->GetElectricalData().nominalVoltageUnit) {
542 // Check if the bus has line as child.
543 std::vector<Element*> childList = element->GetChildList();
544 for (auto itc = childList.begin(), itcEnd = childList.end(); itc != itcEnd; ++itc) {
545 Element* child = *itc;
546 if (typeid(*child) == typeid(Line)) {
547 wxMessageDialog msgDialog(dialogParent, _("Do you want to change the rated voltage of the path?"),
548 _("Warning"), wxYES_NO | wxCENTRE | wxICON_WARNING);
549 if (msgDialog.ShowModal() == wxID_YES)
550 ValidateBusesVoltages(element.get());
551 else {
552 auto data = currentBus->GetElectricalData();
553 data.nominalVoltage = oldBus.GetElectricalData().nominalVoltage;
554 data.nominalVoltageUnit = oldBus.GetElectricalData().nominalVoltageUnit;
555 currentBus->SetElectricalData(data);
556 }
557 break;
558 }
559 }
560 }
561 ValidateElementsVoltages();
562 }
563
564 // Handle only one element per double-click to avoid opening multiple modals in sequence.
565 break;
566 }
567
568 // Click in a switch.
569 else if (element->SwitchesContains(m_camera->ScreenToWorld(event.GetPosition()))) {
570 element->SetOnline(element->IsOnline() ? false : true);
571 clickOnSwitch = true;
572 }
573 }
574
575 // Text element
576 for (auto& text : m_textList) {
577 if (text->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
578 if (text->ShowForm(dialogParent, GetElementList())) SaveCurrentState();
579 // Modal dialogs can steal focus; restore it to the workspace panel to keep mouse/keyboard handling consistent.
580 if (m_workspacePanel) m_workspacePanel->SetFocus();
581 redraw = true;
582 break;
583 }
584 }
585 if (elementEdited) {
586 UpdateTextElements();
587 if (m_continuousCalc) RunStaticStudies();
588 }
589 if (clickOnSwitch && m_continuousCalc) RunStaticStudies();
590
591 if (redraw) Redraw();
592 m_timer->Start();
593}

◆ OnMiddleDoubleClick()

void Workspace::OnMiddleDoubleClick ( wxMouseEvent &  event)
virtual

Definition at line 2743 of file Workspace.cpp.

2744{
2745 Fit();
2746 event.Skip();
2747}

◆ OnMiddleDown()

void Workspace::OnMiddleDown ( wxMouseEvent &  event)
virtual

Definition at line 917 of file Workspace.cpp.

918{
919 // Set to drag mode.
920 switch (m_mode) {
921 case WorkspaceMode::MODE_INSERT: {
922 m_mode = WorkspaceMode::MODE_DRAG_INSERT;
923 } break;
924 case WorkspaceMode::MODE_INSERT_TEXT: {
925 m_mode = WorkspaceMode::MODE_DRAG_INSERT_TEXT;
926 } break;
927 case WorkspaceMode::MODE_PASTE: {
928 m_mode = WorkspaceMode::MODE_DRAG_PASTE;
929 } break;
930 default: {
931 m_mode = WorkspaceMode::MODE_DRAG;
932 } break;
933 }
934 m_camera->StartTranslation(m_camera->ScreenToWorld(event.GetPosition()));
935 UpdateStatusBar();
936
937 if (m_hmPlane && m_showHM) {
938 m_hmPlane->Clear();
939 }
940
941 event.Skip();
942}

◆ OnMiddleUp()

void Workspace::OnMiddleUp ( wxMouseEvent &  event)
virtual

Definition at line 944 of file Workspace.cpp.

945{
946 switch (m_mode) {
947 case WorkspaceMode::MODE_DRAG_INSERT: {
948 m_mode = WorkspaceMode::MODE_INSERT;
949 } break;
950 case WorkspaceMode::MODE_DRAG_INSERT_TEXT: {
951 m_mode = WorkspaceMode::MODE_INSERT_TEXT;
952 } break;
953 case WorkspaceMode::MODE_DRAG_PASTE: {
954 m_mode = WorkspaceMode::MODE_PASTE;
955 } break;
956 case WorkspaceMode::MODE_INSERT:
957 case WorkspaceMode::MODE_INSERT_TEXT:
958 case WorkspaceMode::MODE_PASTE: {
959 // Does nothing.
960 } break;
961 default: {
962 m_mode = WorkspaceMode::MODE_EDIT;
963 } break;
964 }
965 UpdateStatusBar();
966
967 if (m_hmPlane && m_showHM) {
968 UpdateHeatMap();
969 Redraw();
970 }
971
972 event.Skip();
973}

◆ OnMouseMotion()

void Workspace::OnMouseMotion ( wxMouseEvent &  event)
virtual

Definition at line 764 of file Workspace.cpp.

765{
766 bool redraw = false;
767 switch (m_mode) {
768 case WorkspaceMode::MODE_INSERT: {
769 auto& newElement = m_elementList.back(); // Get the last element in the list.
770 newElement->SetPosition(m_camera->ScreenToWorld(event.GetPosition()));
771 redraw = true;
772 } break;
773
774 case WorkspaceMode::MODE_INSERT_TEXT: {
775 auto& newText = m_textList.back();
776 newText->SetPosition(m_camera->ScreenToWorld(event.GetPosition()));
777 redraw = true;
778 } break;
779
780 case WorkspaceMode::MODE_DRAG:
781 case WorkspaceMode::MODE_DRAG_INSERT:
782 case WorkspaceMode::MODE_DRAG_INSERT_TEXT:
783 case WorkspaceMode::MODE_DRAG_PASTE: {
784 m_camera->SetTranslation(event.GetPosition());
785 redraw = true;
786 } break;
787
788 case WorkspaceMode::MODE_EDIT: {
789 bool foundPickbox = false;
790 for (auto& element : m_elementList) {
791 if (element->IsSelected()) {
792 // Show element pickbox (when it has) if the mouse is over the selected object.
793 if (element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
794 element->ShowPickbox();
795 redraw = true;
796
797 // If the mouse is over a pickbox set correct mouse cursor.
798 if (element->PickboxContains(m_camera->ScreenToWorld(event.GetPosition()))) {
799 foundPickbox = true;
800#ifdef __WXMSW__
801 const DWORD beforeCursor = GetWorkspaceGDIObjects();
802#endif
803 SetCursor(element->GetBestPickboxCursor());
804#ifdef __WXMSW__
805 LogWorkspaceGDIDelta(wxString::Format("Workspace::OnMouseMotion pickbox cursor type %d", element->GetElementType()), beforeCursor);
806#endif
807 }
808 else if (!foundPickbox) {
809#ifdef __WXMSW__
810 const DWORD beforeCursor = GetWorkspaceGDIObjects();
811#endif
812 SetCursor(wxCURSOR_ARROW);
813#ifdef __WXMSW__
814 LogWorkspaceGDIDelta("Workspace::OnMouseMotion arrow cursor", beforeCursor);
815#endif
816 element->ResetPickboxes();
817 }
818 }
819 else if (!foundPickbox) {
820 if (element->IsPickboxShown()) redraw = true;
821
822 element->ShowPickbox(false);
823 element->ResetPickboxes();
824#ifdef __WXMSW__
825 const DWORD beforeCursor = GetWorkspaceGDIObjects();
826#endif
827 SetCursor(wxCURSOR_ARROW);
828#ifdef __WXMSW__
829 LogWorkspaceGDIDelta("Workspace::OnMouseMotion arrow cursor", beforeCursor);
830#endif
831 }
832 }
833 }
834 } break;
835
836 case WorkspaceMode::MODE_MOVE_NODE: {
837 for (auto& element : m_elementList) {
838 if (element->IsSelected()) {
839 element->MoveNode(nullptr, m_camera->ScreenToWorld(event.GetPosition()));
840 redraw = true;
841 }
842 }
843 } break;
844
845 case WorkspaceMode::MODE_MOVE_PICKBOX: {
846 for (auto& element : m_elementList) {
847 if (element->IsSelected()) {
848 element->MovePickbox(m_camera->ScreenToWorld(event.GetPosition()));
849 redraw = true;
850 }
851 }
852 if (m_hmPlane && m_showHM) {
853 m_hmPlane->Clear();
854 }
855 } break;
856
857 case WorkspaceMode::MODE_MOVE_ELEMENT:
858 case WorkspaceMode::MODE_PASTE: {
859 for (auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) {
860 auto element = *it;
861 if (element->IsSelected()) {
862 element->Move(m_camera->ScreenToWorld(event.GetPosition()));
863 // Move child nodes
864 std::vector<Element*> childList = element->GetChildList();
865 for (auto it = childList.begin(), itEnd = childList.end(); it != itEnd; ++it) {
866 (*it)->MoveNode(element.get(), m_camera->ScreenToWorld(event.GetPosition()));
867 }
868 redraw = true;
869 }
870 }
871 // Text element motion
872 for (auto& text : m_textList) {
873 if (text->IsSelected()) {
874 text->Move(m_camera->ScreenToWorld(event.GetPosition()));
875 redraw = true;
876 }
877 }
878 if (m_hmPlane && m_showHM) {
879 m_hmPlane->Clear();
880 }
881 } break;
882
883 case WorkspaceMode::MODE_SELECTION_RECT: {
884 wxPoint2DDouble currentPos = m_camera->ScreenToWorld(event.GetPosition());
885 double x, y, w, h;
886 if (currentPos.m_x < m_startSelRect.m_x) {
887 x = currentPos.m_x;
888 w = m_startSelRect.m_x - currentPos.m_x;
889 }
890 else {
891 x = m_startSelRect.m_x;
892 w = currentPos.m_x - m_startSelRect.m_x;
893 }
894 if (currentPos.m_y < m_startSelRect.m_y) {
895 y = currentPos.m_y;
896 h = m_startSelRect.m_y - currentPos.m_y;
897 }
898 else {
899 y = m_startSelRect.m_y;
900 h = currentPos.m_y - m_startSelRect.m_y;
901 }
902
903 m_selectionRect = wxRect2DDouble(x, y, w, h);
904 redraw = true;
905 } break;
906 }
907
908 if (redraw) {
909 Redraw();
910 }
911 m_camera->UpdateMousePosition(event.GetPosition());
912 UpdateStatusBar();
913 m_timer->Start(); // Restart the timer.
914 event.Skip();
915}

◆ OnPaint()

void Workspace::OnPaint ( wxPaintEvent &  event)
virtual

Definition at line 156 of file Workspace.cpp.

157{
158#ifdef __WXMSW__
159 const DWORD beforePaint = GetWorkspaceGDIObjects();
160#endif
161 {
162 wxBufferedPaintDC dc(m_workspacePanel);
163 dc.Clear();
164 wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
165
166 // Draw
167 DrawScene(gc);
168 delete gc;
169 }
170#ifdef __WXMSW__
171 LogWorkspaceGDIDelta("Workspace::OnPaint", beforePaint);
172#endif
173
174 event.Skip();
175}

◆ OnPopupClick()

void Workspace::OnPopupClick ( wxCommandEvent &  event)
virtual

Definition at line 1450 of file Workspace.cpp.

1451{
1452 wxWindow* dialogParent = wxGetTopLevelParent(this);
1453 if (!dialogParent) dialogParent = this;
1454 //wxWindow* dialogParent = this;
1455
1456 bool redrawHM = false;
1457
1458 wxMenu* menu = static_cast<wxMenu*>(event.GetEventObject());
1459 Element* element = static_cast<Element*>(menu->GetClientData());
1460 int eventID = event.GetId();
1461 switch (eventID) {
1462 case ID_EDIT_ELEMENT: {
1463 if (element->ShowForm(dialogParent, element, this)) {
1464 CheckSlackBusDuplication(element);
1465 UpdateTextElements();
1466 SaveCurrentState();
1467 }
1468 // Modal dialogs can steal focus; restore it to the workspace panel to keep mouse/keyboard handling consistent.
1469 if (m_workspacePanel) m_workspacePanel->SetFocus();
1470 } break;
1471 case ID_LINE_ADD_NODE: {
1472 Line* line = static_cast<Line*>(element);
1473 line->AddNode(m_camera->GetMousePosition());
1474 SaveCurrentState();
1475 Redraw();
1476 } break;
1477 case ID_LINE_REMOVE_NODE: {
1478 Line* line = static_cast<Line*>(element);
1479 line->RemoveNode(m_camera->GetMousePosition());
1480 SaveCurrentState();
1481 Redraw();
1482 } break;
1483 case ID_ROTATE_CLOCK: {
1484 element->Rotate();
1485 for (auto& iElement : m_elementList) {
1486 // Parent's element rotating...
1487 for (int i = 0; i < (int)iElement->GetParentList().size(); i++) {
1488 Element* parent = iElement->GetParentList()[i];
1489 if (parent == element) { iElement->RotateNode(parent); }
1490 }
1491 }
1492 redrawHM = true;
1493 SaveCurrentState();
1494 Redraw();
1495 } break;
1497 element->Rotate(false);
1498 for (auto& iElement : m_elementList) {
1499 // Parent's element rotating...
1500 for (int i = 0; i < (int)iElement->GetParentList().size(); i++) {
1501 Element* parent = iElement->GetParentList()[i];
1502 if (parent == element) { iElement->RotateNode(parent, false); }
1503 }
1504 }
1505 redrawHM = true;
1506 SaveCurrentState();
1507 Redraw();
1508 } break;
1509 case ID_DELETE: {
1510 //for (auto& iElement : m_elementList) {
1511 // if (element == iElement.get()) {
1512 // // Remove child/parent.
1513 // std::vector<Element*> childList = element->GetChildList();
1514 // for (auto& child : childList) {
1515 // if (child) {
1516 // child->RemoveParent(element);
1517 // element->RemoveChild(child);
1518 // }
1519 // }
1520 // std::vector<Element*> parentList = element->GetParentList();
1521 // for (auto& parent : parentList) {
1522 // if (parent) { parent->RemoveChild(element); }
1523 // }
1524 //
1525 // //for (auto itt = m_textList.begin(); itt != m_textList.end(); ++itt) {
1526 // // Text* text = *itt;
1527 // // if (text->GetElement() == element) {
1528 // // m_textList.erase(itt--);
1529 // // if (text) delete text;
1530 // // }
1531 // //}
1532 // std::erase_if(m_textList, [&](const auto& text) {
1533 // return text->GetElement() == element;
1534 // });
1535 //
1536 // std::erase_if(m_elementList, [&](const auto& delElement) {
1537 // return delElement.get() == element;
1538 // });
1539 //
1540 // //m_elementList.erase(it);
1541 // //if (element) delete element;
1542 // menu->SetClientData(nullptr);
1543 // break;
1544 // }
1545 //}
1546 //SaveCurrentState();
1547
1548 // Remove child/parent.
1549 std::vector<Element*> childList = element->GetChildList();
1550 for (auto child : childList) {
1551 if (child) {
1552 child->RemoveParent(element);
1553 element->RemoveChild(child);
1554 }
1555 }
1556
1557 std::vector<Element*> parentList = element->GetParentList();
1558 for (auto parent : parentList) {
1559 if (parent)
1560 parent->RemoveChild(element);
1561 }
1562
1563 std::erase_if(m_textList, [&](const auto& text) {
1564 return text->GetElement() == element;
1565 });
1566
1567 std::erase_if(m_elementList, [&](const auto& delElement) {
1568 return delElement.get() == element;
1569 });
1570
1571 menu->SetClientData(nullptr);
1572 SaveCurrentState();
1573 } break;
1574 default:
1575 if (InsertTextElement(eventID, element)) {
1576 UpdateTextElements();
1577 SaveCurrentState();
1578 }
1579 break;
1580 }
1581 if (redrawHM && m_hmPlane && m_showHM) {
1582 m_hmPlane->Clear();
1583 m_showHMTimer = true;
1584 m_timerHeatMap->Start();
1585 }
1586}
@ ID_LINE_REMOVE_NODE
Definition Element.h:77
@ ID_DELETE
Definition Element.h:80
@ ID_ROTATE_CLOCK
Definition Element.h:78
@ ID_EDIT_ELEMENT
Definition Element.h:75
@ ID_ROTATE_COUNTERCLOCK
Definition Element.h:79
@ ID_LINE_ADD_NODE
Definition Element.h:76
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Element.h:316

◆ OnResize()

void Workspace::OnResize ( wxSizeEvent &  event)
virtual

Definition at line 2909 of file Workspace.cpp.

2910{
2911 //m_width = static_cast<float>(m_glCanvas->GetSize().x) - 1.0f;
2912 //m_height = static_cast<float>(m_glCanvas->GetSize().y) - 1.0f;
2913 //
2914 //if (m_hmPlane && m_showHM) {
2915 // m_hmPlane->Resize(m_width, m_height);
2916 // m_showHMTimer = true;
2917 // m_timerHeatMap->Start();
2918 //}
2919 //
2920 //event.Skip();
2921 m_width = static_cast<float>(GetSize().x) - 1.0f;
2922 m_height = static_cast<float>(GetSize().y) - 1.0f;
2923
2924 if (m_hmPlane && m_showHM) {
2925 m_hmPlane->ResizeDC(m_width, m_height);
2926 m_showHMTimer = true;
2927 m_timerHeatMap->Start();
2928 }
2929
2930 event.Skip();
2931}

◆ OnRightClickDown()

void Workspace::OnRightClickDown ( wxMouseEvent &  event)
virtual

Definition at line 595 of file Workspace.cpp.

596{
597 bool redraw = false;
598 if (m_mode == WorkspaceMode::MODE_EDIT) {
599 for (auto& element : m_elementList) {
600 if (element->IsSelected()) {
601 // Show context menu.
602 if (element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
603 element->ShowPickbox(false);
604 wxMenu menu;
605 menu.SetClientData(element.get());
606 if (element->GetContextMenu(menu)) {
607 m_timer->Stop();
608 menu.Bind(wxEVT_COMMAND_MENU_SELECTED, &Workspace::OnPopupClick, this);
609 PopupMenu(&menu);
610 // Context menus can steal focus; restore it so subsequent mouse events keep working.
611 if (m_workspacePanel) m_workspacePanel->SetFocus();
612 redraw = true;
613
614 if (!menu.GetClientData()) break;
615 }
616 element->ResetPickboxes();
617 }
618 }
619 }
620 }
621 if (redraw) Redraw();
622 m_timer->Start();
623}

◆ OnScroll()

void Workspace::OnScroll ( wxMouseEvent &  event)
virtual

Definition at line 975 of file Workspace.cpp.

976{
977 if (event.GetWheelRotation() > 0)
978 m_camera->SetScale(event.GetPosition(), +0.05);
979 else
980 m_camera->SetScale(event.GetPosition(), -0.05);
981
982 if (m_hmPlane && m_showHM) {
983 m_hmPlane->Clear();
984 m_showHMTimer = true;
985 m_timerHeatMap->Start();
986 }
987
988 UpdateStatusBar();
989 Redraw();
990}

◆ OnTimer()

void Workspace::OnTimer ( wxTimerEvent &  event)
virtual

Definition at line 2556 of file Workspace.cpp.

2557{
2558 if (m_tipWindow) {
2559 m_tipWindow->Close();
2560 m_tipWindow = nullptr;
2561 }
2562 if (m_mode == WorkspaceMode::MODE_EDIT) {
2563 for (auto& element : m_elementList) {
2564 if (element->Contains(m_camera->GetMousePosition())) {
2565 wxString tipText = element->GetTipText();
2566 if (!tipText.IsEmpty()) {
2567 m_tipWindow = new wxTipWindow(this, tipText, 10000, &m_tipWindow);
2568 // Creates a very tiny bounding rect to remove the tip on any mouse movement.
2569 m_tipWindow->SetBoundingRect(wxRect(wxGetMousePosition(), wxSize(1, 1)));
2570 break;
2571 }
2572 }
2573 }
2574 }
2575
2576 m_timer->Stop();
2577}

◆ Paste()

bool Workspace::Paste ( )

Definition at line 2238 of file Workspace.cpp.

2239{
2240 if (wxTheClipboard->Open()) {
2241 ElementDataObject dataObject;
2242
2243 if (wxTheClipboard->IsSupported(dataObject.GetFormat())) {
2244 if (!wxTheClipboard->GetData(dataObject)) {
2245 wxMessageDialog dialog(this, _("It was not possible to paste from clipboard."), _("Error"),
2246 wxOK | wxCENTER | wxICON_ERROR, wxDefaultPosition);
2247 dialog.ShowModal();
2248 wxTheClipboard->Close();
2249 return false;
2250 }
2251 }
2252 else {
2253 wxTheClipboard->Close();
2254 return false;
2255 }
2256 wxTheClipboard->Close();
2257
2258 UnselectAll();
2259
2260 std::vector<Element*> pastedElements;
2261 ElementsLists* elementsLists = dataObject.GetElementsLists();
2262
2263 // Paste buses (parents).
2264 auto parentList = elementsLists->parentList;
2265 std::vector<Bus*> pastedBusList; // To set new parents;
2266 for (auto it = parentList.begin(), itEnd = parentList.end(); it != itEnd; ++it) {
2267 Element* copy = (*it)->GetCopy();
2268 if (copy) {
2269 pastedElements.push_back(copy);
2270 pastedBusList.push_back(static_cast<Bus*>(copy));
2271 m_elementList.emplace_back(static_cast<PowerElement*>(copy));
2272 }
2273 }
2274
2275 // Paste other elements.
2276 auto elementLists = elementsLists->elementList;
2277 for (auto it = elementLists.begin(), itEnd = elementLists.end(); it != itEnd; ++it) {
2278 Element* copy = (*it)->GetCopy();
2279 if (copy) {
2280 // Check if is text element
2281 if (Text* text = dynamic_cast<Text*>(copy)) {
2282 // Check if element associated with the text exists.
2283 bool elementExist = false;
2284 for (auto& element : m_elementList) {
2285 if (text->GetElement() == element.get()) {
2286 elementExist = true;
2287 break;
2288 }
2289 }
2290 if (elementExist) {
2291 pastedElements.push_back(copy);
2292 m_textList.emplace_back(text);
2293 }
2294 }
2295 else {
2296 // Change the parent if copied, otherwise remove it.
2297 for (size_t j = 0; j < copy->GetParentList().size(); j++) {
2298 Bus* currentParent = static_cast<Bus*>(copy->GetParentList()[j]);
2299 if (currentParent) {
2300 int parentID = currentParent->GetID();
2301 bool parentCopied = false;
2302 for (size_t k = 0; k < pastedBusList.size(); k++) {
2303 Bus* newParent = pastedBusList[k];
2304 if (parentID == newParent->GetID()) {
2305 parentCopied = true;
2306 copy->ReplaceParent(currentParent, newParent);
2307 break;
2308 }
2309 }
2310 if (!parentCopied) copy->RemoveParent(currentParent);
2311 }
2312 }
2313
2314 pastedElements.push_back(copy);
2315 m_elementList.emplace_back(static_cast<PowerElement*>(copy));
2316 }
2317 }
2318 }
2319
2320 // Update buses childs
2321 for (auto it = pastedBusList.begin(), itEnd = pastedBusList.end(); it != itEnd; ++it) {
2322 Bus* bus = *it;
2323 std::vector<Element*> childList = bus->GetChildList();
2324 for (auto it = childList.begin(), itEnd = childList.end(); it != itEnd; ++it) {
2325 Element* currentChild = *it;
2326 int childID = currentChild->GetID();
2327 bool childCopied = false;
2328 for (int i = 0; i < (int)pastedElements.size(); i++) {
2329 Element* newChild = pastedElements[i];
2330 if (childID == newChild->GetID()) {
2331 childCopied = true;
2332 bus->ReplaceChild(currentChild, newChild);
2333 break;
2334 }
2335 }
2336 if (!childCopied) bus->RemoveChild(currentChild);
2337 }
2338 }
2339
2340 // Move elements (and nodes) to the mouse position.
2341 // The start position it's the center of the pasted objects.
2342 wxPoint2DDouble leftUpCorner, rightDownCorner;
2343 GetElementsCorners(leftUpCorner, rightDownCorner, pastedElements);
2344 wxPoint2DDouble startPosition = (leftUpCorner + rightDownCorner) / 2.0;
2345 for (auto it = pastedElements.begin(), itEnd = pastedElements.end(); it != itEnd; ++it) {
2346 Element* element = *it;
2347 element->StartMove(startPosition);
2348 element->Move(m_camera->GetMousePosition());
2349 for (int i = 0; i < (int)element->GetParentList().size(); i++) {
2350 Element* parent = element->GetParentList()[i];
2351 element->MoveNode(parent, m_camera->GetMousePosition());
2352 }
2353 }
2354 }
2355 else {
2356 wxMessageDialog dialog(this, _("It was not possible to paste from clipboard."), _("Error"),
2357 wxOK | wxCENTER | wxICON_ERROR, wxDefaultPosition);
2358 dialog.ShowModal();
2359 return false;
2360 }
2361
2362 UpdateElementsID();
2363 m_mode = WorkspaceMode::MODE_PASTE;
2364 m_statusBar->SetStatusText(_("Click to paste."));
2365 UpdateStatusBar();
2366 Redraw();
2367 return true;
2368}
virtual Element * GetCopy()
Get a the element copy.
Definition Element.h:261
virtual int GetID() const
Get the element ID.
Definition Element.h:271
virtual void ReplaceParent(Element *oldParent, Element *newParent)
Replace a parent.
Definition Element.cpp:487
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Element.cpp:260
virtual void MoveNode(Element *parent, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
Definition Element.h:346
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Definition Element.cpp:266
virtual void ReplaceChild(Element *oldChild, Element *newChild)
Replace a child from the list.
Definition Element.cpp:503

◆ Redraw()

virtual void Workspace::Redraw ( )
inlinevirtual

Definition at line 149 of file Workspace.h.

149{ m_workspacePanel->Refresh(); }

◆ RemoveAllTextElements()

void Workspace::RemoveAllTextElements ( )

Definition at line 2012 of file Workspace.cpp.

2013{
2014 //for (auto* text : m_textList) {
2015 // if (text) delete text;
2016 //}
2017 m_textList.clear();
2018 SaveCurrentState();
2019}

◆ ResetAllVoltages()

void Workspace::ResetAllVoltages ( )

Definition at line 2099 of file Workspace.cpp.

2100{
2101 PowerFlow pf(GetElementList());
2102 pf.ResetVoltages();
2103 UpdateTextElements();
2104 Redraw();
2105}
Calculate the power flow.
Definition PowerFlow.h:36

◆ RotateSelectedElements()

void Workspace::RotateSelectedElements ( bool  clockwise = true)

Definition at line 1588 of file Workspace.cpp.

1589{
1590 bool saveCurrrentState = false;
1591 for (auto& element : m_elementList) {
1592 // Parent's element rotating...
1593 for (int i = 0; i < (int)element->GetParentList().size(); i++) {
1594 Element* parent = element->GetParentList()[i];
1595 if (parent) { // Check if parent is not null
1596 if (parent->IsSelected()) {
1597 element->RotateNode(parent, clockwise);
1598 // Update the positions used on motion action, the element will not be necessarily
1599 // moved.
1600 element->StartMove(m_camera->GetMousePosition());
1601 }
1602 }
1603 }
1604 if (element->IsSelected()) {
1605 saveCurrrentState = true;
1606 element->Rotate(clockwise);
1607 element->StartMove(m_camera->GetMousePosition());
1608 }
1609 }
1610
1611 // Rotate text element
1612 for (auto& text : m_textList) {
1613 if (text->IsSelected()) {
1614 saveCurrrentState = true;
1615 text->Rotate(clockwise);
1616 text->StartMove(m_camera->GetMousePosition());
1617 }
1618 }
1619 if (saveCurrrentState) SaveCurrentState();
1620
1621 if (m_hmPlane && m_showHM) {
1622 m_hmPlane->Clear();
1623 m_showHMTimer = true;
1624 m_timerHeatMap->Start();
1625 }
1626 Redraw();
1627}

◆ RunFault()

bool Workspace::RunFault ( )

Definition at line 2650 of file Workspace.cpp.

2651{
2652 auto simProp = m_properties->GetSimulationPropertiesData();
2653 double basePower = simProp.basePower;
2654 if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA)
2655 basePower *= 1e6;
2656 else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA)
2657 basePower *= 1e3;
2658
2659 Fault fault(GetElementList());
2660 bool result = fault.RunFaultCalculation(basePower);
2661 if (!result) {
2662 wxMessageDialog msgDialog(this, fault.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
2663 msgDialog.ShowModal();
2664 }
2665
2666 UpdateTextElements();
2667 Redraw();
2668
2669 return result;
2670}
Calculate the fault of the system and update the elements data.
Definition Fault.h:31

◆ RunFrequencyResponse()

bool Workspace::RunFrequencyResponse ( )

Definition at line 2858 of file Workspace.cpp.

2859{
2860 // Get bus list
2861 std::vector<Bus*> busList;
2862 for (auto& element : m_elementList) {
2863 if (Bus* bus = dynamic_cast<Bus*>(element.get())) { busList.push_back(bus); }
2864 }
2865
2866 auto data = m_properties->GetFreqRespData();
2867
2868 FrequencyResponseForm frForm(this, busList, data.injBusNumber, data.initFreq, data.finalFreq, data.stepFreq);
2869
2870 if (frForm.ShowModal() == wxID_OK) {
2871 data.initFreq = frForm.GetInitFreq();
2872 data.finalFreq = frForm.GetEndFreq();
2873 data.stepFreq = frForm.GetStepFreq();
2874 data.injBusNumber = frForm.GetInjBusNumber();
2875 m_properties->SetFreqRespData(data);
2876 }
2877 else
2878 return false;
2879
2880 auto simProp = m_properties->GetSimulationPropertiesData();
2881 double basePower = simProp.basePower;
2882 if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA)
2883 basePower *= 1e6;
2884 else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA)
2885 basePower *= 1e3;
2886 PowerQuality pq(GetElementList());
2887 bool result = pq.CalculateFrequencyResponse(simProp.stabilityFrequency, data.initFreq, data.finalFreq,
2888 data.stepFreq, data.injBusNumber, basePower, simProp.harmLoadConnection);
2889
2890 wxMessageDialog msgDialog(
2891 this, wxString::Format(_("Calculations done.\nDo you wish to open the frequency response graphics?")),
2892 _("Question"), wxYES_NO | wxCENTRE | wxICON_QUESTION);
2893 if (msgDialog.ShowModal() == wxID_YES) {
2894 std::vector<ElementPlotData> plotDataList;
2895 for (auto& element : m_elementList) {
2896 ElementPlotData plotData;
2897 if (element->GetPlotData(plotData, PlotStudy::FREQRESPONSE)) plotDataList.push_back(plotData);
2898 }
2899
2900 ChartView* cView = new ChartView(this, plotDataList, pq.GetFrequencies(), m_properties->GetGeneralPropertiesData().plotLib);
2901 cView->Show();
2902 }
2903
2904 UpdateTextElements();
2905 Redraw();
2906
2907 return result;
2908}
This class is responsible to manage the charts generated in the transient electromechanical studies.
Definition ChartView.h:49
Responsible for the power quality calculations.

◆ RunHarmonicDistortion()

bool Workspace::RunHarmonicDistortion ( bool  runPowerFlowBefore = true)

Definition at line 2784 of file Workspace.cpp.

2785{
2786 auto simProp = m_properties->GetSimulationPropertiesData();
2787 double basePower = simProp.basePower;
2788 if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA)
2789 basePower *= 1e6;
2790 else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA)
2791 basePower *= 1e3;
2792 if (runPowerFlowBefore) {
2793 if (!RunPowerFlow(true)) return false;
2794 }
2795
2796 bool hasEMTElement = false;
2797 for (auto& element : m_elementList) {
2798 if (auto emtElement = dynamic_cast<EMTElement*>(element.get())) {
2799 if (emtElement->IsOnline()) hasEMTElement = true;
2800 }
2801 }
2802
2803 HarmLoadConnection loadConnection = simProp.harmLoadConnection;
2804
2805 PowerQuality pq(GetElementList());
2806 bool result = pq.CalculateDistortions(basePower, loadConnection);
2807
2808 // If has EMT element, repeat the Power Flow and Harmonics calculation untion DHT converge.
2809 if (hasEMTElement && result) {
2810 wxBusyInfo info(
2811 wxBusyInfoFlags()
2812 .Parent(this)
2813 .Icon(wxIcon(Paths::GetDataPath() + "/images/ribbon/harmDist32.png", wxBITMAP_TYPE_PNG))
2814 .Title(_("<b>Calculating Harmonic Flow</b>"))
2815 .Text(_("Please wait..."))
2816 .Foreground(*wxWHITE)
2817 .Background(*wxBLACK)
2818 .Transparency(4 * wxALPHA_OPAQUE / 5)
2819 );
2820 std::vector<double> thdList;
2821 for (auto const& bus : pq.GetBusList())
2822 thdList.emplace_back(bus->GetElectricalData().thd);
2823 double error = 1e3;
2824 while (error > 1e-3) {
2825 // Run Power Flow
2826 if (!RunPowerFlow(false, false)) return false;
2827
2828 // Run Harmonic Distortion
2829 bool result = pq.CalculateDistortions(basePower, loadConnection);
2830 if (!result) break;
2831
2832 // Calculate error
2833 int i = 0;
2834 for (auto const& bus : pq.GetBusList()) {
2835 double errorBus = std::abs(bus->GetElectricalData().thd - thdList[i]);
2836 if (i == 0)
2837 error = errorBus;
2838 else if (errorBus > error)
2839 error = errorBus;
2840 thdList[i] = bus->GetElectricalData().thd;
2841 i++;
2842 }
2843 }
2844 }
2845
2846 if (!result) {
2847 wxMessageDialog msgDialog(this, pq.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
2848 msgDialog.ShowModal();
2849 }
2850 else {
2851 UpdateTextElements();
2852 Redraw();
2853 }
2854
2855 return result;
2856}
Element to connect ATP-EMTP.
Definition EMTElement.h:65

◆ RunPowerFlow()

bool Workspace::RunPowerFlow ( bool  resetVoltages = false,
bool  showBusyInfo = true 
)

Definition at line 2107 of file Workspace.cpp.

2108{
2109 auto simProp = m_properties->GetSimulationPropertiesData();
2110 double basePower = simProp.basePower;
2111 if (simProp.basePowerUnit == ElectricalUnit::UNIT_MVA)
2112 basePower *= 1e6;
2113 else if (simProp.basePowerUnit == ElectricalUnit::UNIT_kVA)
2114 basePower *= 1e3;
2115
2116 // Update EMTElements
2117 for (auto& element : m_elementList) {
2118 if (auto emtElement = dynamic_cast<EMTElement*>(element.get())) {
2119 if (emtElement->IsOnline()) {
2120 emtElement->UpdateData(m_properties, true);
2121 }
2122 }
2123 }
2124 bool result = false;
2125 wxString errorMsg = "";
2126 int numIt = 0;
2127
2128 wxStopWatch sw;
2129 {
2130 wxBusyInfo* info = nullptr;
2131 if (showBusyInfo)
2132 info = new wxBusyInfo(
2133 wxBusyInfoFlags()
2134 .Parent(this)
2135 .Icon(wxIcon(Paths::GetDataPath() + "/images/ribbon/powerFLow32.png", wxBITMAP_TYPE_PNG))
2136 .Title(_("<b>Calculating Power Flow</b>"))
2137 .Text(_("Please wait..."))
2138 .Foreground(*wxWHITE)
2139 .Background(*wxBLACK)
2140 .Transparency(4 * wxALPHA_OPAQUE / 5)
2141 );
2142 //wxBusyInfo info
2143 //(
2144 // wxBusyInfoFlags()
2145 // .Parent(this)
2146 // .Icon(wxIcon(wxT("..\\data\\images\\ribbon\\powerFLow32.png"), wxBITMAP_TYPE_PNG))
2147 // .Title(_("<b>Calculating Power Flow</b>"))
2148 // .Text(_("Please wait..."))
2149 // .Foreground(*wxWHITE)
2150 // .Background(*wxBLACK)
2151 // .Transparency(4 * wxALPHA_OPAQUE / 5)
2152 //);
2153
2154 PowerFlow pf(GetElementList());
2155 if (resetVoltages) pf.ResetVoltages();
2156
2157 switch (simProp.powerFlowMethod) {
2158 case GAUSS_SEIDEL: {
2159 result = pf.RunGaussSeidel(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
2160 simProp.initAngle, simProp.accFator);
2161 } break;
2162 case NEWTON_RAPHSON: {
2163 result = pf.RunNewtonRaphson(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
2164 simProp.initAngle, simProp.newtonInertia);
2165 } break;
2166 case GAUSS_NEWTON: {
2167 result =
2168 pf.RunGaussNewton(basePower, simProp.powerFlowMaxIterations, simProp.powerFlowTolerance,
2169 simProp.initAngle, simProp.accFator, simProp.gaussTolerance, simProp.newtonInertia);
2170 } break;
2171 }
2172
2173 errorMsg = pf.GetErrorMessage();
2174 numIt = pf.GetIterations();
2175
2176 if (showBusyInfo) delete info;
2177 }
2178 sw.Pause();
2179
2180 if (!result) {
2181 wxMessageDialog msgDialog(this, errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
2182 msgDialog.ShowModal();
2183 }
2184 else {
2185 m_statusBar->SetStatusText(
2186 wxString::Format(_("Power flow converge with %d iterations (%ld ms)"), numIt, sw.Time()));
2187 }
2188
2189 UpdateTextElements();
2190 UpdateHeatMap();
2191 Redraw();
2192
2193 return result;
2194}

◆ RunSCPower()

bool Workspace::RunSCPower ( )

Definition at line 2679 of file Workspace.cpp.

2680{
2681 Fault fault(GetElementList());
2682 bool result = fault.RunSCPowerCalcutation(100e6);
2683 if (!result) {
2684 wxMessageDialog msgDialog(this, fault.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
2685 msgDialog.ShowModal();
2686 }
2687
2688 UpdateTextElements();
2689 Redraw();
2690
2691 return result;
2692}

◆ RunStability()

bool Workspace::RunStability ( )

Definition at line 2694 of file Workspace.cpp.

2695{
2696 // Run power flow before stability.
2697 RunPowerFlow();
2698
2699 Electromechanical stability(this, GetElementList(), m_properties->GetSimulationPropertiesData());
2700 wxStopWatch sw;
2701 bool result = stability.RunStabilityCalculation();
2702#ifdef _DEBUG
2703#ifdef SHOW_DEBUG_PANEL
2704 m_debugFrame->AppendDebugMessage(stability.GetDebugMessage());
2705#endif
2706#endif // _DEBUG
2707
2708 sw.Pause();
2709 if (!result) {
2710 wxMessageDialog msgDialog(this, stability.GetErrorMessage(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
2711 msgDialog.ShowModal();
2712 }
2713 m_stabilityTimeVector.clear();
2714 m_stabilityTimeVector = stability.GetTimeVector();
2715
2716 // Run power flow after stability.
2717 RunPowerFlow();
2718
2719 wxMessageDialog msgDialog(
2720 this,
2721 wxString::Format(_("The program took %ld ms to run this system.\nDo you wish to open the stability graphics?"),
2722 sw.Time()),
2723 _("Question"), wxYES_NO | wxCENTRE | wxICON_QUESTION);
2724 if (msgDialog.ShowModal() == wxID_YES) {
2725 std::vector<ElementPlotData> plotDataList;
2726 for (auto& element : m_elementList) {
2727 ElementPlotData plotData;
2728 if (element->GetPlotData(plotData)) plotDataList.push_back(plotData);
2729 }
2730#ifdef SHOW_SIMULATION_PARAMETERS
2731 ElementPlotData plotData;
2732 plotData.SetName(_("Simulation parameters"));
2733 plotData.SetCurveType(ElementPlotData::CurveType::CT_TEST);
2734 plotData.AddData(stability.GetIterationVector(), _("Iterations number"));
2735 plotDataList.push_back(plotData);
2736#endif
2737 ChartView* cView = new ChartView(this, plotDataList, m_stabilityTimeVector, m_properties->GetGeneralPropertiesData().plotLib);
2738 cView->Show();
2739 }
2740
2741 return result;
2742}
Calculates the electromechanical transient based on disturbances (e.g. system fault).

◆ RunStaticStudies()

bool Workspace::RunStaticStudies ( )

Definition at line 2749 of file Workspace.cpp.

2750{
2751 bool pfStatus, faultStatus, scStatus, harmStatus;
2752 pfStatus = faultStatus = scStatus = harmStatus = false;
2753
2754 bool runHarmDistortion = m_properties->GetSimulationPropertiesData().harmDistortionAfterPowerFlow;
2755
2756 pfStatus = RunPowerFlow(runHarmDistortion);
2757
2758 if (m_properties->GetSimulationPropertiesData().faultAfterPowerFlow) {
2759 if (pfStatus) faultStatus = RunFault();
2760 }
2761 else {
2762 faultStatus = true;
2763 }
2764
2765 if (m_properties->GetSimulationPropertiesData().scPowerAfterPowerFlow) {
2766 if (pfStatus) scStatus = RunSCPower();
2767 }
2768 else {
2769 scStatus = true;
2770 }
2771
2772 if (runHarmDistortion) {
2773 if (pfStatus) harmStatus = RunHarmonicDistortion(false);
2774 }
2775 else {
2776 harmStatus = true;
2777 }
2778
2779 if (pfStatus && faultStatus && scStatus && harmStatus) return true;
2780
2781 return false;
2782}

◆ SaveCurrentState()

void Workspace::SaveCurrentState ( )

Definition at line 2370 of file Workspace.cpp.

2371{
2372 //return;
2373#ifdef __WXMSW__
2374 const DWORD beforeSaveState = GetWorkspaceGDIObjects();
2375#endif
2376 // Setup current state
2377 std::vector< std::shared_ptr<PowerElement> > currentStateElementList;
2378 std::vector< std::shared_ptr<Text> > currentStateTextList;
2379
2380 GetStateListsCopy(m_elementList, m_textList, currentStateElementList, currentStateTextList);
2381#ifdef __WXMSW__
2382 LogWorkspaceGDIDelta("Workspace::SaveCurrentState after copy", beforeSaveState);
2383#endif
2384
2385 // Delete all states after the current one
2386 //auto itE = m_elementListState.begin();
2387 //std::advance(itE, m_currenteState + 1);
2388 //for (; itE != m_elementListState.end(); ++itE) {
2389 // auto& elementList = *itE;
2390 // for (auto& element : elementList) delete element;
2391 // elementList.clear();
2392 //}
2393 m_elementListState.resize(m_currenteState + 1);
2394
2395 //auto itT = m_textListState.begin();
2396 //std::advance(itT, m_currenteState + 1);
2397 //for (; itT != m_textListState.end(); ++itT) {
2398 // auto& textList = *itT;
2399 // for (auto& text : textList) delete text;
2400 // textList.clear();
2401 //}
2402 m_textListState.resize(m_currenteState + 1);
2403
2404 m_currenteState++;
2405 if (m_currenteState >= m_maxStates) {
2406 m_currenteState = m_maxStates - 1;
2407 // Erase the first sate on the list
2408 //auto itE = m_elementListState.begin();
2410 //auto& elementList = *itE;
2412 //for (auto& element : elementList) delete element;
2413 //elementList.clear();
2416 //
2417 //m_elementListState.erase(itE);
2418 //m_textListState.erase(itT);
2419 m_elementListState.erase(m_elementListState.begin());
2420 m_textListState.erase(m_textListState.begin());
2421 }
2422
2423 m_elementListState.emplace_back(currentStateElementList);
2424 m_textListState.emplace_back(currentStateTextList);
2425#ifdef __WXMSW__
2426 LogWorkspaceGDIDelta(wxString::Format("Workspace::SaveCurrentState stored states=%zu elements=%zu texts=%zu",
2427 m_elementListState.size(),
2428 currentStateElementList.size(),
2429 currentStateTextList.size()),
2430 beforeSaveState);
2431#endif
2432
2433#ifdef _DEBUG
2434 wxString msg = "";
2435 wxString pointerStr;
2436 pointerStr.Printf("[%d S saved s%d] ", m_currenteState, m_elementListState.size());
2437 msg += pointerStr;
2438 for (auto& element : currentStateElementList) {
2439 pointerStr.Printf("%p ", element.get());
2440 msg += pointerStr;
2441 }
2442 msg += "\n";
2443 pointerStr.Printf("[%d S curr s%d] ", m_currenteState, m_elementListState.size());
2444 msg += pointerStr;
2445 for (auto& element : m_elementList) {
2446 pointerStr.Printf("%p ", element.get());
2447 msg += pointerStr;
2448 }
2449 msg += "\n";
2450 //m_debugFrame->AppendDebugMessage(msg);
2451#endif
2452}

◆ SetContinuousCalculationActive()

void Workspace::SetContinuousCalculationActive ( bool  value = true)
inline

Definition at line 180 of file Workspace.h.

180{ m_continuousCalc = value; }

◆ SetElementList() [1/2]

void Workspace::SetElementList ( std::vector< Element * >  elementList)

Definition at line 2603 of file Workspace.cpp.

2604{
2605 m_elementList.clear();
2606 for (auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it)
2607 m_elementList.emplace_back(static_cast<PowerElement*>(*it));
2608}

◆ SetElementList() [2/2]

void Workspace::SetElementList ( std::vector< std::shared_ptr< PowerElement > >  elementList)

Definition at line 2598 of file Workspace.cpp.

2599{
2600 m_elementList = std::move(elementList);
2601}

◆ SetJustOpened()

void Workspace::SetJustOpened ( bool  justOpened)
inline

Definition at line 147 of file Workspace.h.

147{ m_justOpened = justOpened; }

◆ SetName()

void Workspace::SetName ( wxString  name)

Definition at line 2588 of file Workspace.cpp.

2589{
2590 m_name = name;
2591#ifdef _DEBUG
2592#ifdef SHOW_DEBUG_PANEL
2593 m_debugFrame->SetTitle(_("Debug window: ") + m_name);
2594#endif
2595#endif
2596}

◆ SetNextState()

void Workspace::SetNextState ( )

Definition at line 2454 of file Workspace.cpp.

2455{
2456 m_currenteState++;
2457 if (m_currenteState >= 0 &&
2458 static_cast<size_t>(m_currenteState) < m_elementListState.size() &&
2459 static_cast<size_t>(m_currenteState) < m_textListState.size()) {
2460 //m_elementList = m_elementListState[m_currenteState];
2461 //m_textList = m_textListState[m_currenteState];
2462 GetStateListsCopy(m_elementListState[m_currenteState], m_textListState[m_currenteState], m_elementList, m_textList);
2463
2464#ifdef _DEBUG
2465#ifdef SHOW_DEBUG_PANEL
2466 wxString msg = "";
2467 wxString pointerStr;
2468 pointerStr.Printf("[%d N curr s%d] ", m_currenteState, m_elementListState.size());
2469 msg += pointerStr;
2470 for (Element* element : m_elementList) {
2471 pointerStr.Printf("%p ", element);
2472 msg += pointerStr;
2473 }
2474 msg += "\n";
2475 //m_debugFrame->AppendDebugMessage(msg);
2476#endif
2477#endif
2478
2479 UpdateTextElements();
2480 Redraw();
2481 }
2482 else {
2483 m_currenteState--;
2484 }
2485}

◆ SetPreviousState()

void Workspace::SetPreviousState ( )

Definition at line 2487 of file Workspace.cpp.

2488{
2489 m_currenteState--;
2490 if (m_currenteState >= 0) {
2491 //m_elementList = m_elementListState[m_currenteState];
2492 //m_textList = m_textListState[m_currenteState];
2493 GetStateListsCopy(m_elementListState[m_currenteState], m_textListState[m_currenteState], m_elementList, m_textList);
2494
2495#ifdef _DEBUG
2496#ifdef SHOW_DEBUG_PANEL
2497 wxString msg = "";
2498 wxString pointerStr;
2499 pointerStr.Printf("[%d P curr s%d] ", m_currenteState, m_elementListState.size());
2500 msg += pointerStr;
2501 for (Element* element : m_elementListState[m_currenteState]) {
2502 pointerStr.Printf("%p ", element);
2503 msg += pointerStr;
2504 }
2505 msg += "\n";
2506 pointerStr.Printf("[%d P list s%d] ", m_currenteState, m_elementListState.size());
2507 msg += pointerStr;
2508 for (Element* element : m_elementList) {
2509 pointerStr.Printf("%p ", element);
2510 msg += pointerStr;
2511 }
2512 msg += "\n";
2513 //m_debugFrame->AppendDebugMessage(msg);
2514#endif
2515#endif
2516
2517 UpdateTextElements();
2518 Redraw();
2519 }
2520 else {
2521 m_currenteState++;
2522 }
2523}

◆ SetSavedPath()

void Workspace::SetSavedPath ( wxFileName  savedPath)
inline

Definition at line 146 of file Workspace.h.

146{ m_savedPath = savedPath; }

◆ SetStatusBarText()

void Workspace::SetStatusBarText ( wxString  text)
inline

Definition at line 144 of file Workspace.h.

144{ m_statusBar->SetStatusText(text); }

◆ SetTextList()

void Workspace::SetTextList ( const std::vector< std::shared_ptr< Text > > &  textList)

Definition at line 2579 of file Workspace.cpp.

2580{
2581 //m_textList.clear();
2582 //for (auto it = textList.begin(), itEnd = textList.end(); it != itEnd; ++it) m_textList.push_back(*it);
2583 m_textList = std::move(textList);
2584
2585 UpdateTextElements();
2586}

◆ SetWorkspaceMode()

void Workspace::SetWorkspaceMode ( WorkspaceMode  mode)
inline

Definition at line 145 of file Workspace.h.

145{ m_mode = mode; }

◆ UnselectAll()

void Workspace::UnselectAll ( )

Definition at line 2525 of file Workspace.cpp.

2526{
2527 for (auto& element : m_elementList) {
2528 element->SetSelected(false);
2529 }
2530 for (auto& text : m_textList) {
2531 text->SetSelected(false);
2532 }
2533}

◆ UpdateElementsID()

void Workspace::UpdateElementsID ( )

Definition at line 2544 of file Workspace.cpp.

2545{
2546 int id = 0;
2547 for (auto& element : m_elementList) {
2548 element->SetID(id);
2549 id++;
2550 }
2551 for (auto& text : m_textList) {
2552 text->SetID(id);
2553 id++;
2554 }
2555}

◆ UpdateHeatMap()

void Workspace::UpdateHeatMap ( )

Definition at line 1389 of file Workspace.cpp.

1390{
1391 if (m_hmPlane && m_showHM) {
1392 m_hmPlane->Clear();
1393
1394 wxRect2DDouble screenRect(-100, -100, m_width + 200.0, m_height + 200.0);
1395
1396 // Get new voltage range
1397 std::vector<Bus*> busList;
1398 float minVoltage, maxVoltage;
1399 if (m_hmAutomaticLabel) {
1400 minVoltage = 10.0f;
1401 maxVoltage = 0.0f;
1402 }
1403 else {
1404 minVoltage = m_hmPlane->GetMinLimit();
1405 maxVoltage = m_hmPlane->GetMaxLimit();
1406 }
1407
1408 for (auto& element : m_elementList) {
1409 if (Bus* bus = dynamic_cast<Bus*>(element.get())) {
1410 if (m_hmAutomaticLabel) {
1411 const float voltage = std::abs(bus->GetElectricalData().voltage);
1412 if (minVoltage > voltage) minVoltage = voltage;
1413 if (maxVoltage < voltage) maxVoltage = voltage;
1414 }
1415 busList.push_back(bus);
1416 }
1417 }
1418 if (m_hmAutomaticLabel) {
1419 m_hmPlane->SetLabelLimits(minVoltage, maxVoltage);
1420 }
1421
1422 for (Bus* bus : busList) {
1423 const float voltage = std::abs(bus->GetElectricalData().voltage);
1424 float depth = 2.0f * (voltage - (maxVoltage + minVoltage) / 2.0f) / (maxVoltage - minVoltage);
1425 if (depth < -1.0) depth = -1.0;
1426 if (depth > 1.0) depth = 1.0;
1427
1428 wxRect2DDouble rect = bus->GetRect();
1429 rect = wxRect2DDouble(
1430 (rect.m_x - 100.0f) * m_camera->GetScale() + m_camera->GetTranslation().m_x * m_camera->GetScale(),
1431 (rect.m_y - 50.0f) * m_camera->GetScale() + m_camera->GetTranslation().m_y * m_camera->GetScale(),
1432 (rect.m_width + 200.0f) * m_camera->GetScale(),
1433 (rect.m_height + 100.0f) * m_camera->GetScale());
1434
1435 if (screenRect.Contains(rect))
1436 m_hmPlane->SetRectSlope(rect, M_PI * static_cast<float>(bus->GetAngle()) / 180.0f, depth);
1437 }
1438
1439 //m_hmPlane->UpdateCoords();
1440
1441 //int iterations = std::lround(3.3 * std::pow(m_camera->GetScale(), 0.62));
1442 int iterations = std::lround(10 * std::pow(m_camera->GetScale(), 2));
1443 //int iterations = std::lround(1 * std::pow(m_camera->GetScale(), 0.2));
1444 //int iterations = 1;
1445 if (iterations < 1) iterations = 1;
1446 m_hmPlane->SmoothPlane(iterations);
1447 }
1448}

◆ UpdateStatusBar()

void Workspace::UpdateStatusBar ( )
protected

Definition at line 1273 of file Workspace.cpp.

1274{
1275 switch (m_mode) {
1276 case WorkspaceMode::MODE_DRAG: {
1277 m_statusBar->SetStatusText(_("MODE: DRAG"), 1);
1278 } break;
1279
1280 case WorkspaceMode::MODE_PASTE:
1281 case WorkspaceMode::MODE_DRAG_PASTE: {
1282 m_statusBar->SetStatusText(_("MODE: PASTE"), 1);
1283 } break;
1284
1285 case WorkspaceMode::MODE_INSERT:
1286 case WorkspaceMode::MODE_INSERT_TEXT:
1287 case WorkspaceMode::MODE_DRAG_INSERT:
1288 case WorkspaceMode::MODE_DRAG_INSERT_TEXT: {
1289 m_statusBar->SetStatusText(_("MODE: INSERT"), 1);
1290 } break;
1291
1292 case WorkspaceMode::MODE_MOVE_ELEMENT:
1293 case WorkspaceMode::MODE_MOVE_PICKBOX:
1294 case WorkspaceMode::MODE_MOVE_NODE:
1295 case WorkspaceMode::MODE_SELECTION_RECT:
1296 case WorkspaceMode::MODE_EDIT: {
1297 if (m_oldStatusMode != m_mode)
1298 m_statusBar->SetStatusText(wxT(""));
1299 m_statusBar->SetStatusText(_("MODE: EDIT"), 1);
1300 } break;
1301 }
1302
1303 m_statusBar->SetStatusText(wxString::Format(_("ZOOM: %d%%"), (int)(m_camera->GetScale() * 100.0)), 2);
1304 m_statusBar->SetStatusText(
1305 wxString::Format(wxT("X: %.1f Y: %.1f"), m_camera->GetMousePosition().m_x, m_camera->GetMousePosition().m_y),
1306 3);
1307 m_oldStatusMode = m_mode;
1308}

◆ UpdateTextElements()

bool Workspace::UpdateTextElements ( )

Definition at line 2196 of file Workspace.cpp.

2197{
2198 bool isTexturesOK = true;
2199 double basePower = m_properties->GetSimulationPropertiesData().basePower;
2200 if (m_properties->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_kVA)
2201 basePower *= 1e3;
2202 else if (m_properties->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_MVA)
2203 basePower *= 1e6;
2204 for (auto& text : m_textList) {
2205 text->SetFontName(m_properties->GetGeneralPropertiesData().labelFont);
2206 text->SetFontSize(m_properties->GetGeneralPropertiesData().labelFontSize);
2207 text->UpdateText(basePower);
2208 //if (!text->IsGLTextOK()) isTexturesOK = false;
2209 }
2210 return isTexturesOK;
2211}

◆ ValidateBusesVoltages()

void Workspace::ValidateBusesVoltages ( Element initialBus)

Definition at line 2051 of file Workspace.cpp.

2052{
2053 double nominalVoltage = static_cast<Bus*>(initialBus)->GetElectricalData().nominalVoltage;
2054 ElectricalUnit nominalVoltageUnit = static_cast<Bus*>(initialBus)->GetElectricalData().nominalVoltageUnit;
2055
2056 for (auto it = m_elementList.begin(); it != m_elementList.end(); it++) {
2057 Element* child = it->get();
2058
2059 if (auto line = dynamic_cast<Line*>(child)) {
2060 if (line->GetParentList()[0] && line->GetParentList()[1]) {
2061 BusElectricalData data1 = static_cast<Bus*>(line->GetParentList()[0])->GetElectricalData();
2062 BusElectricalData data2 = static_cast<Bus*>(line->GetParentList()[1])->GetElectricalData();
2063
2064 if (data1.nominalVoltage != data2.nominalVoltage ||
2065 data1.nominalVoltageUnit != data2.nominalVoltageUnit) {
2066 data1.nominalVoltage = nominalVoltage;
2067 data2.nominalVoltage = nominalVoltage;
2068 data1.nominalVoltageUnit = nominalVoltageUnit;
2069 data2.nominalVoltageUnit = nominalVoltageUnit;
2070
2071 static_cast<Bus*>(line->GetParentList()[0])->SetElectricalData(data1);
2072 static_cast<Bus*>(line->GetParentList()[1])->SetElectricalData(data2);
2073
2074 it = m_elementList.begin(); // Restart search.
2075 }
2076 }
2077 }
2078 }
2079
2080 // ValidateElementsVoltages();
2081}
ElectricalUnit
Electrical units.

◆ ValidateElementsVoltages()

void Workspace::ValidateElementsVoltages ( )

Definition at line 2083 of file Workspace.cpp.

2084{
2085 for (auto& child : m_elementList) {
2086 std::vector<double> nominalVoltage;
2087 std::vector<ElectricalUnit> nominalVoltageUnit;
2088 for (int i = 0; i < (int)child->GetParentList().size(); i++) {
2089 Bus* parent = static_cast<Bus*>(child->GetParentList()[i]);
2090 if (parent) {
2091 nominalVoltage.push_back(parent->GetElectricalData().nominalVoltage);
2092 nominalVoltageUnit.push_back(parent->GetElectricalData().nominalVoltageUnit);
2093 }
2094 }
2095 child->SetNominalVoltage(nominalVoltage, nominalVoltageUnit);
2096 }
2097}
virtual void SetNominalVoltage(std::vector< double > nominalVoltage, std::vector< ElectricalUnit > nominalVoltageUnit)
Set nominal voltage of the element.

Member Data Documentation

◆ m_auiNotebook

wxAuiNotebook* Workspace::m_auiNotebook = nullptr
protected

Definition at line 222 of file Workspace.h.

◆ m_camera

Camera* Workspace::m_camera = nullptr
protected

Definition at line 223 of file Workspace.h.

◆ m_continuousCalc

bool Workspace::m_continuousCalc = false
protected

Definition at line 253 of file Workspace.h.

◆ m_currenteState

int Workspace::m_currenteState = -1
protected

Definition at line 241 of file Workspace.h.

◆ m_disconnectedElement

bool Workspace::m_disconnectedElement = false
protected

Definition at line 254 of file Workspace.h.

◆ m_elementList

std::vector< std::shared_ptr<PowerElement> > Workspace::m_elementList
protected

Definition at line 231 of file Workspace.h.

◆ m_elementListState

std::vector< std::vector< std::shared_ptr<PowerElement> > > Workspace::m_elementListState
protected

Definition at line 238 of file Workspace.h.

◆ m_elementNumber

int Workspace::m_elementNumber[NUM_ELEMENTS]
protected

Definition at line 232 of file Workspace.h.

◆ m_height

float Workspace::m_height = 0.0
protected

Definition at line 258 of file Workspace.h.

◆ m_hmAutomaticLabel

bool Workspace::m_hmAutomaticLabel = false
protected

Definition at line 267 of file Workspace.h.

◆ m_hmPlane

HMPlane* Workspace::m_hmPlane = nullptr
protected

Definition at line 261 of file Workspace.h.

◆ m_justOpened

bool Workspace::m_justOpened = false
protected

Definition at line 255 of file Workspace.h.

◆ m_maxStates

int Workspace::m_maxStates = 100
protected

Definition at line 242 of file Workspace.h.

◆ m_mode

WorkspaceMode Workspace::m_mode = WorkspaceMode::MODE_EDIT
protected

Definition at line 227 of file Workspace.h.

◆ m_name

wxString Workspace::m_name
protected

Definition at line 225 of file Workspace.h.

◆ m_oldStatusMode

WorkspaceMode Workspace::m_oldStatusMode = WorkspaceMode::MODE_EDIT
protected

Definition at line 228 of file Workspace.h.

◆ m_properties

PropertiesData* Workspace::m_properties = nullptr
protected

Definition at line 249 of file Workspace.h.

◆ m_savedPath

wxFileName Workspace::m_savedPath
protected

Definition at line 244 of file Workspace.h.

◆ m_selectionRect

wxRect2DDouble Workspace::m_selectionRect
protected

Definition at line 246 of file Workspace.h.

◆ m_showHM

bool Workspace::m_showHM = false
protected

Definition at line 265 of file Workspace.h.

◆ m_showHMTimer

bool Workspace::m_showHMTimer = false
protected

Definition at line 266 of file Workspace.h.

◆ m_stabilityTimeVector

std::vector<double> Workspace::m_stabilityTimeVector
protected

Definition at line 251 of file Workspace.h.

◆ m_startSelRect

wxPoint2DDouble Workspace::m_startSelRect
protected

Definition at line 247 of file Workspace.h.

◆ m_statusBar

wxStatusBar* Workspace::m_statusBar = nullptr
protected

Definition at line 221 of file Workspace.h.

◆ m_textList

std::vector< std::shared_ptr<Text> > Workspace::m_textList
protected

Definition at line 235 of file Workspace.h.

◆ m_textListState

std::vector< std::vector< std::shared_ptr<Text> > > Workspace::m_textListState
protected

Definition at line 240 of file Workspace.h.

◆ m_tipWindow

wxTipWindow* Workspace::m_tipWindow = nullptr
protected

Definition at line 224 of file Workspace.h.

◆ m_width

float Workspace::m_width = 0.0
protected

Definition at line 257 of file Workspace.h.


The documentation for this class was generated from the following files: