Power System Platform  2026w23a-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)
 
void SetColourTheme ()
 
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
 
ControlEditorManagerGetControlEditorManager () const
 
ChartWindowManagerGetChartWindowManager () 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::Ref m_tipWindow
 
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
 
std::unique_ptr< ControlEditorManagerm_CEMngr
 
std::unique_ptr< ChartWindowManagerm_CWMngr
 

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 104 of file Workspace.h.

Member Enumeration Documentation

◆ WorkspaceMode

enum class Workspace::WorkspaceMode : int
strong

Definition at line 107 of file Workspace.h.

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

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 SetColourTheme();
93 m_workspacePanel->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 SetColourTheme();
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 m_CEMngr = std::make_unique<ControlEditorManager>(this);
134 m_CWMngr = std::make_unique<ChartWindowManager>(this);
135
136 SaveCurrentState();
137}
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 139 of file Workspace.cpp.

140{
141 if (m_hmPlane) delete m_hmPlane;
142 if (m_camera) delete m_camera;
143 if (m_properties) delete m_properties;
144}

Member Function Documentation

◆ CheckSlackBusDuplication()

void Workspace::CheckSlackBusDuplication ( Element newSlackBus)

Definition at line 2018 of file Workspace.cpp.

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

◆ CopySelection()

void Workspace::CopySelection ( )

Definition at line 2210 of file Workspace.cpp.

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

◆ CopyToClipboard()

void Workspace::CopyToClipboard ( )

Definition at line 284 of file Workspace.cpp.

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

◆ DeleteSelectedElements()

void Workspace::DeleteSelectedElements ( )

Definition at line 1626 of file Workspace.cpp.

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

◆ DrawScene() [1/2]

void Workspace::DrawScene ( wxDC &  dc)
protected

Definition at line 251 of file Workspace.cpp.

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

◆ DrawScene() [2/2]

void Workspace::DrawScene ( wxGraphicsContext *  gc)
protected

Definition at line 173 of file Workspace.cpp.

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

◆ EnableAutoHeatMapLabel()

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

Definition at line 164 of file Workspace.h.

164{ m_hmAutomaticLabel = enable; }

◆ EnableHeatMap()

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

Definition at line 2532 of file Workspace.cpp.

2533{
2534 m_showHM = enable;
2535 if (m_showHM) {
2536 UpdateHeatMap();
2537 }
2538 Redraw();
2539}

◆ ExportAsSVG()

void Workspace::ExportAsSVG ( wxString  path)

Definition at line 312 of file Workspace.cpp.

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

◆ FindTextElement()

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

Definition at line 2000 of file Workspace.cpp.

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

◆ Fit()

void Workspace::Fit ( )

Definition at line 1713 of file Workspace.cpp.

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

◆ GetAllElements()

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

Definition at line 2638 of file Workspace.cpp.

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

◆ GetCamera()

Camera * Workspace::GetCamera ( ) const
inline

Definition at line 133 of file Workspace.h.

133{ return m_camera; }

◆ GetChartWindowManager()

ChartWindowManager & Workspace::GetChartWindowManager ( ) const
inline

Definition at line 167 of file Workspace.h.

167{ return *m_CWMngr; }

◆ GetControlEditorManager()

ControlEditorManager & Workspace::GetControlEditorManager ( ) const
inline

Definition at line 166 of file Workspace.h.

166{ return *m_CEMngr; }

◆ GetElementList()

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

Definition at line 2670 of file Workspace.cpp.

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

◆ GetElementNumber()

int Workspace::GetElementNumber ( ElementID  elementID)
inline

Definition at line 182 of file Workspace.h.

182{ return m_elementNumber[elementID]; }

◆ GetElementNumberFromList()

int Workspace::GetElementNumberFromList ( Element element)
protected

Definition at line 1307 of file Workspace.cpp.

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

◆ GetElementsCorners()

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

Definition at line 1692 of file Workspace.cpp.

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

◆ GetElementSharedList()

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

Definition at line 129 of file Workspace.h.

129{ return m_elementList; }

◆ GetHeatMap()

HMPlane * Workspace::GetHeatMap ( ) const
inline

Definition at line 163 of file Workspace.h.

163{ return m_hmPlane; }

◆ GetName()

wxString Workspace::GetName ( ) const
inline

Definition at line 127 of file Workspace.h.

127{ return m_name; }

◆ GetProperties()

PropertiesData * Workspace::GetProperties ( ) const
inline

Definition at line 184 of file Workspace.h.

184{ return m_properties; }

◆ GetSavedPath()

wxFileName Workspace::GetSavedPath ( ) const
inline

Definition at line 142 of file Workspace.h.

142{ return m_savedPath; }

◆ GetStabilityTimeVector()

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

Definition at line 185 of file Workspace.h.

185{ 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 1319 of file Workspace.cpp.

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

◆ GetTextList()

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

Definition at line 130 of file Workspace.h.

130{ return m_textList; }

◆ GetWorkspaceMode()

WorkspaceMode Workspace::GetWorkspaceMode ( ) const
inline

Definition at line 132 of file Workspace.h.

132{ return m_mode; }

◆ IncrementElementNumber()

void Workspace::IncrementElementNumber ( ElementID  elementID)
inline

Definition at line 183 of file Workspace.h.

183{ m_elementNumber[elementID]++; }

◆ InsertTextElement()

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

Definition at line 1746 of file Workspace.cpp.

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

◆ IsContinuousCalculationActive()

bool Workspace::IsContinuousCalculationActive ( ) const
inline

Definition at line 186 of file Workspace.h.

186{ return m_continuousCalc; }

◆ IsHeatMapAutoLabelEnable()

bool Workspace::IsHeatMapAutoLabelEnable ( ) const
inline

Definition at line 165 of file Workspace.h.

165{ return m_hmAutomaticLabel; }

◆ IsHeatMapEnable()

bool Workspace::IsHeatMapEnable ( ) const
inline

Definition at line 162 of file Workspace.h.

162{ return m_showHM; }

◆ OnHeatMapTime()

void Workspace::OnHeatMapTime ( wxTimerEvent &  event)
protectedvirtual

Definition at line 2920 of file Workspace.cpp.

2921{
2922 if (m_showHMTimer) {
2923 UpdateHeatMap();
2924 Redraw();
2925 m_showHMTimer = false;
2926 }
2927}

◆ OnIdle()

void Workspace::OnIdle ( wxIdleEvent &  event)
virtual

Definition at line 2608 of file Workspace.cpp.

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

◆ OnKeyDown()

void Workspace::OnKeyDown ( wxKeyEvent &  event)
virtual

Definition at line 989 of file Workspace.cpp.

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

◆ OnLeftClickDown()

void Workspace::OnLeftClickDown ( wxMouseEvent &  event)
virtual

Definition at line 323 of file Workspace.cpp.

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

◆ OnLeftClickUp()

void Workspace::OnLeftClickUp ( wxMouseEvent &  event)
virtual

Definition at line 622 of file Workspace.cpp.

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

◆ OnLeftDoubleClick()

void Workspace::OnLeftDoubleClick ( wxMouseEvent &  event)
virtual

Definition at line 502 of file Workspace.cpp.

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

◆ OnMiddleDoubleClick()

void Workspace::OnMiddleDoubleClick ( wxMouseEvent &  event)
virtual

Definition at line 2741 of file Workspace.cpp.

2742{
2743 Fit();
2744 event.Skip();
2745}

◆ OnMiddleDown()

void Workspace::OnMiddleDown ( wxMouseEvent &  event)
virtual

Definition at line 914 of file Workspace.cpp.

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

◆ OnMiddleUp()

void Workspace::OnMiddleUp ( wxMouseEvent &  event)
virtual

Definition at line 941 of file Workspace.cpp.

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

◆ OnMouseMotion()

void Workspace::OnMouseMotion ( wxMouseEvent &  event)
virtual

Definition at line 761 of file Workspace.cpp.

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

◆ OnPaint()

void Workspace::OnPaint ( wxPaintEvent &  event)
virtual

Definition at line 152 of file Workspace.cpp.

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

◆ OnPopupClick()

void Workspace::OnPopupClick ( wxCommandEvent &  event)
virtual

Definition at line 1447 of file Workspace.cpp.

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

◆ OnResize()

void Workspace::OnResize ( wxSizeEvent &  event)
virtual

Definition at line 2907 of file Workspace.cpp.

2908{
2909 m_width = static_cast<float>(GetSize().x) - 1.0f;
2910 m_height = static_cast<float>(GetSize().y) - 1.0f;
2911
2912 if (m_hmPlane && m_showHM) {
2913 m_hmPlane->ResizeDC(m_width, m_height);
2914 m_showHMTimer = true;
2915 m_timerHeatMap->Start();
2916 }
2917
2918 event.Skip();
2919}

◆ OnRightClickDown()

void Workspace::OnRightClickDown ( wxMouseEvent &  event)
virtual

Definition at line 592 of file Workspace.cpp.

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

◆ OnScroll()

void Workspace::OnScroll ( wxMouseEvent &  event)
virtual

Definition at line 972 of file Workspace.cpp.

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

◆ OnTimer()

void Workspace::OnTimer ( wxTimerEvent &  event)
virtual

Definition at line 2553 of file Workspace.cpp.

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

◆ Paste()

bool Workspace::Paste ( )

Definition at line 2235 of file Workspace.cpp.

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

◆ Redraw()

virtual void Workspace::Redraw ( )
inlinevirtual

Definition at line 152 of file Workspace.h.

152{ m_workspacePanel->Refresh(); }

◆ RemoveAllTextElements()

void Workspace::RemoveAllTextElements ( )

Definition at line 2009 of file Workspace.cpp.

2010{
2011 //for (auto* text : m_textList) {
2012 // if (text) delete text;
2013 //}
2014 m_textList.clear();
2015 SaveCurrentState();
2016}

◆ ResetAllVoltages()

void Workspace::ResetAllVoltages ( )

Definition at line 2096 of file Workspace.cpp.

2097{
2098 PowerFlow pf(GetElementList());
2099 pf.ResetVoltages();
2100 UpdateTextElements();
2101 Redraw();
2102}
Calculate the power flow.
Definition PowerFlow.h:36

◆ RotateSelectedElements()

void Workspace::RotateSelectedElements ( bool  clockwise = true)

Definition at line 1585 of file Workspace.cpp.

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

◆ RunFault()

bool Workspace::RunFault ( )

Definition at line 2648 of file Workspace.cpp.

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

◆ RunFrequencyResponse()

bool Workspace::RunFrequencyResponse ( )

Definition at line 2856 of file Workspace.cpp.

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

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

◆ RunPowerFlow()

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

Definition at line 2104 of file Workspace.cpp.

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

◆ RunSCPower()

bool Workspace::RunSCPower ( )

Definition at line 2677 of file Workspace.cpp.

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

◆ RunStability()

bool Workspace::RunStability ( )

Definition at line 2692 of file Workspace.cpp.

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

◆ RunStaticStudies()

bool Workspace::RunStaticStudies ( )

Definition at line 2747 of file Workspace.cpp.

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

◆ SaveCurrentState()

void Workspace::SaveCurrentState ( )

Definition at line 2367 of file Workspace.cpp.

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

◆ SetColourTheme()

void Workspace::SetColourTheme ( )

Definition at line 146 of file Workspace.cpp.

147{
148 m_properties->SetGUIColourTheme();
149 m_workspacePanel->SetBackgroundColour(m_properties->GetGUIColour()->background);
150}

◆ SetContinuousCalculationActive()

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

Definition at line 187 of file Workspace.h.

187{ m_continuousCalc = value; }

◆ SetElementList() [1/2]

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

Definition at line 2601 of file Workspace.cpp.

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

◆ SetElementList() [2/2]

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

Definition at line 2596 of file Workspace.cpp.

2597{
2598 m_elementList = std::move(elementList);
2599}

◆ SetJustOpened()

void Workspace::SetJustOpened ( bool  justOpened)
inline

Definition at line 150 of file Workspace.h.

150{ m_justOpened = justOpened; }

◆ SetName()

void Workspace::SetName ( wxString  name)

Definition at line 2586 of file Workspace.cpp.

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

◆ SetNextState()

void Workspace::SetNextState ( )

Definition at line 2451 of file Workspace.cpp.

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

◆ SetPreviousState()

void Workspace::SetPreviousState ( )

Definition at line 2484 of file Workspace.cpp.

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

◆ SetSavedPath()

void Workspace::SetSavedPath ( wxFileName  savedPath)
inline

Definition at line 149 of file Workspace.h.

149{ m_savedPath = savedPath; }

◆ SetStatusBarText()

void Workspace::SetStatusBarText ( wxString  text)
inline

Definition at line 147 of file Workspace.h.

147{ m_statusBar->SetStatusText(text); }

◆ SetTextList()

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

Definition at line 2577 of file Workspace.cpp.

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

◆ SetWorkspaceMode()

void Workspace::SetWorkspaceMode ( WorkspaceMode  mode)
inline

Definition at line 148 of file Workspace.h.

148{ m_mode = mode; }

◆ UnselectAll()

void Workspace::UnselectAll ( )

Definition at line 2522 of file Workspace.cpp.

2523{
2524 for (auto& element : m_elementList) {
2525 element->SetSelected(false);
2526 }
2527 for (auto& text : m_textList) {
2528 text->SetSelected(false);
2529 }
2530}

◆ UpdateElementsID()

void Workspace::UpdateElementsID ( )

Definition at line 2541 of file Workspace.cpp.

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

◆ UpdateHeatMap()

void Workspace::UpdateHeatMap ( )

Definition at line 1386 of file Workspace.cpp.

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

◆ UpdateStatusBar()

void Workspace::UpdateStatusBar ( )
protected

Definition at line 1270 of file Workspace.cpp.

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

◆ UpdateTextElements()

bool Workspace::UpdateTextElements ( )

Definition at line 2193 of file Workspace.cpp.

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

◆ ValidateBusesVoltages()

void Workspace::ValidateBusesVoltages ( Element initialBus)

Definition at line 2048 of file Workspace.cpp.

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

◆ ValidateElementsVoltages()

void Workspace::ValidateElementsVoltages ( )

Definition at line 2080 of file Workspace.cpp.

2081{
2082 for (auto& child : m_elementList) {
2083 std::vector<double> nominalVoltage;
2084 std::vector<ElectricalUnit> nominalVoltageUnit;
2085 for (int i = 0; i < (int)child->GetParentList().size(); i++) {
2086 Bus* parent = static_cast<Bus*>(child->GetParentList()[i]);
2087 if (parent) {
2088 nominalVoltage.push_back(parent->GetElectricalData().nominalVoltage);
2089 nominalVoltageUnit.push_back(parent->GetElectricalData().nominalVoltageUnit);
2090 }
2091 }
2092 child->SetNominalVoltage(nominalVoltage, nominalVoltageUnit);
2093 }
2094}
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 229 of file Workspace.h.

◆ m_camera

Camera* Workspace::m_camera = nullptr
protected

Definition at line 230 of file Workspace.h.

◆ m_CEMngr

std::unique_ptr<ControlEditorManager> Workspace::m_CEMngr
protected

Definition at line 276 of file Workspace.h.

◆ m_continuousCalc

bool Workspace::m_continuousCalc = false
protected

Definition at line 260 of file Workspace.h.

◆ m_currenteState

int Workspace::m_currenteState = -1
protected

Definition at line 248 of file Workspace.h.

◆ m_CWMngr

std::unique_ptr<ChartWindowManager> Workspace::m_CWMngr
protected

Definition at line 277 of file Workspace.h.

◆ m_disconnectedElement

bool Workspace::m_disconnectedElement = false
protected

Definition at line 261 of file Workspace.h.

◆ m_elementList

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

Definition at line 238 of file Workspace.h.

◆ m_elementListState

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

Definition at line 245 of file Workspace.h.

◆ m_elementNumber

int Workspace::m_elementNumber[NUM_ELEMENTS]
protected

Definition at line 239 of file Workspace.h.

◆ m_height

float Workspace::m_height = 0.0
protected

Definition at line 265 of file Workspace.h.

◆ m_hmAutomaticLabel

bool Workspace::m_hmAutomaticLabel = false
protected

Definition at line 274 of file Workspace.h.

◆ m_hmPlane

HMPlane* Workspace::m_hmPlane = nullptr
protected

Definition at line 268 of file Workspace.h.

◆ m_justOpened

bool Workspace::m_justOpened = false
protected

Definition at line 262 of file Workspace.h.

◆ m_maxStates

int Workspace::m_maxStates = 100
protected

Definition at line 249 of file Workspace.h.

◆ m_mode

WorkspaceMode Workspace::m_mode = WorkspaceMode::MODE_EDIT
protected

Definition at line 234 of file Workspace.h.

◆ m_name

wxString Workspace::m_name
protected

Definition at line 232 of file Workspace.h.

◆ m_oldStatusMode

WorkspaceMode Workspace::m_oldStatusMode = WorkspaceMode::MODE_EDIT
protected

Definition at line 235 of file Workspace.h.

◆ m_properties

PropertiesData* Workspace::m_properties = nullptr
protected

Definition at line 256 of file Workspace.h.

◆ m_savedPath

wxFileName Workspace::m_savedPath
protected

Definition at line 251 of file Workspace.h.

◆ m_selectionRect

wxRect2DDouble Workspace::m_selectionRect
protected

Definition at line 253 of file Workspace.h.

◆ m_showHM

bool Workspace::m_showHM = false
protected

Definition at line 272 of file Workspace.h.

◆ m_showHMTimer

bool Workspace::m_showHMTimer = false
protected

Definition at line 273 of file Workspace.h.

◆ m_stabilityTimeVector

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

Definition at line 258 of file Workspace.h.

◆ m_startSelRect

wxPoint2DDouble Workspace::m_startSelRect
protected

Definition at line 254 of file Workspace.h.

◆ m_statusBar

wxStatusBar* Workspace::m_statusBar = nullptr
protected

Definition at line 228 of file Workspace.h.

◆ m_textList

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

Definition at line 242 of file Workspace.h.

◆ m_textListState

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

Definition at line 247 of file Workspace.h.

◆ m_tipWindow

wxTipWindow::Ref Workspace::m_tipWindow
protected

Definition at line 231 of file Workspace.h.

◆ m_width

float Workspace::m_width = 0.0
protected

Definition at line 264 of file Workspace.h.


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