Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
Transformer.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 "Transformer.h"
19#include "../../forms/TransformerForm.h"
20
21Transformer::Transformer() : Branch()
22{
23 m_elementType = TYPE_TRANSFORMER;
24 for (int i = 0; i < 2; i++) {
25 for (int j = 0; j < 3; j++) { m_electricalData.faultCurrent[i][j] = std::complex<double>(0.0, 0.0); }
26 }
27}
28Transformer::Transformer(wxString name) : Branch()
29{
30 m_elementType = TYPE_TRANSFORMER;
31 for (int i = 0; i < 2; i++) {
32 for (int j = 0; j < 3; j++) { m_electricalData.faultCurrent[i][j] = std::complex<double>(0.0, 0.0); }
33 }
34 m_electricalData.name = name;
35}
36Transformer::~Transformer() {}
37
38bool Transformer::AddParent(Element* parent, wxPoint2DDouble position)
39{
40 if (parent) {
41 // First bus.
42 if (m_parentList.size() == 0) {
43 m_position = position;
44 m_parentList.push_back(parent);
45 parent->AddChild(this);
46 wxPoint2DDouble parentPt =
47 parent->RotateAtPosition(position, -parent->GetAngle()); // Rotate click to horizontal position.
48 parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus.
49 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); // Rotate back.
50 m_pointList.push_back(parentPt); // First point
51 m_pointList.push_back(GetSwitchPoint(parent, parentPt, m_position));
52
53 wxRect2DDouble genRect(0, 0, 0, 0);
54 m_switchRect.push_back(genRect);
55
56 return false;
57 }
58 // Second bus.
59 else if (parent != m_parentList[0]) {
60 m_parentList.push_back(parent);
61 parent->AddChild(this);
62 wxPoint2DDouble parentPt =
63 parent->RotateAtPosition(position, -parent->GetAngle()); // Rotate click to horizontal position.
64 parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus.
65 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); // Rotate back.
66
67 // Get the average between the two bus points.
68 m_position =
69 wxPoint2DDouble((m_pointList[0].m_x + parentPt.m_x) / 2.0, (m_pointList[0].m_y + parentPt.m_y) / 2.0);
70 // Set the transformer rectangle.
71 m_width = 70.0;
72 m_height = 40.0;
73 SetPosition(m_position); // This method calculates the rectangle propely.
74 // Set the "side" points.
75 m_pointList.push_back(
76 wxPoint2DDouble(m_rect.GetPosition() + wxPoint2DDouble(-10 - m_borderSize, m_height / 2.0)));
77 m_pointList.push_back(
78 wxPoint2DDouble(m_rect.GetPosition() + wxPoint2DDouble(m_width + 10 + m_borderSize, m_height / 2.0)));
79
80 // Set first switch point.
81 wxPoint2DDouble secondPoint = parentPt;
82 if (m_pointList.size() > 2) { secondPoint = m_pointList[2]; }
83 m_pointList[1] = GetSwitchPoint(m_parentList[0], m_pointList[0], secondPoint);
84
85 // Set the second switch point.
86 m_pointList.push_back(GetSwitchPoint(parent, parentPt, m_pointList[m_pointList.size() - 1]));
87
88 m_pointList.push_back(parentPt); // Last point.
89 m_inserted = true;
90
91 wxRect2DDouble genRect(0, 0, 0, 0);
92 m_switchRect.push_back(genRect);
94 UpdatePowerFlowArrowsPosition();
95
96 return true;
97 }
98 }
99 return false;
100}
101
102bool Transformer::Contains(wxPoint2DDouble position) const
103{
104 wxPoint2DDouble ptR = RotateAtPosition(position, -m_angle);
105 return m_rect.Contains(ptR);
106}
107
108//void Transformer::Draw(wxPoint2DDouble translation, double scale) const
109//{
110// OpenGLColour elementColour;
111// if (m_online) {
112// if (m_dynEvent)
113// elementColour = m_dynamicEventColour;
114// else
115// elementColour = m_onlineElementColour;
116// }
117// else
118// elementColour = m_offlineElementColour;
119//
120// if (m_inserted) {
121// // Draw selection (layer 1).
122// if (m_selected) {
123// // Push the current matrix on stack.
124// glLineWidth(1.5 + m_borderSize * 2.0);
125// glColor4dv(m_selectionColour.GetRGBA());
126// DrawLine(m_pointList);
127// glPushMatrix();
128// // Rotate the matrix around the object position.
129// glTranslated(m_position.m_x, m_position.m_y, 0.0);
130// glRotated(m_angle, 0.0, 0.0, 1.0);
131// glTranslated(-m_position.m_x, -m_position.m_y, 0.0);
132//
133// DrawCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20 + (m_borderSize + 1.5) / scale, 20,
134// GL_POLYGON);
135// DrawCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20 + (m_borderSize + 1.5) / scale, 20,
136// GL_POLYGON);
137//
138// glPopMatrix();
139//
140// // Draw nodes selection.
141// if (m_pointList.size() > 0) {
142// DrawCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, GL_POLYGON);
143// if (m_inserted) {
144// DrawCircle(m_pointList[m_pointList.size() - 1], 5.0 + m_borderSize / scale, 10, GL_POLYGON);
145// }
146// }
147// }
148//
149// // Draw transformer (layer 2).
150// // Transformer line
151// glLineWidth(1.5);
152// glColor4dv(elementColour.GetRGBA());
153// DrawLine(m_pointList);
154//
155// // Draw nodes.
156// if (m_pointList.size() > 0) {
157// glColor4dv(elementColour.GetRGBA());
158// DrawCircle(m_pointList[0], 5.0, 10, GL_POLYGON);
159// if (m_inserted) { DrawCircle(m_pointList[m_pointList.size() - 1], 5.0, 10, GL_POLYGON); }
160// }
161//
162// DrawSwitches();
163// DrawPowerFlowPts();
164//
165// // Push the current matrix on stack.
166// glPushMatrix();
167// // Rotate the matrix around the object position.
168// glTranslated(m_position.m_x, m_position.m_y, 0.0);
169// glRotated(m_angle, 0.0, 0.0, 1.0);
170// glTranslated(-m_position.m_x, -m_position.m_y, 0.0);
171//
172// glColor4d(1.0, 1.0, 1.0, 1.0);
173// DrawCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20, 20, GL_POLYGON);
174// DrawCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20, 20, GL_POLYGON);
175//
176// glColor4dv(elementColour.GetRGBA());
177// DrawCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20, 20);
178// DrawCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20, 20);
179//
180// DrawPoint(m_rect.GetPosition(), 8.0 * scale);
181//
182// glPopMatrix();
183// }
184//}
185
186void Transformer::DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext* gc) const
187{
188 wxColour elementColour;
189 if (m_online) {
190 if (m_dynEvent)
191 elementColour = m_dynamicEventColour;
192 else
193 elementColour = m_onlineElementColour;
194 }
195 else
196 elementColour = m_offlineElementColour;
197
198 if (m_inserted) {
199 // Draw selection (layer 1).
200 if (m_selected) {
201 gc->SetPen(wxPen(wxColour(m_selectionColour), 2 + m_borderSize * 2.0));
202 gc->SetBrush(*wxTRANSPARENT_BRUSH);
203 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
204
205 // Push the current matrix on stack.
206 gc->PushState();
207 // Rotate the matrix around the object position.
208 gc->Translate(m_position.m_x, m_position.m_y);
209 gc->Rotate(wxDegToRad(m_angle));
210 gc->Translate(-m_position.m_x, -m_position.m_y);
211
212 gc->SetPen(*wxTRANSPARENT_PEN);
213 gc->SetBrush(wxBrush(m_selectionColour));
214 DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20 + (m_borderSize + 1.5) / scale, 20, gc);
215 DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20 + (m_borderSize + 1.5) / scale, 20, gc);
216
217 gc->PopState();
218
219 // Draw nodes selection.
220 gc->SetPen(*wxTRANSPARENT_PEN);
221 gc->SetBrush(wxBrush(m_selectionColour));
222 if (m_pointList.size() > 0) {
223 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, gc);
224 if (m_inserted) { DrawDCCircle(m_pointList[m_pointList.size() - 1], 5.0 + m_borderSize / scale, 10, gc); }
225 }
226 }
227
228 // Draw transformer (layer 2).
229 // Transformer line
230 gc->SetPen(wxPen(elementColour, 2));
231 gc->SetBrush(*wxTRANSPARENT_BRUSH);
232 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
233
234 // Draw nodes.
235 gc->SetPen(*wxTRANSPARENT_PEN);
236 gc->SetBrush(wxBrush(elementColour));
237 if (m_pointList.size() > 0) {
238 DrawDCCircle(m_pointList[0], 5.0, 10, gc);
239 if (m_inserted) { DrawDCCircle(m_pointList[m_pointList.size() - 1], 5.0, 10, gc); }
240 }
241
242 DrawDCSwitches(gc);
244
245 // Push the current matrix on stack.
246 gc->PushState();
247 // Rotate the matrix around the object position.
248 gc->Translate(m_position.m_x, m_position.m_y);
249 gc->Rotate(wxDegToRad(m_angle));
250 gc->Translate(-m_position.m_x, -m_position.m_y);
251
252 //glColor4d(1.0, 1.0, 1.0, 1.0);
253 gc->SetPen(*wxTRANSPARENT_PEN);
254 gc->SetBrush(*wxWHITE_BRUSH);
255 DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20, 20, gc);
256 DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20, 20, gc);
257
258 gc->SetPen(wxPen(elementColour, 2));
259 gc->SetBrush(*wxTRANSPARENT_BRUSH);
260 DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20, 20, gc);
261 DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20, 20, gc);
262
263 // Point
264 gc->SetPen(*wxTRANSPARENT_PEN);
265 gc->SetBrush(wxBrush(elementColour));
266 DrawDCCircle(m_rect.GetPosition(), 4, 10, gc);
267
268 gc->PopState();
269 }
270}
271
272void Transformer::DrawDC(wxPoint2DDouble translation, double scale, wxDC& dc) const
273{
274 wxColour elementColour;
275 if (m_online) {
276 if (m_dynEvent)
277 elementColour = m_dynamicEventColour;
278 else
279 elementColour = m_onlineElementColour;
280 }
281 else
282 elementColour = m_offlineElementColour;
283
284 std::vector<wxPoint> pointList;
285 for (auto& pt : m_pointList) { pointList.emplace_back(static_cast<int>(pt.m_x), static_cast<int>(pt.m_y)); }
286
287 if (m_inserted) {
288 // Draw selection (layer 1).
289 if (m_selected) {
290 dc.SetPen(wxPen(wxColour(m_selectionColour), 2 + m_borderSize * 2.0));
291 dc.SetBrush(*wxTRANSPARENT_BRUSH);
292 dc.DrawLines(pointList.size(), &pointList[0]);
293
294 dc.SetPen(*wxTRANSPARENT_PEN);
295 dc.SetBrush(wxBrush(m_selectionColour));
296 //DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(20.0, 20.0), 20 + (m_borderSize + 1.5) / scale, dc);
297 //DrawDCCircle(m_rect.GetPosition() + wxPoint2DDouble(50.0, 20.0), 20 + (m_borderSize + 1.5) / scale, dc);
298 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(15.0, 0.0), m_angle), 20 + (m_borderSize + 1.5) / scale, dc);
299 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(-15.0, 0.0), m_angle), 20 + (m_borderSize + 1.5) / scale, dc);
300
301 // Draw nodes selection.
302 dc.SetPen(*wxTRANSPARENT_PEN);
303 dc.SetBrush(wxBrush(m_selectionColour));
304 if (pointList.size() > 0) {
305 DrawDCCircle(pointList[0], 5.0 + m_borderSize / scale, dc);
306 if (m_inserted) { DrawDCCircle(pointList[pointList.size() - 1], 5.0 + m_borderSize / scale, dc); }
307 }
308 }
309
310 // Draw transformer (layer 2).
311 // Transformer line
312 dc.SetPen(wxPen(elementColour, 2));
313 dc.SetBrush(*wxTRANSPARENT_BRUSH);
314 dc.DrawLines(pointList.size(), &pointList[0]);
315
316 // Draw nodes.
317 dc.SetPen(*wxTRANSPARENT_PEN);
318 dc.SetBrush(wxBrush(elementColour));
319 if (pointList.size() > 0) {
320 DrawDCCircle(pointList[0], 5.0, dc);
321 if (m_inserted) { DrawDCCircle(pointList[pointList.size() - 1], 5.0, dc); }
322 }
323
324 DrawDCSwitches(dc);
326
327 dc.SetPen(*wxTRANSPARENT_PEN);
328 dc.SetBrush(*wxWHITE_BRUSH);
329 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(15.0, 0.0), m_angle), 20, dc);
330 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(-15.0, 0.0), m_angle), 20, dc);
331
332 dc.SetPen(wxPen(elementColour, 2));
333 dc.SetBrush(*wxTRANSPARENT_BRUSH);
334 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(15.0, 0.0), m_angle), 20, dc);
335 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(-15.0, 0.0), m_angle), 20, dc);
336
337 // Point
338 dc.SetPen(*wxTRANSPARENT_PEN);
339 dc.SetBrush(wxBrush(elementColour));
340 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(-35, -20), m_angle), 4, dc);
341 }
342}
343
344bool Transformer::Intersects(wxRect2DDouble rect) const
345{
346 if (m_angle == 0.0 || m_angle == 180.0) return m_rect.Intersects(rect);
347 return RotatedRectanglesIntersects(m_rect, rect, m_angle, 0.0);
348}
349
350void Transformer::Rotate(bool clockwise)
351{
352 double rotAngle = m_rotationAngle;
353 if (!clockwise) rotAngle = -m_rotationAngle;
354
355 m_angle += rotAngle;
356 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
357
358 // Rotate all the points, except the switches and buses points.
359 for (int i = 2; i < (int)m_pointList.size() - 2; i++) {
360 m_pointList[i] = RotateAtPosition(m_pointList[i], rotAngle);
361 }
362 UpdateSwitchesPosition();
363 UpdatePowerFlowArrowsPosition();
364}
365
366void Transformer::Move(wxPoint2DDouble position)
367{
368 SetPosition(m_movePos + position - m_moveStartPt);
369
370 // Move all the points, except the switches and buses points.
371 for (int i = 2; i < (int)m_pointList.size() - 2; i++) { m_pointList[i] = m_movePts[i] + position - m_moveStartPt; }
372
373 if (!m_parentList[0]) { m_pointList[0] = m_movePts[0] + position - m_moveStartPt; }
374 if (!m_parentList[1]) {
375 m_pointList[m_pointList.size() - 1] = m_movePts[m_pointList.size() - 1] + position - m_moveStartPt;
376 }
377
378 UpdateSwitchesPosition();
379 UpdatePowerFlowArrowsPosition();
380}
381
382void Transformer::MoveNode(Element* parent, wxPoint2DDouble position)
383{
384 if (parent) {
385 // First bus.
386 if (parent == m_parentList[0]) {
387 m_pointList[0] = m_movePts[0] + position - m_moveStartPt;
388 }
389 // Second bus.
390 else if (parent == m_parentList[1]) {
391 m_pointList[m_pointList.size() - 1] = m_movePts[m_pointList.size() - 1] + position - m_moveStartPt;
392 }
393 }
394 else {
395 if (m_activeNodeID == 1) {
396 m_pointList[0] = m_movePts[0] + position - m_moveStartPt;
397 if (m_parentList[0]) {
398 m_parentList[0]->RemoveChild(this);
399 m_parentList[0] = nullptr;
400 m_online = false;
401 }
402 }
403 else if (m_activeNodeID == 2) {
404 m_pointList[m_pointList.size() - 1] = m_movePts[m_pointList.size() - 1] + position - m_moveStartPt;
405 if (m_parentList[1]) {
406 m_parentList[1]->RemoveChild(this);
407 m_parentList[1] = nullptr;
408 m_online = false;
409 }
410 }
411 }
412
413 // Recalculate switches positions
414 UpdateSwitchesPosition();
415 UpdatePowerFlowArrowsPosition();
416}
417
418void Transformer::StartMove(wxPoint2DDouble position)
419{
420 m_moveStartPt = position;
421 m_movePts = m_pointList;
422 m_movePos = m_position;
423}
424
426{
427 menu.Append(ID_EDIT_ELEMENT, _("Edit tranformer"));
428
429 wxString busName[2] = { "?", "?" };
430 if (m_parentList.size() == 2) {
431 int i = 0;
432 for (Element* element : m_parentList) {
433 if (element) {
434 Bus* bus = static_cast<Bus*>(element);
435 busName[i] = bus->GetElectricalData().name;
436 }
437 i++;
438 }
439 }
440
441 wxMenu* textMenu = new wxMenu();
442
443 textMenu->Append(ID_TXT_NAME, _("Name"));
444 textMenu->Append(ID_TXT_BRANCH_ACTIVE_POWER_1_2, _("Active power (") + busName[0] + _(" to ") + busName[1] + wxT(")"));
445 textMenu->Append(ID_TXT_BRANCH_ACTIVE_POWER_2_1, _("Active power (") + busName[1] + _(" to ") + busName[0] + wxT(")"));
446 textMenu->Append(ID_TXT_BRANCH_REACTIVE_POWER_1_2, _("Reactive power (") + busName[0] + _(" to ") + busName[1] + wxT(")"));
447 textMenu->Append(ID_TXT_BRANCH_REACTIVE_POWER_2_1, _("Reactive power (") + busName[1] + _(" to ") + busName[0] + wxT(")"));
448 textMenu->Append(ID_TXT_BRANCH_LOSSES, _("Losses"));
449 textMenu->Append(ID_TXT_BRANCH_CURRENT_1_2, _("Current (") + busName[0] + _(" to ") + busName[1] + wxT(")"));
450 textMenu->Append(ID_TXT_BRANCH_CURRENT_2_1, _("Current (") + busName[1] + _(" to ") + busName[0] + wxT(")"));
451 textMenu->Append(ID_TXT_BRANCH_FAULT_CURRENT_1_2, _("Fault current (") + busName[0] + _(" to ") + busName[1] + wxT(")"));
452 textMenu->Append(ID_TXT_BRANCH_FAULT_CURRENT_2_1, _("Fault current (") + busName[1] + _(" to ") + busName[0] + wxT(")"));
453 textMenu->SetClientData(menu.GetClientData());
454 menu.AppendSubMenu(textMenu, _("Add text"));
455
456 GeneralMenuItens(menu);
457 return true;
458}
459
460bool Transformer::ShowForm(wxWindow* parent, Element* element)
461{
462 TransformerForm transfForm(parent, this);
463 transfForm.CenterOnParent();
464 if (transfForm.ShowModal() == wxID_OK) {
465 return true;
466 }
467 return false;
468}
469
470void Transformer::SetNominalVoltage(std::vector<double> nominalVoltage, std::vector<ElectricalUnit> nominalVoltageUnit)
471{
472 if (nominalVoltage.size() == 1) {
473 m_electricalData.primaryNominalVoltage = nominalVoltage[0];
474 m_electricalData.primaryNominalVoltageUnit = nominalVoltageUnit[0];
475 }
476 else if (nominalVoltage.size() == 2) {
477 m_electricalData.primaryNominalVoltage = nominalVoltage[0];
478 m_electricalData.primaryNominalVoltageUnit = nominalVoltageUnit[0];
479 m_electricalData.secondaryNominalVoltage = nominalVoltage[1];
480 m_electricalData.secondaryNominalVoltageUnit = nominalVoltageUnit[1];
481 }
482}
483
484void Transformer::UpdatePowerFlowArrowsPosition()
485{
486 std::vector<wxPoint2DDouble> edges;
487 switch (m_pfDirection) {
489 m_powerFlowArrow.clear();
490 } break;
492 for (int i = 1; i < (int)m_pointList.size() - 1; i++) { edges.push_back(m_pointList[i]); }
493 } break;
495 for (int i = (int)m_pointList.size() - 2; i > 0; i--) { edges.push_back(m_pointList[i]); }
496 } break;
497 default:
498 break;
499 }
501}
502
503void Transformer::RotateNode(Element* parent, bool clockwise)
504{
505 double rotAngle = m_rotationAngle;
506 if (!clockwise) rotAngle = -m_rotationAngle;
507
508 if (parent == m_parentList[0]) {
509 m_pointList[0] = parent->RotateAtPosition(m_pointList[0], rotAngle);
510 }
511 else if (parent == m_parentList[1]) {
512 m_pointList[m_pointList.size() - 1] = parent->RotateAtPosition(m_pointList[m_pointList.size() - 1], rotAngle);
513 }
514 UpdateSwitchesPosition();
515 UpdatePowerFlowArrowsPosition();
516}
517
519{
520 if (m_activeNodeID == 1 && parent == m_parentList[0]) return false;
521 if (m_activeNodeID == 2 && parent == m_parentList[1]) return false;
522
523 if (parent && m_activeNodeID != 0) {
524 wxRect2DDouble nodeRect(0, 0, 0, 0);
525 if (m_activeNodeID == 1) {
526 nodeRect = wxRect2DDouble(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize,
527 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize);
528 }
529 if (m_activeNodeID == 2) {
530 nodeRect = wxRect2DDouble(m_pointList[m_pointList.size() - 1].m_x - 5.0 - m_borderSize,
531 m_pointList[m_pointList.size() - 1].m_y - 5.0 - m_borderSize,
532 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize);
533 }
534
535 if (parent->Intersects(nodeRect)) {
536 if (m_activeNodeID == 1) {
537 // Check if the user is trying to connect the same bus.
538 if (m_parentList[1] == parent) {
539 m_activeNodeID = 0;
540 return false;
541 }
542
543 m_parentList[0] = parent;
544
545 // Centralize the node on bus.
546 wxPoint2DDouble parentPt = parent->RotateAtPosition(
547 m_pointList[0], -parent->GetAngle()); // Rotate click to horizontal position.
548 parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus.
549 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle());
550 m_pointList[0] = parentPt;
551
552 UpdateSwitchesPosition();
553 UpdatePowerFlowArrowsPosition();
554 return true;
555 }
556 if (m_activeNodeID == 2) {
557 if (m_parentList[0] == parent) {
558 m_activeNodeID = 0;
559 return false;
560 }
561
562 m_parentList[1] = parent;
563
564 wxPoint2DDouble parentPt =
565 parent->RotateAtPosition(m_pointList[m_pointList.size() - 1], -parent->GetAngle());
566 parentPt.m_y = parent->GetPosition().m_y;
567 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle());
568 m_pointList[m_pointList.size() - 1] = parentPt;
569
570 UpdateSwitchesPosition();
571 UpdatePowerFlowArrowsPosition();
572 return true;
573 }
574 }
575 else {
576 if (m_activeNodeID == 1) m_parentList[0] = nullptr;
577 if (m_activeNodeID == 2) m_parentList[1] = nullptr;
578 }
579 }
580 return false;
581}
582
584{
585 m_pfDirection = pfDirection;
586 UpdatePowerFlowArrowsPosition();
587}
588
590{
591 Transformer* copy = new Transformer();
592 *copy = *this;
593 return copy;
594}
595
597{
598 wxString tipText = m_electricalData.name;
599 wxString primVoltage = StringFromDouble(m_electricalData.primaryNominalVoltage);
600 switch (m_electricalData.primaryNominalVoltageUnit) {
602 primVoltage += _(" V");
603 } break;
605 primVoltage += _(" kV");
606 } break;
607 default:
608 break;
609 }
610 wxString secVoltage = StringFromDouble(m_electricalData.secondaryNominalVoltage);
611 switch (m_electricalData.secondaryNominalVoltageUnit) {
613 secVoltage += _(" V");
614 } break;
616 secVoltage += _(" kV");
617 } break;
618 default:
619 break;
620 }
621
622 tipText += "\n" + primVoltage + " / " + secVoltage;
623
624 if (m_online) {
625 tipText += "\n";
626 int busNumber[2];
627 busNumber[0] = static_cast<Bus*>(m_parentList[0])->GetElectricalData().number + 1;
628 busNumber[1] = static_cast<Bus*>(m_parentList[1])->GetElectricalData().number + 1;
629
630 tipText += _("\nP") + wxString::Format("(%d-%d) = ", busNumber[0], busNumber[1]) +
631 wxString::FromDouble(m_electricalData.powerFlow[0].real(), 5) + _(" p.u.");
632 tipText += _("\nQ") + wxString::Format("(%d-%d) = ", busNumber[0], busNumber[1]) +
633 wxString::FromDouble(m_electricalData.powerFlow[0].imag(), 5) + _(" p.u.");
634 tipText += _("\nP") + wxString::Format("(%d-%d) = ", busNumber[1], busNumber[0]) +
635 wxString::FromDouble(m_electricalData.powerFlow[1].real(), 5) + _(" p.u.");
636 tipText += _("\nQ") + wxString::Format("(%d-%d) = ", busNumber[1], busNumber[0]) +
637 wxString::FromDouble(m_electricalData.powerFlow[1].imag(), 5) + _(" p.u.");
638
639 if (!m_electricalData.harmonicOrder.empty()) {
640 tipText += _("\n\nHarmonic currents:");
641 int i = 0;
642 for (auto& hCurrent1 : m_electricalData.harmonicCurrent[0]) {
643 auto& hCurrent2 = m_electricalData.harmonicCurrent[1][i];
644 wxString i1, i2;
645 i1.Printf(_("\nIh(%d)(%d-%d) = %.5e%s%.2f%s p.u."), m_electricalData.harmonicOrder[i], busNumber[0], busNumber[1], std::abs(hCurrent1), wxString(L'\u2220'), wxRadToDeg(std::arg(hCurrent1)), wxString(L'\u00B0'));
646 i2.Printf(_("\nIh(%d)(%d-%d) = %.5e%s%.2f%s p.u."), m_electricalData.harmonicOrder[i], busNumber[1], busNumber[0], std::abs(hCurrent2), wxString(L'\u2220'), wxRadToDeg(std::arg(hCurrent2)), wxString(L'\u00B0'));
647
648 tipText += i1 + i2;
649 i++;
650 }
651 }
652 }
653
654 return tipText;
655}
656
657TransformerElectricalData Transformer::GetPUElectricalData(double systemBasePower)
658{
659 TransformerElectricalData data = m_electricalData;
660 double transformerBasePower = GetValueFromUnit(data.nominalPower, data.nominalPowerUnit);
661 double baseVoltage = 0.0;
662 if (data.baseVoltage == 0) {
663 baseVoltage = GetValueFromUnit(data.primaryNominalVoltage, data.primaryNominalVoltageUnit);
664 }
665 else {
666 baseVoltage = GetValueFromUnit(data.secondaryNominalVoltage, data.secondaryNominalVoltageUnit);
667 }
668 double systemBaseImpedance = (baseVoltage * baseVoltage) / systemBasePower;
669 double transformerBaseImpedance = (baseVoltage * baseVoltage) / transformerBasePower;
670
671 // Resistance
672 double r = data.resistance;
673 if (data.resistanceUnit == ElectricalUnit::UNIT_PU) {
674 if (data.useTransformerPower) data.resistance = (r * transformerBaseImpedance) / systemBaseImpedance;
675 }
676 else {
677 data.resistance = r / systemBaseImpedance;
678 }
679 data.resistanceUnit = ElectricalUnit::UNIT_PU;
680
681 // Indutive reactance
682 double x = data.indReactance;
683 if (data.indReactanceUnit == ElectricalUnit::UNIT_PU) {
684 if (data.useTransformerPower) data.indReactance = (x * transformerBaseImpedance) / systemBaseImpedance;
685 }
686 else {
687 data.indReactance = x / systemBaseImpedance;
688 }
689 data.indReactanceUnit = ElectricalUnit::UNIT_PU;
690
691 // Fault
692
693 // Zero seq. resistance
694 double r0 = data.zeroResistance;
695 if (data.useTransformerPower) data.zeroResistance = (r0 * transformerBaseImpedance) / systemBaseImpedance;
696
697 // Zero seq. ind. reactance
698 double x0 = data.zeroIndReactance;
699 if (data.useTransformerPower) data.zeroIndReactance = (x0 * transformerBaseImpedance) / systemBaseImpedance;
700
701 // Primary ground resistance
702 double rgp = data.primaryGrndResistance;
703 if (data.useTransformerPower) data.primaryGrndResistance = (rgp * transformerBaseImpedance) / systemBaseImpedance;
704
705 // Primary ground ind reactance
706 double xgp = data.primaryGrndReactance;
707 if (data.useTransformerPower) data.primaryGrndReactance = (xgp * transformerBaseImpedance) / systemBaseImpedance;
708
709 // Secondary ground resistance
710 double rgs = data.secondaryGrndResistance;
711 if (data.useTransformerPower) data.secondaryGrndResistance = (rgs * transformerBaseImpedance) / systemBaseImpedance;
712
713 // Secondary ground ind reactance
714 double xgs = data.secondaryGrndReactance;
715 if (data.useTransformerPower) data.secondaryGrndReactance = (xgs * transformerBaseImpedance) / systemBaseImpedance;
716
717 if (!m_online) {
718 data.powerFlow[0] = std::complex<double>(0, 0);
719 data.powerFlow[1] = std::complex<double>(0, 0);
720 data.faultCurrent[0][0] = std::complex<double>(0, 0);
721 data.faultCurrent[0][1] = std::complex<double>(0, 0);
722 data.faultCurrent[0][2] = std::complex<double>(0, 0);
723 data.faultCurrent[1][0] = std::complex<double>(0, 0);
724 data.faultCurrent[1][1] = std::complex<double>(0, 0);
725 data.faultCurrent[1][2] = std::complex<double>(0, 0);
726 }
727
728 return data;
729}
730
731rapidxml::xml_node<>* Transformer::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
732{
733 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "Transfomer");
734 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
735 auto cadProp = XMLParser::AppendNode(doc, elementNode, "CADProperties");
736 auto position = XMLParser::AppendNode(doc, cadProp, "Position");
737 auto posX = XMLParser::AppendNode(doc, position, "X");
738 XMLParser::SetNodeValue(doc, posX, m_position.m_x);
739 auto posY = XMLParser::AppendNode(doc, position, "Y");
740 XMLParser::SetNodeValue(doc, posY, m_position.m_y);
741 auto size = XMLParser::AppendNode(doc, cadProp, "Size");
742 auto width = XMLParser::AppendNode(doc, size, "Width");
743 XMLParser::SetNodeValue(doc, width, m_width);
744 auto height = XMLParser::AppendNode(doc, size, "Height");
745 XMLParser::SetNodeValue(doc, height, m_height);
746 auto angle = XMLParser::AppendNode(doc, cadProp, "Angle");
747 XMLParser::SetNodeValue(doc, angle, m_angle);
748 auto nodeList = XMLParser::AppendNode(doc, cadProp, "NodeList");
749 auto nodePos1 = XMLParser::AppendNode(doc, nodeList, "Node");
750 XMLParser::SetNodeAttribute(doc, nodePos1, "ID", 0);
751 auto nodePosX1 = XMLParser::AppendNode(doc, nodePos1, "X");
752 XMLParser::SetNodeValue(doc, nodePosX1, m_pointList[0].m_x);
753 auto nodePosY1 = XMLParser::AppendNode(doc, nodePos1, "Y");
754 XMLParser::SetNodeValue(doc, nodePosY1, m_pointList[0].m_y);
755 auto nodePos2 = XMLParser::AppendNode(doc, nodeList, "Node");
756 XMLParser::SetNodeAttribute(doc, nodePos2, "ID", 1);
757 auto nodePosX2 = XMLParser::AppendNode(doc, nodePos2, "X");
758 XMLParser::SetNodeValue(doc, nodePosX2, m_pointList[m_pointList.size() - 1].m_x);
759 auto nodePosY2 = XMLParser::AppendNode(doc, nodePos2, "Y");
760 XMLParser::SetNodeValue(doc, nodePosY2, m_pointList[m_pointList.size() - 1].m_y);
761
762 auto parentIDList = XMLParser::AppendNode(doc, cadProp, "ParentIDList");
763 for (unsigned int i = 0; i < m_parentList.size(); i++) {
764 Element* parent = m_parentList[i];
765 if (parent) {
766 auto parentID = XMLParser::AppendNode(doc, parentIDList, "ParentID");
767 XMLParser::SetNodeAttribute(doc, parentID, "ID", static_cast<int>(i));
768 XMLParser::SetNodeValue(doc, parentID, parent->GetID());
769 }
770 }
771
772 auto electricalProp = XMLParser::AppendNode(doc, elementNode, "ElectricalProperties");
773 auto isOnline = XMLParser::AppendNode(doc, electricalProp, "IsOnline");
774 XMLParser::SetNodeValue(doc, isOnline, m_online);
775 auto name = XMLParser::AppendNode(doc, electricalProp, "Name");
776 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
777 auto primaryNominalVoltage = XMLParser::AppendNode(doc, electricalProp, "PrimaryNominalVoltage");
778 XMLParser::SetNodeValue(doc, primaryNominalVoltage, m_electricalData.primaryNominalVoltage);
779 XMLParser::SetNodeAttribute(doc, primaryNominalVoltage, "UnitID", static_cast<int>(m_electricalData.primaryNominalVoltageUnit));
780 auto secondaryNominalVoltage = XMLParser::AppendNode(doc, electricalProp, "SecondaryNominalVoltage");
781 XMLParser::SetNodeValue(doc, secondaryNominalVoltage, m_electricalData.secondaryNominalVoltage);
782 XMLParser::SetNodeAttribute(doc, secondaryNominalVoltage, "UnitID", static_cast<int>(m_electricalData.secondaryNominalVoltageUnit));
783 auto nominalPower = XMLParser::AppendNode(doc, electricalProp, "NominalPower");
784 XMLParser::SetNodeValue(doc, nominalPower, m_electricalData.nominalPower);
785 XMLParser::SetNodeAttribute(doc, nominalPower, "UnitID", static_cast<int>(m_electricalData.nominalPowerUnit));
786 auto resistance = XMLParser::AppendNode(doc, electricalProp, "Resistance");
787 XMLParser::SetNodeValue(doc, resistance, m_electricalData.resistance);
788 XMLParser::SetNodeAttribute(doc, resistance, "UnitID", static_cast<int>(m_electricalData.resistanceUnit));
789 auto indReactance = XMLParser::AppendNode(doc, electricalProp, "IndReactance");
790 XMLParser::SetNodeValue(doc, indReactance, m_electricalData.indReactance);
791 XMLParser::SetNodeAttribute(doc, indReactance, "UnitID", static_cast<int>(m_electricalData.indReactanceUnit));
792 auto connection = XMLParser::AppendNode(doc, electricalProp, "Connection");
793 XMLParser::SetNodeValue(doc, connection, m_electricalData.connection);
794 auto turnsRatio = XMLParser::AppendNode(doc, electricalProp, "TurnsRatio");
795 XMLParser::SetNodeValue(doc, turnsRatio, m_electricalData.turnsRatio);
796 auto phaseShift = XMLParser::AppendNode(doc, electricalProp, "PhaseShift");
797 XMLParser::SetNodeValue(doc, phaseShift, m_electricalData.phaseShift);
798 auto useTransformerPower = XMLParser::AppendNode(doc, electricalProp, "UseTransfomerPower");
799 XMLParser::SetNodeValue(doc, useTransformerPower, m_electricalData.useTransformerPower);
800
801 auto fault = XMLParser::AppendNode(doc, electricalProp, "Fault");
802 auto zeroResistance = XMLParser::AppendNode(doc, fault, "ZeroResistance");
803 XMLParser::SetNodeValue(doc, zeroResistance, m_electricalData.zeroResistance);
804 auto zeroIndReactance = XMLParser::AppendNode(doc, fault, "ZeroIndReactance");
805 XMLParser::SetNodeValue(doc, zeroIndReactance, m_electricalData.zeroIndReactance);
806 auto primaryGrndResistance = XMLParser::AppendNode(doc, fault, "PrimaryGrndResistance");
807 XMLParser::SetNodeValue(doc, primaryGrndResistance, m_electricalData.primaryGrndResistance);
808 auto primaryGrndReactance = XMLParser::AppendNode(doc, fault, "PrimaryGrndReactance");
809 XMLParser::SetNodeValue(doc, primaryGrndReactance, m_electricalData.primaryGrndReactance);
810 auto secondaryGrndResistance = XMLParser::AppendNode(doc, fault, "SecondaryGrndResistance");
811 XMLParser::SetNodeValue(doc, secondaryGrndResistance, m_electricalData.secondaryGrndResistance);
812 auto secondaryGrndReactance = XMLParser::AppendNode(doc, fault, "SecondaryGrndReactance");
813 XMLParser::SetNodeValue(doc, secondaryGrndReactance, m_electricalData.secondaryGrndReactance);
814
815 SaveSwitchingData(doc, electricalProp);
816
817 return elementNode;
818}
819
820bool Transformer::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
821{
822 auto cadPropNode = elementNode->first_node("CADProperties");
823 if (!cadPropNode) return false;
824
825 auto position = cadPropNode->first_node("Position");
826 double posX = XMLParser::GetNodeValueDouble(position, "X");
827 double posY = XMLParser::GetNodeValueDouble(position, "Y");
828 auto size = cadPropNode->first_node("Size");
829 m_width = XMLParser::GetNodeValueDouble(size, "Width");
830 m_height = XMLParser::GetNodeValueDouble(size, "Height");
831 double angle = XMLParser::GetNodeValueDouble(cadPropNode, "Angle");
832
833 // Get nodes points
834 std::vector<wxPoint2DDouble> ptsList;
835 auto nodePosList = cadPropNode->first_node("NodeList");
836 if (!nodePosList) return false;
837 auto nodePos = nodePosList->first_node("Node");
838 while (nodePos) {
839 double nodePosX = XMLParser::GetNodeValueDouble(nodePos, "X");
840 double nodePosY = XMLParser::GetNodeValueDouble(nodePos, "Y");
841 ptsList.push_back(wxPoint2DDouble(nodePosX, nodePosY));
842 nodePos = nodePos->next_sibling("Node");
843 }
844
845 // Get parents IDs
846 auto parentIDList = cadPropNode->first_node("ParentIDList");
847 if (!parentIDList) return false;
848 auto parentNode = parentIDList->first_node("ParentID");
849 long parentID[2] = { -1, -1 };
850 while (parentNode) {
851 long index = 0;
852 wxString(parentNode->first_attribute("ID")->value()).ToLong(&index);
853 wxString(parentNode->value()).ToCLong(&parentID[index]);
854 parentNode = parentNode->next_sibling("ParentID");
855 }
856
857 std::vector<wxPoint2DDouble> nodePtsList; // List of node points
858 nodePtsList.push_back(ptsList[0]); // First point on the list
859 nodePtsList.push_back(ptsList[ptsList.size() - 1]); // Last point on the list
860
861 // List of dummy buses to set not connected nodes properly
862 std::vector<Bus*> dummyBusList;
863 // Set parents (if have)
864 for (unsigned int i = 0; i < 2; ++i) {
865 if (parentID[i] == -1) // No parent connected
866 {
867 Bus* dummyBus = new Bus(nodePtsList[i]);
868 dummyBusList.push_back(dummyBus);
869 AddParent(dummyBus, nodePtsList[i]);
870 }
871 else { // Parent connected (necessarily a bus, get from bus list)
872 AddParent(parentList[parentID[i]], nodePtsList[i]);
873 }
874 }
875
876 StartMove(m_position);
877 Move(wxPoint2DDouble(posX, posY));
878
879 // Remove dummy buses
880 for (auto it = dummyBusList.begin(), itEnd = dummyBusList.end(); it != itEnd; ++it) {
881 RemoveParent(*it);
882 delete* it;
883 }
884 dummyBusList.clear();
885
886 // Set rotation properly.
887 int numRot = angle / GetRotationAngle();
888 bool clockwise = true;
889 if (numRot < 0) {
890 numRot = std::abs(numRot);
891 clockwise = false;
892 }
893 for (int i = 0; i < numRot; i++) Rotate(clockwise);
894
895 auto electricalProp = elementNode->first_node("ElectricalProperties");
896 if (!electricalProp) return false;
897
898 SetOnline(XMLParser::GetNodeValueInt(electricalProp, "IsOnline"));
899 m_electricalData.name = electricalProp->first_node("Name")->value();
900 m_electricalData.primaryNominalVoltage = XMLParser::GetNodeValueDouble(electricalProp, "PrimaryNominalVoltage");
901 m_electricalData.primaryNominalVoltageUnit =
902 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp, "PrimaryNominalVoltage", "UnitID"));
903 m_electricalData.secondaryNominalVoltage = XMLParser::GetNodeValueDouble(electricalProp, "SecondaryNominalVoltage");
904 m_electricalData.secondaryNominalVoltageUnit = static_cast<ElectricalUnit>(
905 XMLParser::GetAttributeValueInt(electricalProp, "SecondaryNominalVoltage", "UnitID"));
906 m_electricalData.nominalPower = XMLParser::GetNodeValueDouble(electricalProp, "NominalPower");
907 m_electricalData.nominalPowerUnit =
908 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp, "NominalPower", "UnitID"));
909 m_electricalData.resistance = XMLParser::GetNodeValueDouble(electricalProp, "Resistance");
910 m_electricalData.resistanceUnit =
911 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp, "Resistance", "UnitID"));
912 m_electricalData.indReactance = XMLParser::GetNodeValueDouble(electricalProp, "IndReactance");
913 m_electricalData.indReactanceUnit =
914 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp, "IndReactance", "UnitID"));
915 m_electricalData.connection = (TransformerConnection)XMLParser::GetNodeValueInt(electricalProp, "Connection");
916 m_electricalData.turnsRatio = XMLParser::GetNodeValueDouble(electricalProp, "TurnsRatio");
917 m_electricalData.phaseShift = XMLParser::GetNodeValueDouble(electricalProp, "PhaseShift");
918 m_electricalData.useTransformerPower = XMLParser::GetNodeValueInt(electricalProp, "UseTransfomerPower");
919
920 auto fault = electricalProp->first_node("Fault");
921 m_electricalData.zeroResistance = XMLParser::GetNodeValueDouble(fault, "ZeroResistance");
922 m_electricalData.zeroIndReactance = XMLParser::GetNodeValueDouble(fault, "ZeroIndReactance");
923 m_electricalData.primaryGrndResistance = XMLParser::GetNodeValueDouble(fault, "PrimaryGrndResistance");
924 m_electricalData.primaryGrndReactance = XMLParser::GetNodeValueDouble(fault, "PrimaryGrndReactance");
925 m_electricalData.secondaryGrndResistance = XMLParser::GetNodeValueDouble(fault, "SecondaryGrndResistance");
926 m_electricalData.secondaryGrndReactance = XMLParser::GetNodeValueDouble(fault, "SecondaryGrndReactance");
927
928 if (!OpenSwitchingData(electricalProp)) return false;
929 if (m_swData.swTime.size() != 0) SetDynamicEvent(true);
930
931 return true;
932}
933
934void Transformer::SetBestPositionAndRotation()
935{
936 wxPoint2DDouble p1 = m_pointList[0];
937 wxPoint2DDouble p2 = m_pointList[m_pointList.size() - 1];
938 wxPoint2DDouble mid = (p1 + p2) / 2.0;
939 StartMove(m_position);
940 Move(mid);
941 double bestAngle = wxRadToDeg(std::atan2(p2.m_y - p1.m_y, p2.m_x - p1.m_x));
942 bool clockwise = bestAngle > 0 ? true : false;
943 while (std::abs(m_angle) < std::abs(bestAngle)) { Rotate(clockwise); }
944}
@ ID_EDIT_ELEMENT
Definition Element.h:75
ElectricalUnit
Electrical units.
PowerFlowDirection
Direction of power flow arrows.
Abstract class for branch power elements.
Definition Branch.h:32
virtual void UpdateSwitches()
Update the switch position.
Definition Branch.cpp:179
virtual void RemoveParent(Element *parent)
Remove a parent.
Definition Branch.cpp:105
Node for power elements. All others power elements are connected through this.
Definition Bus.h:86
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 bool Intersects(wxRect2DDouble rect) const =0
Check if the element's rect intersects other rect.
virtual int GetID() const
Get the element ID.
Definition Element.h:271
virtual void GeneralMenuItens(wxMenu &menu)
Insert general itens to context menu.
Definition Element.cpp:457
double GetRotationAngle() const
Get the angle of rotation.
Definition Element.h:216
wxPoint2DDouble GetPosition() const
Get the element position.
Definition Element.h:186
double GetAngle() const
Get the element angle.
Definition Element.h:211
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 AddChild(Element *child)
Add a child to the child list.
Definition Element.cpp:566
static wxString StringFromDouble(double value, int minDecimal=1, int maxDecimals=13)
Convert a double value to string.
Definition Element.cpp:533
bool SetOnline(bool online=true)
Set if the element is online or offline.
Definition Element.cpp:447
virtual void DrawDCCircle(wxPoint2DDouble position, double radius, int numSegments, wxGraphicsContext *gc) const
Draw a circle using device context.
Definition Element.cpp:177
virtual void SetDynamicEvent(bool dynEvent=true)
Set if the power element have dynamic event.
virtual void CalculatePowerFlowPts(std::vector< wxPoint2DDouble > edges)
Calculate the points of the power flow arrows.
virtual void DrawDCSwitches(wxGraphicsContext *gc) const
Draw switch.
virtual void DrawDCPowerFlowPts(wxGraphicsContext *gc) const
Draw power flow arrows.
virtual wxPoint2DDouble GetSwitchPoint(Element *parent, wxPoint2DDouble parentPoint, wxPoint2DDouble secondPoint) const
Get the correct switch position.
Form to edit the transformer power data.
Two-winding transformer power element.
Definition Transformer.h:84
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
virtual wxString GetTipText() const
Get the tip text.
virtual Element * GetCopy()
Get a the element copy.
virtual bool Contains(wxPoint2DDouble position) const
Checks if the element contains a position.
virtual void SetPowerFlowDirection(PowerFlowDirection pfDirection)
Set the direction of the power flow.
virtual bool Intersects(wxRect2DDouble rect) const
Check if the element's rect intersects other rect.
virtual bool SetNodeParent(Element *parent)
Set a perent to the node. If all conditions are met, a new parent are added to the element and the po...
virtual void Move(wxPoint2DDouble position)
Move the element other position.
virtual void SetNominalVoltage(std::vector< double > nominalVoltage, std::vector< ElectricalUnit > nominalVoltageUnit)
Set nominal voltage of the element.
virtual void MoveNode(Element *parent, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.
virtual void RotateNode(Element *parent, bool clockwise)
Rotate a node.
virtual bool GetContextMenu(wxMenu &menu)
Get the element contex menu.
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,...
std::vector< double > swTime