Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
Bus.cpp
1/*
2 * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "Bus.h"
19#ifdef USING_WX_3_0_X
20#include "utils/DegreesAndRadians.h"
21#endif
22
23Bus::Bus() : PowerElement() { m_elementType = TYPE_BUS; }
24Bus::Bus(wxPoint2DDouble position) : PowerElement()
25{
26 m_elementType = TYPE_BUS;
27 m_width = 100.0;
28 m_height = 5.0;
29 SetPosition(position);
30}
31
32Bus::Bus(wxPoint2DDouble position, wxString name)
33{
34 m_elementType = TYPE_BUS;
35 m_width = 100.0;
36 m_height = 5.0;
37 SetPosition(position);
38
39 m_electricalData.name = name;
40}
41
42Bus::~Bus() {}
43
44void Bus::DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext* gc) const
45{
46 wxPoint2DDouble gcPosition = m_position - wxPoint2DDouble(m_width / 2.0, m_height / 2.0);
47 wxGraphicsMatrix identityMatrix = gc->GetTransform();
48 identityMatrix.Set(); // Set to identity
49
50 gc->SetPen(*wxTRANSPARENT_PEN);
51
52 // Draw selection (layer 1)
53 if (m_selected) {
54 // If the object is selected, the matrix is reset to remove scale effects applied to it, thus keeping the
55 // edges with fixed sizes for all zoom levels.
56 gc->PushState();
57 gc->SetTransform(identityMatrix);
58 // The matrix was reset, so we must use screen coordinates (WorldToScreen).
59 wxPoint2DDouble screenPt = WorldToScreen(translation, scale);
60 gc->Translate(screenPt.m_x, screenPt.m_y);
61 gc->Rotate(wxDegToRad(m_angle));
62 gc->Translate(-screenPt.m_x, -screenPt.m_y);
63
64 gc->SetBrush(wxBrush(m_selectionColour));
65
66 wxPoint2DDouble pts[4] = { WorldToScreen(translation, scale, -(m_width / 2.0), -(m_height / 2.0)) -
67 wxPoint2DDouble(m_borderSize, m_borderSize),
68 WorldToScreen(translation, scale, -(m_width / 2.0), (m_height / 2.0)) -
69 wxPoint2DDouble(m_borderSize, -m_borderSize),
70 WorldToScreen(translation, scale, (m_width / 2.0), (m_height / 2.0)) -
71 wxPoint2DDouble(-m_borderSize, -m_borderSize),
72 WorldToScreen(translation, scale, (m_width / 2.0), -(m_height / 2.0)) -
73 wxPoint2DDouble(-m_borderSize, m_borderSize) };
74 gc->DrawLines(4, pts);
75 gc->PopState();
76 }
77
78 gc->PushState();
79 gc->Translate(m_position.m_x, m_position.m_y);
80 gc->Rotate(wxDegToRad(m_angle));
81 gc->Translate(-m_position.m_x, -m_position.m_y);
82
83
84 if (!m_electricalData.isConnected)
85 gc->SetBrush(wxBrush(m_offlineElementColour));
86 else if (m_dynEvent)
87 gc->SetBrush(wxBrush(m_dynamicEventColour));
88 else
89 gc->SetBrush(wxBrush(m_busColour));
90
91 gc->DrawRectangle(gcPosition.m_x, gcPosition.m_y, m_width, m_height);
92
93 //if (m_electricalData.slackBus) {
94 // gc->SetBrush(wxBrush(*wxBLACK, wxBRUSHSTYLE_CROSSDIAG_HATCH));
95 // gc->DrawRectangle(gcPosition.m_x, gcPosition.m_y, m_width, m_height);
96 //}
97
98 gc->PopState();
99
100 // Draw pickbox (layer 3)
101 if (m_showPickbox) {
102 gc->PushState();
103 gc->SetTransform(identityMatrix);
104
105 wxPoint2DDouble screenPt = WorldToScreen(translation, scale);
106 gc->Translate(screenPt.m_x, screenPt.m_y);
107 gc->Rotate(wxDegToRad(m_angle));
108 gc->Translate(-screenPt.m_x, -screenPt.m_y);
109
110 wxPoint2DDouble pbPosition[2] = { WorldToScreen(translation, scale, m_width / 2.0) - wxPoint2DDouble(4, 4),
111 WorldToScreen(translation, scale, -m_width / 2.0) - wxPoint2DDouble(4, 4) };
112 DrawDCPickbox(pbPosition[0], gc);
113 DrawDCPickbox(pbPosition[1], gc);
114
115 gc->PopState();
116 }
117
118 // Draw faulted bus symbol (layer 4)
119 if (m_electricalData.hasFault) {
120 gc->PushState();
121 gc->SetTransform(identityMatrix);
122
123 wxPoint2DDouble screenPt = WorldToScreen(translation, scale);
124 gc->Translate(screenPt.m_x, screenPt.m_y);
125 gc->Rotate(wxDegToRad(m_angle));
126 gc->Translate(-screenPt.m_x, -screenPt.m_y);
127
128 wxPoint2DDouble fsPosition = WorldToScreen(translation, scale, m_width / 2.0);
129
130 wxColour faultSymbolColour(255, 0, 0, 255);
131 //glColor4dv(faultSymbolColour);
132
133 double scale = 1.5;
134
135 gc->SetBrush(*wxRED_BRUSH);
136 gc->SetPen(*wxTRANSPARENT_PEN);
137 //gc->SetPen(*wxRED_PEN);
138
139 wxPoint2DDouble* points = new wxPoint2DDouble[4];
140 points[0] = wxPoint2DDouble(fsPosition.m_x + 1 * scale, fsPosition.m_y + 3 * scale);
141 points[1] = wxPoint2DDouble(fsPosition.m_x + 1 * scale, fsPosition.m_y - 3 * scale);
142 points[2] = wxPoint2DDouble(fsPosition.m_x + 11 * scale, fsPosition.m_y - 1 * scale);
143 points[3] = wxPoint2DDouble(fsPosition.m_x + 11 * scale, fsPosition.m_y + 5 * scale);
144
145 gc->DrawLines(4, points);
146
147 points[0] = wxPoint2DDouble(fsPosition.m_x + 7 * scale, fsPosition.m_y - 5 * scale);
148 points[1] = wxPoint2DDouble(fsPosition.m_x + 21 * scale, fsPosition.m_y + 3 * scale);
149 points[2] = wxPoint2DDouble(fsPosition.m_x + 7 * scale, fsPosition.m_y + 1 * scale);
150
151 gc->DrawLines(3, points);
152
153 delete[] points;
154
155 gc->PopState();
156 }
157}
158
159void Bus::DrawDC(wxPoint2DDouble translation, double scale, wxDC& dc) const
160{
161 //wxPoint2DDouble gcPosition = m_position - wxPoint2DDouble(m_width / 2.0, m_height / 2.0);
162 wxPoint2DDouble gcPosition = m_position;
163
164 dc.SetPen(*wxTRANSPARENT_PEN);
165
166 // Draw selection (layer 1)
167 if (m_selected) {
168 dc.SetBrush(wxBrush(m_selectionColour));
169
170 wxPoint2DDouble pts[4] = { WorldToScreen(translation, scale, -(m_width / 2.0), -(m_height / 2.0)) -
171 wxPoint2DDouble(m_borderSize, m_borderSize),
172 WorldToScreen(translation, scale, -(m_width / 2.0), (m_height / 2.0)) -
173 wxPoint2DDouble(m_borderSize, -m_borderSize),
174 WorldToScreen(translation, scale, (m_width / 2.0), (m_height / 2.0)) -
175 wxPoint2DDouble(-m_borderSize, -m_borderSize),
176 WorldToScreen(translation, scale, (m_width / 2.0), -(m_height / 2.0)) -
177 wxPoint2DDouble(-m_borderSize, m_borderSize) };
178
179 DrawDCRectangle(gcPosition, m_width + 2 * m_borderSize, m_height + 2 * m_borderSize, m_angle, dc);
180 }
181
182
183 if (!m_electricalData.isConnected)
184 dc.SetBrush(wxBrush(m_offlineElementColour));
185 else if (m_dynEvent)
186 dc.SetBrush(wxBrush(m_dynamicEventColour));
187 else
188 dc.SetBrush(wxBrush(m_busColour));
189
190 DrawDCRectangle(gcPosition, m_width, m_height, m_angle, dc);
191
192
193 // Draw faulted bus symbol (layer 4)
194 if (m_electricalData.hasFault) {
195
196 wxPoint2DDouble center = m_position;
197 wxPoint2DDouble fsPosition = center + wxPoint2DDouble(m_width / 2.0, 0.0);
198
199 wxColour faultSymbolColour(255, 0, 0, 255);
200
201 double localScale = 1.5;
202
203 dc.SetBrush(*wxRED_BRUSH);
204 dc.SetPen(*wxTRANSPARENT_PEN);
205 //gc->SetPen(*wxRED_PEN);
206
207 wxPoint points[4];
208
209 wxPoint2DDouble p;
210
211 // Primeiro polĂ­gono
212 p = wxPoint2DDouble(fsPosition.m_x + 1 * localScale, fsPosition.m_y + 3 * localScale);
213 points[0] = RotateAround(p, center, m_angle);
214 p = wxPoint2DDouble(fsPosition.m_x + 1 * localScale, fsPosition.m_y - 3 * localScale);
215 points[1] = RotateAround(p, center, m_angle);
216 p = wxPoint2DDouble(fsPosition.m_x + 11 * localScale, fsPosition.m_y - 1 * localScale);
217 points[2] = RotateAround(p, center, m_angle);
218 p = wxPoint2DDouble(fsPosition.m_x + 11 * localScale, fsPosition.m_y + 5 * localScale);
219 points[3] = RotateAround(p, center, m_angle);
220
221 dc.DrawPolygon(4, points);
222
223 p = wxPoint2DDouble(fsPosition.m_x + 7 * localScale, fsPosition.m_y - 5 * localScale);
224 points[0] = RotateAround(p, center, m_angle);
225 p = wxPoint2DDouble(fsPosition.m_x + 21 * localScale, fsPosition.m_y + 3 * localScale);
226 points[1] = RotateAround(p, center, m_angle);
227 p = wxPoint2DDouble(fsPosition.m_x + 7 * localScale, fsPosition.m_y + 1 * localScale);
228 points[2] = RotateAround(p, center, m_angle);
229
230 dc.DrawPolygon(3, points);
231 }
232}
233
234bool Bus::Contains(wxPoint2DDouble position) const
235{
236 wxPoint2DDouble ptR = RotateAtPosition(position, -m_angle);
237 return m_rect.Contains(ptR);
238}
239
240bool Bus::Intersects(wxRect2DDouble rect) const
241{
242 if (m_angle == 0.0 || m_angle == 180.0) return m_rect.Intersects(rect);
243
244 return RotatedRectanglesIntersects(m_rect, rect, m_angle, 0.0);
245}
246
247bool Bus::PickboxContains(wxPoint2DDouble position)
248{
249 m_activePickboxID = ID_PB_NONE;
250
251 wxPoint2DDouble ptR = RotateAtPosition(position, -m_angle);
252
253 wxPoint2DDouble center(m_position.m_x + m_width / 2.0, m_position.m_y);
254 wxRect2DDouble rectRight(center.m_x - 5.0, center.m_y - 5.0, 10.0, 10.0);
255
256 center = wxPoint2DDouble(m_position.m_x - m_width / 2.0, m_position.m_y);
257 wxRect2DDouble rectLeft(center.m_x - 5.0, center.m_y - 5.0, 10.0, 10.0);
258
259 if (rectRight.Contains(ptR)) {
260 m_activePickboxID = ID_PB_RIGHT;
261 return true;
262 }
263 if (rectLeft.Contains(ptR)) {
264 m_activePickboxID = ID_PB_LEFT;
265 return true;
266 }
267
268 return false;
269}
270
272{
273 double angle = m_angle;
274 while (angle >= 157.5) angle -= 180.0;
275
276 if (angle >= -22.5 && angle < 22.5)
277 return wxCursor(wxCURSOR_SIZEWE);
278 else if (angle >= 22.5 && angle < 67.5)
279 return wxCursor(wxCURSOR_SIZENWSE);
280 else if (angle >= 67.5 && angle < 112.5)
281 return wxCursor(wxCURSOR_SIZENS);
282 else if (angle >= 112.5 && angle < 157.5)
283 return wxCursor(wxCURSOR_SIZENESW);
284
285 return wxCursor(wxCURSOR_ARROW);
286}
287
288void Bus::MovePickbox(wxPoint2DDouble position)
289{
290 if (m_activePickboxID == ID_PB_NONE) return;
291
292 wxPoint2DDouble ptR = RotateAtPosition(position, -m_angle);
293
294 double dx = 0.0;
295 if (m_activePickboxID == ID_PB_RIGHT)
296 dx = ptR.m_x - m_position.m_x - m_width / 2.0;
297 else if (m_activePickboxID == ID_PB_LEFT)
298 dx = m_position.m_x - m_width / 2.0 - ptR.m_x;
299
300 if (m_width + dx < 20.0) return;
301
302 if (m_activePickboxID == ID_PB_RIGHT) {
303 m_position.m_x += (dx / 2.0) * std::cos(wxDegToRad(m_angle));
304 m_position.m_y += (dx / 2.0) * std::sin(wxDegToRad(m_angle));
305 }
306 else if (m_activePickboxID == ID_PB_LEFT) {
307 m_position.m_x -= (dx / 2.0) * std::cos(wxDegToRad(m_angle));
308 m_position.m_y -= (dx / 2.0) * std::sin(wxDegToRad(m_angle));
309 }
310 m_width += dx;
311
312 SetPosition(m_position);
313}
314
315void Bus::Rotate(bool clockwise)
316{
317 double rotAngle = m_rotationAngle;
318 if (!clockwise) rotAngle = -m_rotationAngle;
319
320 m_angle += rotAngle;
321 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
322}
323
324bool Bus::GetContextMenu(wxMenu& menu)
325{
326 menu.Append(ContextMenuID::ID_EDIT_ELEMENT, _("Edit bus"));
327
328 wxMenu* textMenu = new wxMenu();
329
330 textMenu->Append(ID_TXT_NAME, _("Name"));
331 textMenu->Append(ID_TXT_VOLTAGE, _("Voltage"));
332 textMenu->Append(ID_TXT_ANGLE, _("Angle"));
333 textMenu->Append(ID_TXT_FAULTCURRENT, _("Fault current"));
334 textMenu->Append(ID_TXT_FAULTVOLTAGE, _("Fault voltage"));
335 textMenu->Append(ID_TXT_SCC, _("Short-circuit power"));
336 textMenu->Append(ID_TXT_THD, _("Voltage THD"));
337 textMenu->SetClientData(menu.GetClientData());
338
339
340 menu.AppendSubMenu(textMenu, _("Add text"));
341 GeneralMenuItens(menu);
342 return true;
343}
344
345bool Bus::ShowForm(wxWindow* parent, Element* element)
346{
347 BusForm busForm(parent, this);
348 busForm.CentreOnParent();
349 if (busForm.ShowModal() == wxID_OK) {
350 return true;
351 }
352 return false;
353}
354
356{
357 Bus* copy = new Bus();
358 *copy = *this;
359 return copy;
360}
361wxString Bus::GetTipText() const
362{
363 wxString tipText = m_electricalData.name;
364 tipText += wxString::Format(" (%d)", m_electricalData.number + 1);
365 tipText += "\n";
366 tipText += StringFromDouble(m_electricalData.nominalVoltage, 1) +
367 (m_electricalData.nominalVoltageUnit == ElectricalUnit::UNIT_V
368 ? _(" V")
369 : _(" kV"));
370 tipText += "\n";
371 tipText += _("\nV = ") + wxString::FromDouble(std::abs(m_electricalData.voltage), 5) + _(" p.u.");
372 tipText += "\n";
373 tipText += wxString(L'\u03B8') + " = " + wxString::FromDouble(wxRadToDeg(std::arg(m_electricalData.voltage)), 5)
374 + wxString(L'\u00B0');
375
376 tipText += _("\n\nFault info:");
377 tipText += _("\nVa = ") + wxString::FromDouble(std::abs(m_electricalData.faultVoltage[0]), 5) + _(" p.u.");
378 tipText += _("\nVb = ") + wxString::FromDouble(std::abs(m_electricalData.faultVoltage[1]), 5) + _(" p.u.");
379 tipText += _("\nVc = ") + wxString::FromDouble(std::abs(m_electricalData.faultVoltage[2]), 5) + _(" p.u.");
380 if (m_electricalData.hasFault) {
381 tipText += _("\nIa = ") + wxString::FromDouble(std::abs(m_electricalData.faultCurrent[0]), 5) + _(" p.u.");
382 tipText += _("\nIb = ") + wxString::FromDouble(std::abs(m_electricalData.faultCurrent[1]), 5) + _(" p.u.");
383 tipText += _("\nIc = ") + wxString::FromDouble(std::abs(m_electricalData.faultCurrent[2]), 5) + _(" p.u.");
384 }
385
386 tipText += _("\n\nSsc = ") + wxString::FromDouble(std::abs(m_electricalData.scPower), 5) + _(" p.u.");
387
388 wxString harmonicsInfo = _("\n\nHarmonics info:");
389 bool hasHarmonics = false;
390 harmonicsInfo += _("\nTHD = ") + wxString::FromDouble(std::abs(m_electricalData.thd), 5) + wxT("%");
391 int i = 0;
392 for (auto& hVoltage : m_electricalData.harmonicVoltage) {
393 hasHarmonics = true;
394 wxString hVoltageStr;
395 hVoltageStr.Printf(_("\nVh(%d) = %.5e%s%.2f%s p.u."), m_electricalData.harmonicOrder[i], std::abs(hVoltage), wxString(L'\u2220'), wxRadToDeg(std::arg(hVoltage)), wxString(L'\u00B0'));
396 harmonicsInfo += hVoltageStr;
397 i++;
398 }
399 if (hasHarmonics) tipText += harmonicsInfo;
400
401 return tipText;
402}
403
405{
406 if (study == PlotStudy::STABILITY) {
407 if (!m_electricalData.plotBus) return false;
408 plotData.SetName(m_electricalData.name);
409 plotData.SetCurveType(ElementPlotData::CurveType::CT_BUS);
410
411 std::vector<double> absVoltage, argVoltage;
412 for (unsigned int i = 0; i < m_electricalData.stabVoltageVector.size(); ++i) {
413 absVoltage.push_back(std::abs(m_electricalData.stabVoltageVector[i]));
414 argVoltage.push_back(wxRadToDeg(std::arg(m_electricalData.stabVoltageVector[i])));
415 }
416 plotData.AddData(absVoltage, _("Voltage"));
417 plotData.AddData(argVoltage, _("Angle"));
418 plotData.AddData(m_electricalData.stabFreqVector, _("Frequency"));
419 return true;
420 }
421 else if (study == PlotStudy::FREQRESPONSE) {
422 if (!m_electricalData.plotPQData) return false;
423 plotData.SetName(m_electricalData.name);
424 plotData.SetCurveType(ElementPlotData::CurveType::CT_BUS);
425 plotData.AddData(m_electricalData.absImpedanceVector, _("Impedance"));
426 return true;
427 }
428 return false;
429}
430
431rapidxml::xml_node<>* Bus::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
432{
433 m_electricalData.number = m_elementID;
434
435 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "Bus");
436 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
437
438 Element::SaveCADProperties(doc, elementNode);
439
440 auto electricalProp = XMLParser::AppendNode(doc, elementNode, "ElectricalProperties");
441 auto name = XMLParser::AppendNode(doc, electricalProp, "Name");
442 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
443 auto nominalVoltage = XMLParser::AppendNode(doc, electricalProp, "NominalVoltage");
444 XMLParser::SetNodeValue(doc, nominalVoltage, m_electricalData.nominalVoltage);
445 XMLParser::SetNodeAttribute(doc, nominalVoltage, "UnitID", static_cast<int>(m_electricalData.nominalVoltageUnit));
446 auto isVoltageControlled = XMLParser::AppendNode(doc, electricalProp, "IsVoltageControlled");
447 XMLParser::SetNodeValue(doc, isVoltageControlled, m_electricalData.isVoltageControlled);
448 auto controlledVoltage = XMLParser::AppendNode(doc, electricalProp, "ControlledVoltage");
449 XMLParser::SetNodeValue(doc, controlledVoltage, m_electricalData.controlledVoltage);
450 XMLParser::SetNodeAttribute(doc, controlledVoltage, "Choice", m_electricalData.controlledVoltageUnitChoice);
451 auto slackBus = XMLParser::AppendNode(doc, electricalProp, "SlackBus");
452 XMLParser::SetNodeValue(doc, slackBus, m_electricalData.slackBus);
453
454 auto fault = XMLParser::AppendNode(doc, electricalProp, "Fault");
455 auto hasFault = XMLParser::AppendNode(doc, fault, "HasFault");
456 XMLParser::SetNodeValue(doc, hasFault, m_electricalData.hasFault);
457 auto faultType = XMLParser::AppendNode(doc, fault, "Type");
458 XMLParser::SetNodeValue(doc, faultType, static_cast<int>(m_electricalData.faultType));
459 auto faultLocation = XMLParser::AppendNode(doc, fault, "Location");
460 XMLParser::SetNodeValue(doc, faultLocation, static_cast<int>(m_electricalData.faultLocation));
461 auto faultResistance = XMLParser::AppendNode(doc, fault, "Resistance");
462 XMLParser::SetNodeValue(doc, faultResistance, m_electricalData.faultResistance);
463 auto faultReactance = XMLParser::AppendNode(doc, fault, "Reactance");
464 XMLParser::SetNodeValue(doc, faultReactance, m_electricalData.faultReactance);
465
466 auto stability = XMLParser::AppendNode(doc, electricalProp, "Stability");
467 auto plotBus = XMLParser::AppendNode(doc, stability, "Plot");
468 XMLParser::SetNodeValue(doc, plotBus, m_electricalData.plotBus);
469 auto stabHasFault = XMLParser::AppendNode(doc, stability, "HasFault");
470 XMLParser::SetNodeValue(doc, stabHasFault, m_electricalData.stabHasFault);
471 auto stabFaultTime = XMLParser::AppendNode(doc, stability, "FaultTime");
472 XMLParser::SetNodeValue(doc, stabFaultTime, m_electricalData.stabFaultTime);
473 auto stabFaultLength = XMLParser::AppendNode(doc, stability, "FaultLength");
474 XMLParser::SetNodeValue(doc, stabFaultLength, m_electricalData.stabFaultLength);
475 auto stabFaultResistance = XMLParser::AppendNode(doc, stability, "FaultResistance");
476 XMLParser::SetNodeValue(doc, stabFaultResistance, m_electricalData.stabFaultResistance);
477 auto stabFaultReactance = XMLParser::AppendNode(doc, stability, "FaultReactance");
478 XMLParser::SetNodeValue(doc, stabFaultReactance, m_electricalData.stabFaultReactance);
479
480 auto powerQuality = XMLParser::AppendNode(doc, electricalProp, "PowerQuality");
481 auto plotPQData = XMLParser::AppendNode(doc, powerQuality, "Plot");
482 XMLParser::SetNodeValue(doc, plotPQData, m_electricalData.plotPQData);
483
484 return elementNode;
485}
486
487bool Bus::OpenElement(rapidxml::xml_node<>* elementNode)
488{
489 if (!Element::OpenCADProperties(elementNode)) return false;
490
491 auto electricalProp = elementNode->first_node("ElectricalProperties");
492 if (!electricalProp) return false;
493
494 m_electricalData.name = electricalProp->first_node("Name")->value();
495 m_electricalData.nominalVoltage = XMLParser::GetNodeValueDouble(electricalProp, "NominalVoltage");
496 m_electricalData.nominalVoltageUnit =
497 (ElectricalUnit)XMLParser::GetAttributeValueInt(electricalProp, "NominalVoltage", "UnitID");
498 m_electricalData.isVoltageControlled = XMLParser::GetNodeValueInt(electricalProp, "IsVoltageControlled");
499 m_electricalData.controlledVoltage = XMLParser::GetNodeValueDouble(electricalProp, "ControlledVoltage");
500 m_electricalData.controlledVoltageUnitChoice =
501 XMLParser::GetAttributeValueInt(electricalProp, "ControlledVoltage", "Choice");
502 m_electricalData.slackBus = XMLParser::GetNodeValueInt(electricalProp, "SlackBus");
503 auto fault = electricalProp->first_node("Fault");
504 m_electricalData.hasFault = XMLParser::GetNodeValueInt(fault, "HasFault");
505 m_electricalData.faultType = (FaultData)XMLParser::GetNodeValueInt(fault, "Type");
506 m_electricalData.faultLocation = (FaultData)XMLParser::GetNodeValueInt(fault, "Location");
507 m_electricalData.faultResistance = XMLParser::GetNodeValueDouble(fault, "Resistance");
508 m_electricalData.faultReactance = XMLParser::GetNodeValueDouble(fault, "Reactance");
509 auto stability = electricalProp->first_node("Stability");
510 m_electricalData.plotBus = XMLParser::GetNodeValueInt(stability, "Plot");
511 m_electricalData.stabHasFault = XMLParser::GetNodeValueInt(stability, "HasFault");
512 m_electricalData.stabFaultTime = XMLParser::GetNodeValueDouble(stability, "FaultTime");
513 m_electricalData.stabFaultLength = XMLParser::GetNodeValueDouble(stability, "FaultLength");
514 m_electricalData.stabFaultResistance = XMLParser::GetNodeValueDouble(stability, "FaultResistance");
515 m_electricalData.stabFaultReactance = XMLParser::GetNodeValueDouble(stability, "FaultReactance");
516
517 auto powerQuality = electricalProp->first_node("PowerQuality");
518 if (powerQuality) m_electricalData.plotPQData = XMLParser::GetNodeValueInt(powerQuality, "Plot");
519
520 if (m_electricalData.stabHasFault) SetDynamicEvent(true);
521 SetInserted();
522 return true;
523}
@ ID_EDIT_ELEMENT
Definition Element.h:75
@ ID_PB_NONE
Definition Element.h:61
@ ID_PB_LEFT
Definition Element.h:63
@ ID_PB_RIGHT
Definition Element.h:62
ElectricalUnit
Electrical units.
FaultData
Information about fault (type and location).
PlotStudy
Form to edit the bus power data.
Definition BusForm.h:32
Node for power elements. All others power elements are connected through this.
Definition Bus.h:86
virtual bool PickboxContains(wxPoint2DDouble position)
Check if a pickbox contains a point. If contains the attributes related to pickbox movement will be c...
Definition Bus.cpp:247
virtual wxString GetTipText() const
Get the tip text.
Definition Bus.cpp:361
virtual bool GetPlotData(ElementPlotData &plotData, PlotStudy study=PlotStudy::STABILITY)
Fill the plot data.
Definition Bus.cpp:404
virtual Element * GetCopy()
Get a the element copy.
Definition Bus.cpp:355
virtual bool Intersects(wxRect2DDouble rect) const
Check if the element's rect intersects other rect.
Definition Bus.cpp:240
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
Definition Bus.cpp:44
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.
Definition Bus.cpp:345
Bus()
Default constructor.
Definition Bus.cpp:23
virtual wxCursor GetBestPickboxCursor() const
Get the best cursor to shown to the user when the mouse is above a pickbox.
Definition Bus.cpp:271
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Bus.cpp:315
virtual bool Contains(wxPoint2DDouble position) const
Checks if the element contains a position.
Definition Bus.cpp:234
virtual void MovePickbox(wxPoint2DDouble position)
Move the pickbox.
Definition Bus.cpp:288
virtual bool GetContextMenu(wxMenu &menu)
Get the element contex menu.
Definition Bus.cpp:324
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
virtual bool RotatedRectanglesIntersects(wxRect2DDouble rect1, wxRect2DDouble rect2, double angle1, double angle2) const
Check if two roteted rectangles intersect.
Definition Element.cpp:359
virtual void GeneralMenuItens(wxMenu &menu)
Insert general itens to context menu.
Definition Element.cpp:457
virtual void DrawDCRectangle(wxPoint2DDouble position, double width, double height, double angle, wxDC &dc) const
Draw a circle.
Definition Element.cpp:45
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
Definition Element.cpp:27
virtual wxPoint2DDouble RotateAtPosition(wxPoint2DDouble pointToRotate, double angle, bool degrees=true) const
Rotate a point as element position being the origin.
Definition Element.cpp:292
virtual void DrawDCPickbox(wxPoint2DDouble position, wxGraphicsContext *gc) const
Draw a point.
Definition Element.cpp:285
virtual wxPoint2DDouble WorldToScreen(wxPoint2DDouble translation, double scale, double offsetX=0.0, double offsetY=0.0) const
Convert the element position to screen position.
Definition Element.cpp:336
static wxString StringFromDouble(double value, int minDecimal=1, int maxDecimals=13)
Convert a double value to string.
Definition Element.cpp:533
void SetInserted(bool inserted=true)
Set if the element is properly inserted in the workspace.
Definition Element.h:631
Abstract class of power elements.
virtual void SetDynamicEvent(bool dynEvent=true)
Set if the power element have dynamic event.