20#include "../forms/TextForm.h"
22#include "../simulation/ElectricCalculation.h"
35#include "../utils/DegreesAndRadians.h"
40 m_elementType = TYPE_TEXT;
44Text::Text(wxPoint2DDouble position, wxString fontName,
int fontSize) :
GraphicalElement()
46 m_elementType = TYPE_TEXT;
47 m_position = position;
48 m_fontName = fontName;
49 m_fontSize = fontSize;
61 for (
auto& gcText : m_gcTextList) {
62 if (gcText)
delete gcText;
70 return m_rect.Contains(ptR);
108void Text::DrawDC(
GUIColour* guiColour, wxPoint2DDouble translation,
double scale, wxGraphicsContext* gc)
111 if (m_updateTextRectangle) {
112 for (
GCText* gcText : m_gcTextList) {
113 if (gcText)
delete gcText;
115 m_gcTextList.clear();
117 m_numberOfLines = m_text.Freq(
'\n') + 1;
118 m_isMultlineText = m_numberOfLines > 1;
121 wxFont font = wxFont(m_fontSize,
122 wxFONTFAMILY_DEFAULT,
127 gc->SetFont(font, guiColour->text);
129 wxString multText = m_text;
130 for (
int i = 0; i < m_numberOfLines; ++i) {
132 wxString currentLine = multText.BeforeFirst(
'\n', &nextLine);
136 gc->GetTextExtent(currentLine, &w, &h);
138 if (w > m_width) m_width = w;
142 gcText->SetFont(font);
143 gcText->
SetText(currentLine, wxSize(
static_cast<int>(w),
static_cast<int>(h)));
144 m_gcTextList.push_back(gcText);
147 m_updateTextRectangle =
false;
155 gc->Translate(m_position.m_x, m_position.m_y);
156 gc->Rotate(wxDegToRad(m_angle));
157 gc->Translate(-m_position.m_x, -m_position.m_y);
161 gc->SetPen(*wxTRANSPARENT_PEN);
162 if (m_useAltSelectionColour) gc->SetBrush(wxBrush(guiColour->altSelection));
163 else gc->SetBrush(wxBrush(guiColour->selection));
165 wxPoint2DDouble pos = m_position - wxPoint2DDouble(m_borderSize / 2.0 + m_width / 2, m_borderSize / 2.0 + m_height / 2);
166 gc->DrawRectangle(pos.m_x, pos.m_y, m_rect.m_width, m_rect.m_height);
172 wxPoint2DDouble pos = m_position - wxPoint2DDouble(m_width / 2, m_height / 2);
173 if (m_isMultlineText) {
174 for (
unsigned int i = 0; i < m_gcTextList.size(); ++i) {
175 m_gcTextList[i]->Draw(
177 wxPoint2DDouble(0.0, (m_height *
static_cast<double>(i) /
static_cast<double>(m_numberOfLines))), gc, 0, guiColour->text);
180 else if (m_gcTextList.size() > 0) {
181 m_gcTextList[0]->Draw(pos, gc, 0, guiColour->text);
186void Text::DrawDC(
GUIColour* guiColour, wxPoint2DDouble translation,
double scale, wxDC& dc)
189 if (m_updateTextRectangle) {
190 for (
GCText* gcText : m_gcTextList) {
191 if (gcText)
delete gcText;
193 m_gcTextList.clear();
195 m_numberOfLines = m_text.Freq(
'\n') + 1;
196 m_isMultlineText = m_numberOfLines > 1;
199 wxFont font = wxFont(m_fontSize,
200 wxFONTFAMILY_DEFAULT,
207 wxString multText = m_text;
208 for (
int i = 0; i < m_numberOfLines; ++i) {
210 wxString currentLine = multText.BeforeFirst(
'\n', &nextLine);
213 wxSize txtSize = dc.GetTextExtent(currentLine);
215 if (txtSize.GetWidth() > m_width) m_width = txtSize.GetWidth();
216 m_height += txtSize.GetHeight();
219 gcText->SetFont(font);
220 gcText->
SetText(currentLine, txtSize);
221 m_gcTextList.push_back(gcText);
224 m_updateTextRectangle =
false;
229 dc.SetPen(*wxTRANSPARENT_PEN);
230 if (m_useAltSelectionColour) dc.SetBrush(wxBrush(guiColour->altSelection));
231 else dc.SetBrush(wxBrush(guiColour->selection));
233 DrawDCRectangle(m_position, m_rect.m_width, m_rect.m_height, m_angle, dc);
238 if (m_isMultlineText) {
239 for (
unsigned int i = 0; i < m_gcTextList.size(); ++i) {
240 m_gcTextList[i]->Draw(
242 wxPoint2DDouble(0.0, (m_height *
static_cast<double>(i) /
static_cast<double>(m_numberOfLines))), m_width, m_height, dc, m_angle);
245 else if (m_gcTextList.size() > 0) {
246 m_gcTextList[0]->Draw(m_position, m_width, m_height, dc, m_angle, guiColour->text);
252 if (m_angle == 0.0 || m_angle == 180.0)
return m_rect.Intersects(rect);
256void Text::SetText(wxString text)
258 if (m_text == text)
return;
261 m_updateTextRectangle =
true;
266 if (!m_allowRotation)
return;
268 double rotAngle = m_rotationAngle;
269 if (!clockwise) rotAngle = -m_rotationAngle;
272 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
275bool Text::ShowForm(wxWindow* parent, std::vector<Element*> elementList)
277 TextForm textForm(parent,
this, elementList);
278 if (textForm.ShowModal() == wxID_OK) {
284void Text::UpdateText(
double systemPowerBase)
286 switch (m_elementTypeText) {
291 Bus* bus =
static_cast<Bus*
>(m_element);
294 double baseVoltage = data.nominalVoltage;
295 if (data.nominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage *= 1e3;
296 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * baseVoltage);
298 switch (m_dataType) {
300 SetText(bus->GetElectricalData().name);
303 double voltage = std::abs(data.voltage);
305 case ElectricalUnit::UNIT_PU: {
306 SetText(wxString::FromDouble(voltage, m_decimalPlaces) +
" p.u.");
308 case ElectricalUnit::UNIT_V: {
309 SetText(wxString::FromDouble(voltage * baseVoltage, m_decimalPlaces) +
" V");
311 case ElectricalUnit::UNIT_kV: {
312 SetText(wxString::FromDouble(voltage * baseVoltage / 1e3, m_decimalPlaces) +
" kV");
319 double angle = std::arg(data.voltage);
321 case ElectricalUnit::UNIT_RADIAN: {
322 SetText(wxString::FromDouble(angle, m_decimalPlaces) +
" rad");
324 case ElectricalUnit::UNIT_DEGREE: {
325 SetText(wxString::FromDouble(wxRadToDeg(angle), m_decimalPlaces) + (wxString)L
'\u00B0');
331 case DATA_SC_CURRENT: {
332 double faultCurrent[3] = { std::abs(data.faultCurrent[0]), std::abs(data.faultCurrent[1]),
333 std::abs(data.faultCurrent[2]) };
335 case ElectricalUnit::UNIT_PU: {
337 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
338 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
339 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
342 case ElectricalUnit::UNIT_A: {
344 "Ia = " + wxString::FromDouble(faultCurrent[0] * baseCurrent, m_decimalPlaces) +
347 wxString::FromDouble(faultCurrent[1] * baseCurrent, m_decimalPlaces) +
" A";
349 wxString::FromDouble(faultCurrent[2] * baseCurrent, m_decimalPlaces) +
" A";
352 case ElectricalUnit::UNIT_kA: {
355 wxString::FromDouble(faultCurrent[0] * baseCurrent / 1e3, m_decimalPlaces) +
" kA";
357 wxString::FromDouble(faultCurrent[1] * baseCurrent / 1e3, m_decimalPlaces) +
360 wxString::FromDouble(faultCurrent[2] * baseCurrent / 1e3, m_decimalPlaces) +
368 case DATA_SC_VOLTAGE: {
369 double faultVoltage[3] = { std::abs(data.faultVoltage[0]), std::abs(data.faultVoltage[1]),
370 std::abs(data.faultVoltage[2]) };
372 case ElectricalUnit::UNIT_PU: {
374 "Va = " + wxString::FromDouble(faultVoltage[0], m_decimalPlaces) +
" p.u.";
375 str +=
"\nVb = " + wxString::FromDouble(faultVoltage[1], m_decimalPlaces) +
" p.u.";
376 str +=
"\nVc = " + wxString::FromDouble(faultVoltage[2], m_decimalPlaces) +
" p.u.";
379 case ElectricalUnit::UNIT_V: {
381 "Va = " + wxString::FromDouble(faultVoltage[0] * baseVoltage, m_decimalPlaces) +
384 wxString::FromDouble(faultVoltage[1] * baseVoltage, m_decimalPlaces) +
" V";
386 wxString::FromDouble(faultVoltage[2] * baseVoltage, m_decimalPlaces) +
" V";
389 case ElectricalUnit::UNIT_kV: {
392 wxString::FromDouble(faultVoltage[0] * baseVoltage / 1e3, m_decimalPlaces) +
" kV";
394 wxString::FromDouble(faultVoltage[1] * baseVoltage / 1e3, m_decimalPlaces) +
397 wxString::FromDouble(faultVoltage[2] * baseVoltage / 1e3, m_decimalPlaces) +
405 case DATA_SC_POWER: {
406 double scPower = data.scPower;
407 if (!data.isConnected) scPower = 0.0;
409 case ElectricalUnit::UNIT_PU: {
410 SetText(wxString::FromDouble(scPower, m_decimalPlaces) +
" p.u.");
412 case ElectricalUnit::UNIT_VA: {
413 SetText(wxString::FromDouble(scPower * systemPowerBase, m_decimalPlaces) +
" VA");
415 case ElectricalUnit::UNIT_kVA: {
416 SetText(wxString::FromDouble(scPower * systemPowerBase / 1e3, m_decimalPlaces) +
419 case ElectricalUnit::UNIT_MVA: {
420 SetText(wxString::FromDouble(scPower * systemPowerBase / 1e6, m_decimalPlaces) +
428 SetText(_(
"THD = ") + wxString::FromDouble(data.thd, m_decimalPlaces) +
"%");
435 case TYPE_SYNC_GENERATOR: {
439 double baseVoltage = syncGenerator->GetValueFromUnit(data.nominalVoltage, data.nominalVoltageUnit);
440 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * baseVoltage);
441 bool busParentOnline =
false;
443 if (parentList.size() == 1) {
444 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
445 if (busParent) busParentOnline = busParent->GetElectricalData().isConnected;
447 switch (m_dataType) {
451 case DATA_ACTIVE_POWER: {
452 double activePower = data.activePower;
453 if (!syncGenerator->
IsOnline() || !busParentOnline) activePower = 0.0;
455 case ElectricalUnit::UNIT_PU: {
456 SetText(wxString::FromDouble(activePower, m_decimalPlaces) +
" p.u.");
458 case ElectricalUnit::UNIT_W: {
459 SetText(wxString::FromDouble(activePower * systemPowerBase, m_decimalPlaces) +
" W");
461 case ElectricalUnit::UNIT_kW: {
462 SetText(wxString::FromDouble(activePower * systemPowerBase / 1e3, m_decimalPlaces) +
465 case ElectricalUnit::UNIT_MW: {
466 SetText(wxString::FromDouble(activePower * systemPowerBase / 1e6, m_decimalPlaces) +
473 case DATA_REACTIVE_POWER: {
474 double reactivePower = data.reactivePower;
475 if (!syncGenerator->
IsOnline() || !busParentOnline) reactivePower = 0.0;
477 case ElectricalUnit::UNIT_PU: {
478 SetText(wxString::FromDouble(reactivePower, m_decimalPlaces) +
" p.u.");
480 case ElectricalUnit::UNIT_var: {
481 SetText(wxString::FromDouble(reactivePower * systemPowerBase, m_decimalPlaces) +
484 case ElectricalUnit::UNIT_kvar: {
485 SetText(wxString::FromDouble(reactivePower * systemPowerBase / 1e3, m_decimalPlaces) +
488 case ElectricalUnit::UNIT_Mvar: {
489 SetText(wxString::FromDouble(reactivePower * systemPowerBase / 1e6, m_decimalPlaces) +
496 case DATA_SC_CURRENT: {
497 double faultCurrent[3] = { std::abs(data.faultCurrent[0]), std::abs(data.faultCurrent[1]),
498 std::abs(data.faultCurrent[2]) };
500 case ElectricalUnit::UNIT_PU: {
502 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
503 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
504 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
507 case ElectricalUnit::UNIT_A: {
509 "Ia = " + wxString::FromDouble(faultCurrent[0] * baseCurrent, m_decimalPlaces) +
512 wxString::FromDouble(faultCurrent[1] * baseCurrent, m_decimalPlaces) +
" A";
514 wxString::FromDouble(faultCurrent[2] * baseCurrent, m_decimalPlaces) +
" A";
517 case ElectricalUnit::UNIT_kA: {
520 wxString::FromDouble(faultCurrent[0] * baseCurrent / 1e3, m_decimalPlaces) +
" kA";
522 wxString::FromDouble(faultCurrent[1] * baseCurrent / 1e3, m_decimalPlaces) +
525 wxString::FromDouble(faultCurrent[2] * baseCurrent / 1e3, m_decimalPlaces) +
539 Line* line =
static_cast<Line*
>(m_element);
542 double baseVoltage = data.nominalVoltage;
543 if (data.nominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage *= 1e3;
544 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * baseVoltage);
545 bool busParentOnline =
false;
547 if (parentList.size() == 2) {
548 Bus* busParent1 =
dynamic_cast<Bus*
>(parentList[0]);
549 Bus* busParent2 =
dynamic_cast<Bus*
>(parentList[1]);
550 if (busParent1 && busParent2) {
551 if (busParent1->GetElectricalData().isConnected && busParent1->GetElectricalData().isConnected)
552 busParentOnline =
true;
555 switch (m_dataType) {
559 case DATA_PF_ACTIVE: {
560 double activePF = std::real(data.powerFlow[m_direction]);
561 if (!line->
IsOnline() || !busParentOnline) activePF = 0.0;
563 case ElectricalUnit::UNIT_PU: {
564 SetText(wxString::FromDouble(activePF, m_decimalPlaces) +
" p.u.");
566 case ElectricalUnit::UNIT_W: {
567 SetText(wxString::FromDouble(activePF * systemPowerBase, m_decimalPlaces) +
" W");
569 case ElectricalUnit::UNIT_kW: {
570 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e3, m_decimalPlaces) +
573 case ElectricalUnit::UNIT_MW: {
574 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e6, m_decimalPlaces) +
581 case DATA_PF_REACTIVE: {
582 double reactivePF = std::imag(data.powerFlow[m_direction]);
583 if (!line->
IsOnline() || !busParentOnline) reactivePF = 0.0;
585 case ElectricalUnit::UNIT_PU: {
586 SetText(wxString::FromDouble(reactivePF, m_decimalPlaces) +
" p.u.");
588 case ElectricalUnit::UNIT_var: {
589 SetText(wxString::FromDouble(reactivePF * systemPowerBase, m_decimalPlaces) +
" var");
591 case ElectricalUnit::UNIT_kvar: {
592 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e3, m_decimalPlaces) +
595 case ElectricalUnit::UNIT_Mvar: {
596 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e6, m_decimalPlaces) +
603 case DATA_PF_LOSSES: {
604 double losses = std::abs(std::real(data.powerFlow[0]) + std::real(data.powerFlow[1]));
605 if (!line->
IsOnline() || !busParentOnline) losses = 0.0;
607 case ElectricalUnit::UNIT_PU: {
608 SetText(wxString::FromDouble(losses, m_decimalPlaces) +
" p.u.");
610 case ElectricalUnit::UNIT_W: {
611 SetText(wxString::FromDouble(losses * systemPowerBase, m_decimalPlaces) +
" W");
613 case ElectricalUnit::UNIT_kW: {
614 SetText(wxString::FromDouble(losses * systemPowerBase / 1e3, m_decimalPlaces) +
" kW");
616 case ElectricalUnit::UNIT_MW: {
617 SetText(wxString::FromDouble(losses * systemPowerBase / 1e6, m_decimalPlaces) +
" MW");
623 case DATA_PF_CURRENT: {
624 double current = std::abs(data.current[m_direction]);
625 if (!line->
IsOnline() || !busParentOnline) current = 0.0;
627 case ElectricalUnit::UNIT_PU: {
628 SetText(wxString::FromDouble(current, m_decimalPlaces) +
" p.u.");
630 case ElectricalUnit::UNIT_A: {
631 SetText(wxString::FromDouble(current * baseCurrent, m_decimalPlaces) +
" A");
633 case ElectricalUnit::UNIT_kA: {
634 SetText(wxString::FromDouble(current * baseCurrent / 1e3, m_decimalPlaces) +
" kA");
640 case DATA_SC_CURRENT: {
641 double faultCurrent[3] = { std::abs(data.faultCurrent[m_direction][0]),
642 std::abs(data.faultCurrent[m_direction][1]),
643 std::abs(data.faultCurrent[m_direction][2]) };
644 if (!line->
IsOnline()) faultCurrent[0] = faultCurrent[1] = faultCurrent[2] = 0.0;
646 case ElectricalUnit::UNIT_PU: {
648 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
649 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
650 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
653 case ElectricalUnit::UNIT_A: {
655 "Ia = " + wxString::FromDouble(faultCurrent[0] * baseCurrent, m_decimalPlaces) +
658 wxString::FromDouble(faultCurrent[1] * baseCurrent, m_decimalPlaces) +
" A";
660 wxString::FromDouble(faultCurrent[2] * baseCurrent, m_decimalPlaces) +
" A";
663 case ElectricalUnit::UNIT_kA: {
666 wxString::FromDouble(faultCurrent[0] * baseCurrent / 1e3, m_decimalPlaces) +
" kA";
668 wxString::FromDouble(faultCurrent[1] * baseCurrent / 1e3, m_decimalPlaces) +
671 wxString::FromDouble(faultCurrent[2] * baseCurrent / 1e3, m_decimalPlaces) +
684 case TYPE_TRANSFORMER: {
688 double baseVoltage[2] = { data.primaryNominalVoltage, data.secondaryNominalVoltage };
689 bool busParentOnline =
false;
691 if (parentList.size() == 2) {
692 Bus* busParent1 =
dynamic_cast<Bus*
>(parentList[0]);
693 Bus* busParent2 =
dynamic_cast<Bus*
>(parentList[1]);
694 if (busParent1 && busParent2) {
695 if (busParent1->GetElectricalData().isConnected && busParent1->GetElectricalData().isConnected)
696 busParentOnline =
true;
700 if (data.primaryNominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage[0] *= 1e3;
701 if (data.secondaryNominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage[1] *= 1e3;
703 double baseCurrent[2] = { systemPowerBase / (std::sqrt(3.0) * baseVoltage[0]),
704 systemPowerBase / (std::sqrt(3.0) * baseVoltage[1]) };
705 switch (m_dataType) {
709 case DATA_PF_ACTIVE: {
710 double activePF = std::real(data.powerFlow[m_direction]);
711 if (!transformer->
IsOnline() || !busParentOnline) activePF = 0.0;
713 case ElectricalUnit::UNIT_PU: {
714 SetText(wxString::FromDouble(activePF, m_decimalPlaces) +
" p.u.");
716 case ElectricalUnit::UNIT_W: {
717 SetText(wxString::FromDouble(activePF * systemPowerBase, m_decimalPlaces) +
" W");
719 case ElectricalUnit::UNIT_kW: {
720 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e3, m_decimalPlaces) +
723 case ElectricalUnit::UNIT_MW: {
724 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e6, m_decimalPlaces) +
731 case DATA_PF_REACTIVE: {
732 double reactivePF = std::imag(data.powerFlow[m_direction]);
733 if (!transformer->
IsOnline() || !busParentOnline) reactivePF = 0.0;
735 case ElectricalUnit::UNIT_PU: {
736 SetText(wxString::FromDouble(reactivePF, m_decimalPlaces) +
" p.u.");
738 case ElectricalUnit::UNIT_var: {
739 SetText(wxString::FromDouble(reactivePF * systemPowerBase, m_decimalPlaces) +
" var");
741 case ElectricalUnit::UNIT_kvar: {
742 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e3, m_decimalPlaces) +
745 case ElectricalUnit::UNIT_Mvar: {
746 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e6, m_decimalPlaces) +
753 case DATA_PF_LOSSES: {
754 double losses = std::abs(std::real(data.powerFlow[0]) + std::real(data.powerFlow[1]));
755 if (!transformer->
IsOnline() || !busParentOnline) losses = 0.0;
757 case ElectricalUnit::UNIT_PU: {
758 SetText(wxString::FromDouble(losses, m_decimalPlaces) +
" p.u.");
760 case ElectricalUnit::UNIT_W: {
761 SetText(wxString::FromDouble(losses * systemPowerBase, m_decimalPlaces) +
" W");
763 case ElectricalUnit::UNIT_kW: {
764 SetText(wxString::FromDouble(losses * systemPowerBase / 1e3, m_decimalPlaces) +
" kW");
766 case ElectricalUnit::UNIT_MW: {
767 SetText(wxString::FromDouble(losses * systemPowerBase / 1e6, m_decimalPlaces) +
" MW");
773 case DATA_PF_CURRENT: {
774 double current = std::abs(data.current[m_direction]);
775 if (!transformer->
IsOnline() || !busParentOnline) current = 0.0;
777 case ElectricalUnit::UNIT_PU: {
778 SetText(wxString::FromDouble(current, m_decimalPlaces) +
" p.u.");
780 case ElectricalUnit::UNIT_A: {
781 SetText(wxString::FromDouble(current * baseCurrent[m_direction], m_decimalPlaces) +
784 case ElectricalUnit::UNIT_kA: {
786 wxString::FromDouble(current * baseCurrent[m_direction] / 1e3, m_decimalPlaces) +
793 case DATA_SC_CURRENT: {
794 double faultCurrent[3] = { std::abs(data.faultCurrent[m_direction][0]),
795 std::abs(data.faultCurrent[m_direction][1]),
796 std::abs(data.faultCurrent[m_direction][2]) };
797 if (!transformer->
IsOnline()) faultCurrent[0] = faultCurrent[1] = faultCurrent[2] = 0.0;
799 case ElectricalUnit::UNIT_PU: {
801 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
802 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
803 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
806 case ElectricalUnit::UNIT_A: {
809 wxString::FromDouble(faultCurrent[0] * baseCurrent[m_direction], m_decimalPlaces) +
813 wxString::FromDouble(faultCurrent[1] * baseCurrent[m_direction], m_decimalPlaces) +
817 wxString::FromDouble(faultCurrent[2] * baseCurrent[m_direction], m_decimalPlaces) +
821 case ElectricalUnit::UNIT_kA: {
822 wxString str =
"Ia = " +
823 wxString::FromDouble(faultCurrent[0] * baseCurrent[m_direction] / 1e3,
827 wxString::FromDouble(faultCurrent[1] * baseCurrent[m_direction] / 1e3,
831 wxString::FromDouble(faultCurrent[2] * baseCurrent[m_direction] / 1e3,
846 Load* load =
static_cast<Load*
>(m_element);
849 std::complex<double> sPower(data.activePower, data.reactivePower);
850 if (data.loadType == CONST_IMPEDANCE && load->
IsOnline()) {
851 std::complex<double> v =
static_cast<Bus*
>(load->
GetParentList()[0])->GetElectricalData().voltage;
852 sPower = std::pow(std::abs(v), 2) * sPower;
854 bool busParentOnline =
false;
856 if (parentList.size() == 1) {
857 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
859 busParentOnline = busParent->GetElectricalData().isConnected;
862 if (!load->
IsOnline() || !busParentOnline) sPower = std::complex<double>(0.0, 0.0);
863 switch (m_dataType) {
867 case DATA_ACTIVE_POWER: {
869 case ElectricalUnit::UNIT_PU: {
870 SetText(wxString::FromDouble(sPower.real(), m_decimalPlaces) +
" p.u.");
872 case ElectricalUnit::UNIT_W: {
873 SetText(wxString::FromDouble(sPower.real() * systemPowerBase, m_decimalPlaces) +
" W");
875 case ElectricalUnit::UNIT_kW: {
876 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e3, m_decimalPlaces) +
879 case ElectricalUnit::UNIT_MW: {
880 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e6, m_decimalPlaces) +
887 case DATA_REACTIVE_POWER: {
889 case ElectricalUnit::UNIT_PU: {
890 SetText(wxString::FromDouble(sPower.imag(), m_decimalPlaces) +
" p.u.");
892 case ElectricalUnit::UNIT_var: {
893 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase, m_decimalPlaces) +
896 case ElectricalUnit::UNIT_kvar: {
897 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e3, m_decimalPlaces) +
900 case ElectricalUnit::UNIT_Mvar: {
901 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e6, m_decimalPlaces) +
913 case TYPE_SYNC_MOTOR: {
918 bool busParentOnline =
false;
920 if (parentList.size() == 1) {
921 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
923 busParentOnline = busParent->GetElectricalData().isConnected;
925 std::complex<double> sPower(data.activePower, data.reactivePower);
926 if (!syncMotor->
IsOnline() || !busParentOnline) sPower = std::complex<double>(0.0, 0.0);
927 switch (m_dataType) {
931 case DATA_ACTIVE_POWER: {
933 case ElectricalUnit::UNIT_PU: {
934 SetText(wxString::FromDouble(sPower.real(), m_decimalPlaces) +
" p.u.");
936 case ElectricalUnit::UNIT_W: {
937 SetText(wxString::FromDouble(sPower.real() * systemPowerBase, m_decimalPlaces) +
" W");
939 case ElectricalUnit::UNIT_kW: {
940 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e3, m_decimalPlaces) +
943 case ElectricalUnit::UNIT_MW: {
944 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e6, m_decimalPlaces) +
951 case DATA_REACTIVE_POWER: {
953 case ElectricalUnit::UNIT_PU: {
954 SetText(wxString::FromDouble(sPower.imag(), m_decimalPlaces) +
" p.u.");
956 case ElectricalUnit::UNIT_var: {
957 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase, m_decimalPlaces) +
960 case ElectricalUnit::UNIT_kvar: {
961 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e3, m_decimalPlaces) +
964 case ElectricalUnit::UNIT_Mvar: {
965 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e6, m_decimalPlaces) +
977 case TYPE_IND_MOTOR: {
981 bool busParentOnline =
false;
983 if (parentList.size() == 1) {
984 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
986 busParentOnline = busParent->GetElectricalData().isConnected;
988 std::complex<double> sPower(data.activePower, data.reactivePower);
989 if (!indMotor->
IsOnline() || !busParentOnline) sPower = std::complex<double>(0.0, 0.0);
990 switch (m_dataType) {
994 case DATA_ACTIVE_POWER: {
996 case ElectricalUnit::UNIT_PU: {
997 SetText(wxString::FromDouble(sPower.real(), m_decimalPlaces) +
" p.u.");
999 case ElectricalUnit::UNIT_W: {
1000 SetText(wxString::FromDouble(sPower.real() * systemPowerBase, m_decimalPlaces) +
" W");
1002 case ElectricalUnit::UNIT_kW: {
1003 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e3, m_decimalPlaces) +
1006 case ElectricalUnit::UNIT_MW: {
1007 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e6, m_decimalPlaces) +
1014 case DATA_REACTIVE_POWER: {
1016 case ElectricalUnit::UNIT_PU: {
1017 SetText(wxString::FromDouble(sPower.imag(), m_decimalPlaces) +
" p.u.");
1019 case ElectricalUnit::UNIT_var: {
1020 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase, m_decimalPlaces) +
1023 case ElectricalUnit::UNIT_kvar: {
1024 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e3, m_decimalPlaces) +
1027 case ElectricalUnit::UNIT_Mvar: {
1028 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e6, m_decimalPlaces) +
1040 case TYPE_CAPACITOR: {
1044 double reativePower = data.reactivePower;
1046 bool busParentOnline =
false;
1048 if (parentList.size() == 1) {
1049 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
1051 busParentOnline = busParent->GetElectricalData().isConnected;
1054 if (!capacitor->
IsOnline() || !busParentOnline)
1057 std::complex<double> v =
1058 static_cast<Bus*
>(capacitor->
GetParentList()[0])->GetElectricalData().voltage;
1059 reativePower *= std::pow(std::abs(v), 2);
1061 switch (m_dataType) {
1065 case DATA_REACTIVE_POWER: {
1067 case ElectricalUnit::UNIT_PU: {
1068 SetText(wxString::FromDouble(reativePower, m_decimalPlaces) +
" p.u.");
1070 case ElectricalUnit::UNIT_var: {
1071 SetText(wxString::FromDouble(reativePower * systemPowerBase, m_decimalPlaces) +
" var");
1073 case ElectricalUnit::UNIT_kvar: {
1074 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e3, m_decimalPlaces) +
1077 case ElectricalUnit::UNIT_Mvar: {
1078 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e6, m_decimalPlaces) +
1090 case TYPE_INDUCTOR: {
1094 double reativePower = data.reactivePower;
1096 bool busParentOnline =
false;
1098 if (parentList.size() == 1) {
1099 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
1101 busParentOnline = busParent->GetElectricalData().isConnected;
1104 if (!inductor->
IsOnline() || !busParentOnline)
1107 std::complex<double> v =
1108 static_cast<Bus*
>(inductor->
GetParentList()[0])->GetElectricalData().voltage;
1109 reativePower *= std::pow(std::abs(v), 2);
1111 switch (m_dataType) {
1115 case DATA_REACTIVE_POWER: {
1117 case ElectricalUnit::UNIT_PU: {
1118 SetText(wxString::FromDouble(reativePower, m_decimalPlaces) +
" p.u.");
1120 case ElectricalUnit::UNIT_var: {
1121 SetText(wxString::FromDouble(reativePower * systemPowerBase, m_decimalPlaces) +
" var");
1123 case ElectricalUnit::UNIT_kvar: {
1124 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e3, m_decimalPlaces) +
1127 case ElectricalUnit::UNIT_Mvar: {
1128 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e6, m_decimalPlaces) +
1140 case TYPE_HARMCURRENT: {
1143 auto data = harmCurrent->GetElectricalData();
1144 switch (m_dataType) {
1160 copy->m_gcTextList.clear();
1161 copy->m_updateTextRectangle =
true;
1174rapidxml::xml_node<>* Text::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
1176 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Text");
1177 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
1179 SaveCADProperties(doc, elementNode);
1181 auto textProperties = XMLParser::AppendNode(doc, elementNode,
"TextProperties");
1182 auto elementType = XMLParser::AppendNode(doc, textProperties,
"ElementType");
1183 XMLParser::SetNodeValue(doc, elementType, m_elementTypeText);
1184 auto elementNumber = XMLParser::AppendNode(doc, textProperties,
"ElementNumber");
1185 XMLParser::SetNodeValue(doc, elementNumber, m_elementNumber);
1186 auto dataType = XMLParser::AppendNode(doc, textProperties,
"DataType");
1187 XMLParser::SetNodeValue(doc, dataType, m_dataType);
1188 auto dataUnit = XMLParser::AppendNode(doc, textProperties,
"DataUnit");
1189 XMLParser::SetNodeValue(doc, dataUnit,
static_cast<int>(m_unit));
1190 auto direction = XMLParser::AppendNode(doc, textProperties,
"Direction");
1191 XMLParser::SetNodeValue(doc, direction, m_direction);
1192 auto decimalPlaces = XMLParser::AppendNode(doc, textProperties,
"DecimalPlaces");
1193 XMLParser::SetNodeValue(doc, decimalPlaces, m_decimalPlaces);
1198bool Text::OpenElement(rapidxml::xml_node<>* elementNode)
1200 if (!OpenCADProperties(elementNode))
return false;
1202 auto textProperties = elementNode->first_node(
"TextProperties");
1203 if (!textProperties)
return false;
1205 SetElementTypeText(
static_cast<ElementType
>(XMLParser::GetNodeValueDouble(textProperties,
"ElementType")));
1206 SetDataType(
static_cast<DataType
>(XMLParser::GetNodeValueDouble(textProperties,
"DataType")));
1207 SetUnit(
static_cast<ElectricalUnit
>(XMLParser::GetNodeValueDouble(textProperties,
"DataUnit")));
1208 SetDirection(XMLParser::GetNodeValueDouble(textProperties,
"Direction"));
1209 SetDecimalPlaces(XMLParser::GetNodeValueDouble(textProperties,
"DecimalPlaces"));
1210 SetElementNumber(XMLParser::GetNodeValueInt(textProperties,
"ElementNumber"));
Node for power elements. All others power elements are connected through this.
Shunt capactior power element.
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 std::vector< Element * > GetParentList() const
Get the parent list.
bool IsOnline() const
Checks if the element is online or offline.
virtual void DrawDCRectangle(wxPoint2DDouble position, double width, double height, double angle, wxDC &dc) const
Draw a circle.
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.
void SetInserted(bool inserted=true)
Set if the element is properly inserted in the workspace.
Class to draw text on Graphics Context using wxWidgets.
virtual void SetText(wxString text)
Set correctly a new text string.
Abstract class for graphical elements shown with graphical elements in workspace.
Shunt Harmonic Corrent Source.
Induction motor power element.
Inductor shunt power element.
Loas shunt power element.
Synchronous generator power element.
Synchronous motor (synchronous compensator) power element.
Form to edit the text graphical data.
Element that shows power element informations in workspace.
virtual Element * GetCopy()
Get a the element copy.
virtual bool Contains(wxPoint2DDouble position) const
Checks if the element contains a position.
virtual bool Intersects(wxRect2DDouble rect) const
Check if the element's rect intersects other rect.
virtual void Rotate(bool clockwise=true)
Rotate the element.