19#include "../../forms/TransformerForm.h"
21Transformer::Transformer() :
Branch()
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); }
28Transformer::Transformer(wxString name) :
Branch()
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); }
34 m_electricalData.name = name;
36Transformer::~Transformer() {}
42 if (m_parentList.size() == 0) {
43 m_position = position;
44 m_parentList.push_back(parent);
46 wxPoint2DDouble parentPt =
50 m_pointList.push_back(parentPt);
51 m_pointList.push_back(
GetSwitchPoint(parent, parentPt, m_position));
53 wxRect2DDouble genRect(0, 0, 0, 0);
54 m_switchRect.push_back(genRect);
59 else if (parent != m_parentList[0]) {
60 m_parentList.push_back(parent);
62 wxPoint2DDouble parentPt =
69 wxPoint2DDouble((m_pointList[0].m_x + parentPt.m_x) / 2.0, (m_pointList[0].m_y + parentPt.m_y) / 2.0);
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)));
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);
86 m_pointList.push_back(
GetSwitchPoint(parent, parentPt, m_pointList[m_pointList.size() - 1]));
88 m_pointList.push_back(parentPt);
91 wxRect2DDouble genRect(0, 0, 0, 0);
92 m_switchRect.push_back(genRect);
94 UpdatePowerFlowArrowsPosition();
105 return m_rect.Contains(ptR);
188 wxColour elementColour;
191 elementColour = m_dynamicEventColour;
193 elementColour = m_onlineElementColour;
196 elementColour = m_offlineElementColour;
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]);
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);
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);
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); }
230 gc->SetPen(wxPen(elementColour, 2));
231 gc->SetBrush(*wxTRANSPARENT_BRUSH);
232 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
235 gc->SetPen(*wxTRANSPARENT_PEN);
236 gc->SetBrush(wxBrush(elementColour));
237 if (m_pointList.size() > 0) {
239 if (m_inserted) {
DrawDCCircle(m_pointList[m_pointList.size() - 1], 5.0, 10, gc); }
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);
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);
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);
264 gc->SetPen(*wxTRANSPARENT_PEN);
265 gc->SetBrush(wxBrush(elementColour));
274 wxColour elementColour;
277 elementColour = m_dynamicEventColour;
279 elementColour = m_onlineElementColour;
282 elementColour = m_offlineElementColour;
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)); }
290 dc.SetPen(wxPen(wxColour(m_selectionColour), 2 + m_borderSize * 2.0));
291 dc.SetBrush(*wxTRANSPARENT_BRUSH);
292 dc.DrawLines(pointList.size(), &pointList[0]);
294 dc.SetPen(*wxTRANSPARENT_PEN);
295 dc.SetBrush(wxBrush(m_selectionColour));
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);
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); }
312 dc.SetPen(wxPen(elementColour, 2));
313 dc.SetBrush(*wxTRANSPARENT_BRUSH);
314 dc.DrawLines(pointList.size(), &pointList[0]);
317 dc.SetPen(*wxTRANSPARENT_PEN);
318 dc.SetBrush(wxBrush(elementColour));
319 if (pointList.size() > 0) {
321 if (m_inserted) {
DrawDCCircle(pointList[pointList.size() - 1], 5.0, dc); }
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);
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);
338 dc.SetPen(*wxTRANSPARENT_PEN);
339 dc.SetBrush(wxBrush(elementColour));
340 DrawDCCircle(m_position + RotateLocal(wxPoint2DDouble(-35, -20), m_angle), 4, dc);
346 if (m_angle == 0.0 || m_angle == 180.0)
return m_rect.Intersects(rect);
352 double rotAngle = m_rotationAngle;
353 if (!clockwise) rotAngle = -m_rotationAngle;
356 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
359 for (
int i = 2; i < (int)m_pointList.size() - 2; i++) {
362 UpdateSwitchesPosition();
363 UpdatePowerFlowArrowsPosition();
371 for (
int i = 2; i < (int)m_pointList.size() - 2; i++) { m_pointList[i] = m_movePts[i] + position - m_moveStartPt; }
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;
378 UpdateSwitchesPosition();
379 UpdatePowerFlowArrowsPosition();
386 if (parent == m_parentList[0]) {
387 m_pointList[0] = m_movePts[0] + position - m_moveStartPt;
390 else if (parent == m_parentList[1]) {
391 m_pointList[m_pointList.size() - 1] = m_movePts[m_pointList.size() - 1] + position - m_moveStartPt;
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;
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;
414 UpdateSwitchesPosition();
415 UpdatePowerFlowArrowsPosition();
420 m_moveStartPt = position;
421 m_movePts = m_pointList;
422 m_movePos = m_position;
429 wxString busName[2] = {
"?",
"?" };
430 if (m_parentList.size() == 2) {
432 for (
Element* element : m_parentList) {
434 Bus* bus =
static_cast<Bus*
>(element);
435 busName[i] = bus->GetElectricalData().name;
441 wxMenu* textMenu =
new wxMenu();
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"));
463 transfForm.CenterOnParent();
464 if (transfForm.ShowModal() == wxID_OK) {
472 if (nominalVoltage.size() == 1) {
473 m_electricalData.primaryNominalVoltage = nominalVoltage[0];
474 m_electricalData.primaryNominalVoltageUnit = nominalVoltageUnit[0];
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];
484void Transformer::UpdatePowerFlowArrowsPosition()
486 std::vector<wxPoint2DDouble> edges;
487 switch (m_pfDirection) {
489 m_powerFlowArrow.clear();
492 for (
int i = 1; i < (int)m_pointList.size() - 1; i++) { edges.push_back(m_pointList[i]); }
495 for (
int i = (
int)m_pointList.size() - 2; i > 0; i--) { edges.push_back(m_pointList[i]); }
505 double rotAngle = m_rotationAngle;
506 if (!clockwise) rotAngle = -m_rotationAngle;
508 if (parent == m_parentList[0]) {
511 else if (parent == m_parentList[1]) {
512 m_pointList[m_pointList.size() - 1] = parent->
RotateAtPosition(m_pointList[m_pointList.size() - 1], rotAngle);
514 UpdateSwitchesPosition();
515 UpdatePowerFlowArrowsPosition();
520 if (m_activeNodeID == 1 && parent == m_parentList[0])
return false;
521 if (m_activeNodeID == 2 && parent == m_parentList[1])
return false;
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);
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);
536 if (m_activeNodeID == 1) {
538 if (m_parentList[1] == parent) {
543 m_parentList[0] = parent;
547 m_pointList[0], -parent->
GetAngle());
550 m_pointList[0] = parentPt;
552 UpdateSwitchesPosition();
553 UpdatePowerFlowArrowsPosition();
556 if (m_activeNodeID == 2) {
557 if (m_parentList[0] == parent) {
562 m_parentList[1] = parent;
564 wxPoint2DDouble parentPt =
568 m_pointList[m_pointList.size() - 1] = parentPt;
570 UpdateSwitchesPosition();
571 UpdatePowerFlowArrowsPosition();
576 if (m_activeNodeID == 1) m_parentList[0] =
nullptr;
577 if (m_activeNodeID == 2) m_parentList[1] =
nullptr;
585 m_pfDirection = pfDirection;
586 UpdatePowerFlowArrowsPosition();
598 wxString tipText = m_electricalData.name;
599 wxString primVoltage =
StringFromDouble(m_electricalData.primaryNominalVoltage);
600 switch (m_electricalData.primaryNominalVoltageUnit) {
602 primVoltage += _(
" V");
605 primVoltage += _(
" kV");
610 wxString secVoltage =
StringFromDouble(m_electricalData.secondaryNominalVoltage);
611 switch (m_electricalData.secondaryNominalVoltageUnit) {
613 secVoltage += _(
" V");
616 secVoltage += _(
" kV");
622 tipText +=
"\n" + primVoltage +
" / " + secVoltage;
627 busNumber[0] =
static_cast<Bus*
>(m_parentList[0])->GetElectricalData().number + 1;
628 busNumber[1] =
static_cast<Bus*
>(m_parentList[1])->GetElectricalData().number + 1;
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.");
639 if (!m_electricalData.harmonicOrder.empty()) {
640 tipText += _(
"\n\nHarmonic currents:");
642 for (
auto& hCurrent1 : m_electricalData.harmonicCurrent[0]) {
643 auto& hCurrent2 = m_electricalData.harmonicCurrent[1][i];
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'));
661 data.nominalPower = m_electricalData.nominalPower;
662 data.nominalPowerUnit = m_electricalData.nominalPowerUnit;
664 data.primaryNominalVoltage = m_electricalData.primaryNominalVoltage;
665 data.primaryNominalVoltageUnit =
666 m_electricalData.primaryNominalVoltageUnit;
668 data.secondaryNominalVoltage =
669 m_electricalData.secondaryNominalVoltage;
670 data.secondaryNominalVoltageUnit =
671 m_electricalData.secondaryNominalVoltageUnit;
673 data.useTransformerPower =
674 m_electricalData.useTransformerPower;
676 data.baseVoltage = m_electricalData.baseVoltage;
678 data.resistance = m_electricalData.resistance;
679 data.resistanceUnit = m_electricalData.resistanceUnit;
681 data.indReactance = m_electricalData.indReactance;
682 data.indReactanceUnit = m_electricalData.indReactanceUnit;
684 data.zeroResistance = m_electricalData.zeroResistance;
685 data.zeroIndReactance = m_electricalData.zeroIndReactance;
687 data.primaryGrndResistance =
688 m_electricalData.primaryGrndResistance;
689 data.primaryGrndReactance =
690 m_electricalData.primaryGrndReactance;
692 data.secondaryGrndResistance =
693 m_electricalData.secondaryGrndResistance;
694 data.secondaryGrndReactance =
695 m_electricalData.secondaryGrndReactance;
697 data.powerFlow[0] = m_electricalData.powerFlow[0];
698 data.powerFlow[1] = m_electricalData.powerFlow[1];
700 double transformerBasePower = GetValueFromUnit(data.nominalPower, data.nominalPowerUnit);
701 double baseVoltage = 0.0;
702 if (data.baseVoltage == 0) {
703 baseVoltage = GetValueFromUnit(data.primaryNominalVoltage, data.primaryNominalVoltageUnit);
706 baseVoltage = GetValueFromUnit(data.secondaryNominalVoltage, data.secondaryNominalVoltageUnit);
708 double systemBaseImpedance = (baseVoltage * baseVoltage) / systemBasePower;
709 double transformerBaseImpedance = (baseVoltage * baseVoltage) / transformerBasePower;
712 double r = data.resistance;
714 if (data.useTransformerPower) data.resistance = (r * transformerBaseImpedance) / systemBaseImpedance;
717 data.resistance = r / systemBaseImpedance;
722 double x = data.indReactance;
724 if (data.useTransformerPower) data.indReactance = (x * transformerBaseImpedance) / systemBaseImpedance;
727 data.indReactance = x / systemBaseImpedance;
734 double r0 = data.zeroResistance;
735 if (data.useTransformerPower) data.zeroResistance = (r0 * transformerBaseImpedance) / systemBaseImpedance;
738 double x0 = data.zeroIndReactance;
739 if (data.useTransformerPower) data.zeroIndReactance = (x0 * transformerBaseImpedance) / systemBaseImpedance;
742 double rgp = data.primaryGrndResistance;
743 if (data.useTransformerPower) data.primaryGrndResistance = (rgp * transformerBaseImpedance) / systemBaseImpedance;
746 double xgp = data.primaryGrndReactance;
747 if (data.useTransformerPower) data.primaryGrndReactance = (xgp * transformerBaseImpedance) / systemBaseImpedance;
750 double rgs = data.secondaryGrndResistance;
751 if (data.useTransformerPower) data.secondaryGrndResistance = (rgs * transformerBaseImpedance) / systemBaseImpedance;
754 double xgs = data.secondaryGrndReactance;
755 if (data.useTransformerPower) data.secondaryGrndReactance = (xgs * transformerBaseImpedance) / systemBaseImpedance;
758 data.powerFlow[0] = std::complex<double>(0, 0);
759 data.powerFlow[1] = std::complex<double>(0, 0);
760 data.faultCurrent[0][0] = std::complex<double>(0, 0);
761 data.faultCurrent[0][1] = std::complex<double>(0, 0);
762 data.faultCurrent[0][2] = std::complex<double>(0, 0);
763 data.faultCurrent[1][0] = std::complex<double>(0, 0);
764 data.faultCurrent[1][1] = std::complex<double>(0, 0);
765 data.faultCurrent[1][2] = std::complex<double>(0, 0);
771rapidxml::xml_node<>* Transformer::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
773 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Transfomer");
774 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
775 auto cadProp = XMLParser::AppendNode(doc, elementNode,
"CADProperties");
776 auto position = XMLParser::AppendNode(doc, cadProp,
"Position");
777 auto posX = XMLParser::AppendNode(doc, position,
"X");
778 XMLParser::SetNodeValue(doc, posX, m_position.m_x);
779 auto posY = XMLParser::AppendNode(doc, position,
"Y");
780 XMLParser::SetNodeValue(doc, posY, m_position.m_y);
781 auto size = XMLParser::AppendNode(doc, cadProp,
"Size");
782 auto width = XMLParser::AppendNode(doc, size,
"Width");
783 XMLParser::SetNodeValue(doc, width, m_width);
784 auto height = XMLParser::AppendNode(doc, size,
"Height");
785 XMLParser::SetNodeValue(doc, height, m_height);
786 auto angle = XMLParser::AppendNode(doc, cadProp,
"Angle");
787 XMLParser::SetNodeValue(doc, angle, m_angle);
788 auto nodeList = XMLParser::AppendNode(doc, cadProp,
"NodeList");
789 auto nodePos1 = XMLParser::AppendNode(doc, nodeList,
"Node");
790 XMLParser::SetNodeAttribute(doc, nodePos1,
"ID", 0);
791 auto nodePosX1 = XMLParser::AppendNode(doc, nodePos1,
"X");
792 XMLParser::SetNodeValue(doc, nodePosX1, m_pointList[0].m_x);
793 auto nodePosY1 = XMLParser::AppendNode(doc, nodePos1,
"Y");
794 XMLParser::SetNodeValue(doc, nodePosY1, m_pointList[0].m_y);
795 auto nodePos2 = XMLParser::AppendNode(doc, nodeList,
"Node");
796 XMLParser::SetNodeAttribute(doc, nodePos2,
"ID", 1);
797 auto nodePosX2 = XMLParser::AppendNode(doc, nodePos2,
"X");
798 XMLParser::SetNodeValue(doc, nodePosX2, m_pointList[m_pointList.size() - 1].m_x);
799 auto nodePosY2 = XMLParser::AppendNode(doc, nodePos2,
"Y");
800 XMLParser::SetNodeValue(doc, nodePosY2, m_pointList[m_pointList.size() - 1].m_y);
802 auto parentIDList = XMLParser::AppendNode(doc, cadProp,
"ParentIDList");
803 for (
unsigned int i = 0; i < m_parentList.size(); i++) {
804 Element* parent = m_parentList[i];
806 auto parentID = XMLParser::AppendNode(doc, parentIDList,
"ParentID");
807 XMLParser::SetNodeAttribute(doc, parentID,
"ID",
static_cast<int>(i));
808 XMLParser::SetNodeValue(doc, parentID, parent->
GetID());
812 auto electricalProp = XMLParser::AppendNode(doc, elementNode,
"ElectricalProperties");
813 auto isOnline = XMLParser::AppendNode(doc, electricalProp,
"IsOnline");
814 XMLParser::SetNodeValue(doc, isOnline, m_online);
815 auto name = XMLParser::AppendNode(doc, electricalProp,
"Name");
816 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
817 auto primaryNominalVoltage = XMLParser::AppendNode(doc, electricalProp,
"PrimaryNominalVoltage");
818 XMLParser::SetNodeValue(doc, primaryNominalVoltage, m_electricalData.primaryNominalVoltage);
819 XMLParser::SetNodeAttribute(doc, primaryNominalVoltage,
"UnitID",
static_cast<int>(m_electricalData.primaryNominalVoltageUnit));
820 auto secondaryNominalVoltage = XMLParser::AppendNode(doc, electricalProp,
"SecondaryNominalVoltage");
821 XMLParser::SetNodeValue(doc, secondaryNominalVoltage, m_electricalData.secondaryNominalVoltage);
822 XMLParser::SetNodeAttribute(doc, secondaryNominalVoltage,
"UnitID",
static_cast<int>(m_electricalData.secondaryNominalVoltageUnit));
823 auto nominalPower = XMLParser::AppendNode(doc, electricalProp,
"NominalPower");
824 XMLParser::SetNodeValue(doc, nominalPower, m_electricalData.nominalPower);
825 XMLParser::SetNodeAttribute(doc, nominalPower,
"UnitID",
static_cast<int>(m_electricalData.nominalPowerUnit));
826 auto resistance = XMLParser::AppendNode(doc, electricalProp,
"Resistance");
827 XMLParser::SetNodeValue(doc, resistance, m_electricalData.resistance);
828 XMLParser::SetNodeAttribute(doc, resistance,
"UnitID",
static_cast<int>(m_electricalData.resistanceUnit));
829 auto indReactance = XMLParser::AppendNode(doc, electricalProp,
"IndReactance");
830 XMLParser::SetNodeValue(doc, indReactance, m_electricalData.indReactance);
831 XMLParser::SetNodeAttribute(doc, indReactance,
"UnitID",
static_cast<int>(m_electricalData.indReactanceUnit));
832 auto connection = XMLParser::AppendNode(doc, electricalProp,
"Connection");
833 XMLParser::SetNodeValue(doc, connection, m_electricalData.connection);
834 auto turnsRatio = XMLParser::AppendNode(doc, electricalProp,
"TurnsRatio");
835 XMLParser::SetNodeValue(doc, turnsRatio, m_electricalData.turnsRatio);
836 auto phaseShift = XMLParser::AppendNode(doc, electricalProp,
"PhaseShift");
837 XMLParser::SetNodeValue(doc, phaseShift, m_electricalData.phaseShift);
838 auto useTransformerPower = XMLParser::AppendNode(doc, electricalProp,
"UseTransfomerPower");
839 XMLParser::SetNodeValue(doc, useTransformerPower, m_electricalData.useTransformerPower);
841 auto fault = XMLParser::AppendNode(doc, electricalProp,
"Fault");
842 auto zeroResistance = XMLParser::AppendNode(doc, fault,
"ZeroResistance");
843 XMLParser::SetNodeValue(doc, zeroResistance, m_electricalData.zeroResistance);
844 auto zeroIndReactance = XMLParser::AppendNode(doc, fault,
"ZeroIndReactance");
845 XMLParser::SetNodeValue(doc, zeroIndReactance, m_electricalData.zeroIndReactance);
846 auto primaryGrndResistance = XMLParser::AppendNode(doc, fault,
"PrimaryGrndResistance");
847 XMLParser::SetNodeValue(doc, primaryGrndResistance, m_electricalData.primaryGrndResistance);
848 auto primaryGrndReactance = XMLParser::AppendNode(doc, fault,
"PrimaryGrndReactance");
849 XMLParser::SetNodeValue(doc, primaryGrndReactance, m_electricalData.primaryGrndReactance);
850 auto secondaryGrndResistance = XMLParser::AppendNode(doc, fault,
"SecondaryGrndResistance");
851 XMLParser::SetNodeValue(doc, secondaryGrndResistance, m_electricalData.secondaryGrndResistance);
852 auto secondaryGrndReactance = XMLParser::AppendNode(doc, fault,
"SecondaryGrndReactance");
853 XMLParser::SetNodeValue(doc, secondaryGrndReactance, m_electricalData.secondaryGrndReactance);
855 SaveSwitchingData(doc, electricalProp);
860bool Transformer::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
862 auto cadPropNode = elementNode->first_node(
"CADProperties");
863 if (!cadPropNode)
return false;
865 auto position = cadPropNode->first_node(
"Position");
866 double posX = XMLParser::GetNodeValueDouble(position,
"X");
867 double posY = XMLParser::GetNodeValueDouble(position,
"Y");
868 auto size = cadPropNode->first_node(
"Size");
869 m_width = XMLParser::GetNodeValueDouble(size,
"Width");
870 m_height = XMLParser::GetNodeValueDouble(size,
"Height");
871 double angle = XMLParser::GetNodeValueDouble(cadPropNode,
"Angle");
874 std::vector<wxPoint2DDouble> ptsList;
875 auto nodePosList = cadPropNode->first_node(
"NodeList");
876 if (!nodePosList)
return false;
877 auto nodePos = nodePosList->first_node(
"Node");
879 double nodePosX = XMLParser::GetNodeValueDouble(nodePos,
"X");
880 double nodePosY = XMLParser::GetNodeValueDouble(nodePos,
"Y");
881 ptsList.push_back(wxPoint2DDouble(nodePosX, nodePosY));
882 nodePos = nodePos->next_sibling(
"Node");
886 auto parentIDList = cadPropNode->first_node(
"ParentIDList");
887 if (!parentIDList)
return false;
888 auto parentNode = parentIDList->first_node(
"ParentID");
889 long parentID[2] = { -1, -1 };
892 wxString(parentNode->first_attribute(
"ID")->value()).ToLong(&index);
893 wxString(parentNode->value()).ToCLong(&parentID[index]);
894 parentNode = parentNode->next_sibling(
"ParentID");
897 std::vector<wxPoint2DDouble> nodePtsList;
898 nodePtsList.push_back(ptsList[0]);
899 nodePtsList.push_back(ptsList[ptsList.size() - 1]);
902 std::vector<Bus*> dummyBusList;
904 for (
unsigned int i = 0; i < 2; ++i) {
905 if (parentID[i] == -1)
907 Bus* dummyBus =
new Bus(nodePtsList[i]);
908 dummyBusList.push_back(dummyBus);
912 AddParent(parentList[parentID[i]], nodePtsList[i]);
917 Move(wxPoint2DDouble(posX, posY));
920 for (
auto it = dummyBusList.begin(), itEnd = dummyBusList.end(); it != itEnd; ++it) {
924 dummyBusList.clear();
928 bool clockwise =
true;
930 numRot = std::abs(numRot);
933 for (
int i = 0; i < numRot; i++)
Rotate(clockwise);
935 auto electricalProp = elementNode->first_node(
"ElectricalProperties");
936 if (!electricalProp)
return false;
938 SetOnline(XMLParser::GetNodeValueInt(electricalProp,
"IsOnline"));
939 m_electricalData.name = electricalProp->first_node(
"Name")->value();
940 m_electricalData.primaryNominalVoltage = XMLParser::GetNodeValueDouble(electricalProp,
"PrimaryNominalVoltage");
941 m_electricalData.primaryNominalVoltageUnit =
942 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"PrimaryNominalVoltage",
"UnitID"));
943 m_electricalData.secondaryNominalVoltage = XMLParser::GetNodeValueDouble(electricalProp,
"SecondaryNominalVoltage");
944 m_electricalData.secondaryNominalVoltageUnit =
static_cast<ElectricalUnit>(
945 XMLParser::GetAttributeValueInt(electricalProp,
"SecondaryNominalVoltage",
"UnitID"));
946 m_electricalData.nominalPower = XMLParser::GetNodeValueDouble(electricalProp,
"NominalPower");
947 m_electricalData.nominalPowerUnit =
948 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"NominalPower",
"UnitID"));
949 m_electricalData.resistance = XMLParser::GetNodeValueDouble(electricalProp,
"Resistance");
950 m_electricalData.resistanceUnit =
951 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"Resistance",
"UnitID"));
952 m_electricalData.indReactance = XMLParser::GetNodeValueDouble(electricalProp,
"IndReactance");
953 m_electricalData.indReactanceUnit =
954 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"IndReactance",
"UnitID"));
955 m_electricalData.connection = (TransformerConnection)XMLParser::GetNodeValueInt(electricalProp,
"Connection");
956 m_electricalData.turnsRatio = XMLParser::GetNodeValueDouble(electricalProp,
"TurnsRatio");
957 m_electricalData.phaseShift = XMLParser::GetNodeValueDouble(electricalProp,
"PhaseShift");
958 m_electricalData.useTransformerPower = XMLParser::GetNodeValueInt(electricalProp,
"UseTransfomerPower");
960 auto fault = electricalProp->first_node(
"Fault");
961 m_electricalData.zeroResistance = XMLParser::GetNodeValueDouble(fault,
"ZeroResistance");
962 m_electricalData.zeroIndReactance = XMLParser::GetNodeValueDouble(fault,
"ZeroIndReactance");
963 m_electricalData.primaryGrndResistance = XMLParser::GetNodeValueDouble(fault,
"PrimaryGrndResistance");
964 m_electricalData.primaryGrndReactance = XMLParser::GetNodeValueDouble(fault,
"PrimaryGrndReactance");
965 m_electricalData.secondaryGrndResistance = XMLParser::GetNodeValueDouble(fault,
"SecondaryGrndResistance");
966 m_electricalData.secondaryGrndReactance = XMLParser::GetNodeValueDouble(fault,
"SecondaryGrndReactance");
968 if (!OpenSwitchingData(electricalProp))
return false;
974void Transformer::SetBestPositionAndRotation()
976 wxPoint2DDouble p1 = m_pointList[0];
977 wxPoint2DDouble p2 = m_pointList[m_pointList.size() - 1];
978 wxPoint2DDouble mid = (p1 + p2) / 2.0;
981 double bestAngle = wxRadToDeg(std::atan2(p2.m_y - p1.m_y, p2.m_x - p1.m_x));
982 bool clockwise = bestAngle > 0 ? true :
false;
983 while (std::abs(m_angle) < std::abs(bestAngle)) {
Rotate(clockwise); }
ElectricalUnit
Electrical units.
PowerFlowDirection
Direction of power flow arrows.
Abstract class for branch power elements.
virtual void UpdateSwitches()
Update the switch position.
virtual void RemoveParent(Element *parent)
Remove a parent.
Node for power elements. All others power elements are connected through this.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
virtual bool RotatedRectanglesIntersects(wxRect2DDouble rect1, wxRect2DDouble rect2, double angle1, double angle2) const
Check if two roteted rectangles intersect.
virtual bool Intersects(wxRect2DDouble rect) const =0
Check if the element's rect intersects other rect.
virtual int GetID() const
Get the element ID.
virtual void GeneralMenuItens(wxMenu &menu)
Insert general itens to context menu.
double GetRotationAngle() const
Get the angle of rotation.
wxPoint2DDouble GetPosition() const
Get the element position.
double GetAngle() const
Get the element angle.
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
virtual wxPoint2DDouble RotateAtPosition(wxPoint2DDouble pointToRotate, double angle, bool degrees=true) const
Rotate a point as element position being the origin.
virtual void AddChild(Element *child)
Add a child to the child list.
static wxString StringFromDouble(double value, int minDecimal=1, int maxDecimals=13)
Convert a double value to string.
bool SetOnline(bool online=true)
Set if the element is online or offline.
virtual void DrawDCCircle(wxPoint2DDouble position, double radius, int numSegments, wxGraphicsContext *gc) const
Draw a circle using device context.
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.
std::vector< double > swTime