20#include "../forms/TextForm.h"
22#include "../simulation/ElectricCalculation.h"
24#include "../editors/Workspace.h"
37#include "../utils/DegreesAndRadians.h"
42 m_elementType = TYPE_TEXT;
46Text::Text(wxPoint2DDouble position, wxString fontName,
int fontSize) :
GraphicalElement()
48 m_elementType = TYPE_TEXT;
49 m_position = position;
50 m_fontName = fontName;
51 m_fontSize = fontSize;
63 for (
auto& gcText : m_gcTextList) {
64 if (gcText)
delete gcText;
72 return m_rect.Contains(ptR);
110void Text::DrawDC(
GUIColour* guiColour, wxPoint2DDouble translation,
double scale, wxGraphicsContext* gc)
113 if (m_updateTextRectangle) {
114 for (
GCText* gcText : m_gcTextList) {
115 if (gcText)
delete gcText;
117 m_gcTextList.clear();
119 m_numberOfLines = m_text.Freq(
'\n') + 1;
120 m_isMultlineText = m_numberOfLines > 1;
123 wxFont font = wxFont(m_fontSize,
124 wxFONTFAMILY_DEFAULT,
129 gc->SetFont(font, guiColour->text);
131 wxString multText = m_text;
132 for (
int i = 0; i < m_numberOfLines; ++i) {
134 wxString currentLine = multText.BeforeFirst(
'\n', &nextLine);
138 gc->GetTextExtent(currentLine, &w, &h);
140 if (w > m_width) m_width = w;
144 gcText->SetFont(font);
145 gcText->
SetText(currentLine, wxSize(
static_cast<int>(w),
static_cast<int>(h)));
146 m_gcTextList.push_back(gcText);
149 m_updateTextRectangle =
false;
157 gc->Translate(m_position.m_x, m_position.m_y);
158 gc->Rotate(wxDegToRad(m_angle));
159 gc->Translate(-m_position.m_x, -m_position.m_y);
163 gc->SetPen(*wxTRANSPARENT_PEN);
164 if (m_useAltSelectionColour) gc->SetBrush(wxBrush(guiColour->altSelection));
165 else gc->SetBrush(wxBrush(guiColour->selection));
167 wxPoint2DDouble pos = m_position - wxPoint2DDouble(m_borderSize / 2.0 + m_width / 2, m_borderSize / 2.0 + m_height / 2);
168 gc->DrawRectangle(pos.m_x, pos.m_y, m_rect.m_width, m_rect.m_height);
174 wxPoint2DDouble pos = m_position - wxPoint2DDouble(m_width / 2, m_height / 2);
175 if (m_isMultlineText) {
176 for (
unsigned int i = 0; i < m_gcTextList.size(); ++i) {
177 m_gcTextList[i]->Draw(
179 wxPoint2DDouble(0.0, (m_height *
static_cast<double>(i) /
static_cast<double>(m_numberOfLines))), gc, 0, guiColour->text);
182 else if (m_gcTextList.size() > 0) {
183 m_gcTextList[0]->Draw(pos, gc, 0, guiColour->text);
188void Text::DrawDC(
GUIColour* guiColour, wxPoint2DDouble translation,
double scale, wxDC& dc)
191 if (m_updateTextRectangle) {
192 for (
GCText* gcText : m_gcTextList) {
193 if (gcText)
delete gcText;
195 m_gcTextList.clear();
197 m_numberOfLines = m_text.Freq(
'\n') + 1;
198 m_isMultlineText = m_numberOfLines > 1;
201 wxFont font = wxFont(m_fontSize,
202 wxFONTFAMILY_DEFAULT,
209 wxString multText = m_text;
210 for (
int i = 0; i < m_numberOfLines; ++i) {
212 wxString currentLine = multText.BeforeFirst(
'\n', &nextLine);
215 wxSize txtSize = dc.GetTextExtent(currentLine);
217 if (txtSize.GetWidth() > m_width) m_width = txtSize.GetWidth();
218 m_height += txtSize.GetHeight();
221 gcText->SetFont(font);
222 gcText->
SetText(currentLine, txtSize);
223 m_gcTextList.push_back(gcText);
226 m_updateTextRectangle =
false;
231 dc.SetPen(*wxTRANSPARENT_PEN);
232 if (m_useAltSelectionColour) dc.SetBrush(wxBrush(guiColour->altSelection));
233 else dc.SetBrush(wxBrush(guiColour->selection));
235 DrawDCRectangle(m_position, m_rect.m_width, m_rect.m_height, m_angle, dc);
240 if (m_isMultlineText) {
241 for (
unsigned int i = 0; i < m_gcTextList.size(); ++i) {
242 m_gcTextList[i]->Draw(
244 wxPoint2DDouble(0.0, (m_height *
static_cast<double>(i) /
static_cast<double>(m_numberOfLines))), m_width, m_height, dc, m_angle);
247 else if (m_gcTextList.size() > 0) {
248 m_gcTextList[0]->Draw(m_position, m_width, m_height, dc, m_angle, guiColour->text);
254 if (m_angle == 0.0 || m_angle == 180.0)
return m_rect.Intersects(rect);
258void Text::SetText(wxString text)
260 if (m_text == text)
return;
263 m_updateTextRectangle =
true;
268 if (!m_allowRotation)
return;
270 double rotAngle = m_rotationAngle;
271 if (!clockwise) rotAngle = -m_rotationAngle;
274 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
277bool Text::ShowForm(wxWindow* parent, std::vector<Element*> elementList, wxWindow* workspace)
280 if (!ws)
return false;
281 double systemPowerBase = ws->GetProperties()->GetSimulationPropertiesData().basePower;
282 if (ws->GetProperties()->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_MVA)
283 systemPowerBase *= 1e6;
284 else if (ws->GetProperties()->GetSimulationPropertiesData().basePowerUnit == ElectricalUnit::UNIT_kVA)
285 systemPowerBase *= 1e3;
287 TextForm textForm(parent,
this, elementList, systemPowerBase);
288 if (textForm.ShowModal() == wxID_OK) {
294void Text::UpdateText(
double systemPowerBase)
296 switch (m_elementTypeText) {
301 Bus* bus =
static_cast<Bus*
>(m_element);
304 double baseVoltage = data.nominalVoltage;
305 if (data.nominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage *= 1e3;
306 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * baseVoltage);
308 switch (m_dataType) {
310 SetText(bus->GetElectricalData().name);
313 double voltage = std::abs(data.voltage);
315 case ElectricalUnit::UNIT_PU: {
316 SetText(wxString::FromDouble(voltage, m_decimalPlaces) +
" p.u.");
318 case ElectricalUnit::UNIT_V: {
319 SetText(wxString::FromDouble(voltage * baseVoltage, m_decimalPlaces) +
" V");
321 case ElectricalUnit::UNIT_kV: {
322 SetText(wxString::FromDouble(voltage * baseVoltage / 1e3, m_decimalPlaces) +
" kV");
329 double angle = std::arg(data.voltage);
331 case ElectricalUnit::UNIT_RADIAN: {
332 SetText(wxString::FromDouble(angle, m_decimalPlaces) +
" rad");
334 case ElectricalUnit::UNIT_DEGREE: {
335 SetText(wxString::FromDouble(wxRadToDeg(angle), m_decimalPlaces) + (wxString)L
'\u00B0');
341 case DATA_SC_CURRENT: {
342 double faultCurrent[3] = { std::abs(data.faultCurrent[0]), std::abs(data.faultCurrent[1]),
343 std::abs(data.faultCurrent[2]) };
345 case ElectricalUnit::UNIT_PU: {
347 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
348 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
349 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
352 case ElectricalUnit::UNIT_A: {
354 "Ia = " + wxString::FromDouble(faultCurrent[0] * baseCurrent, m_decimalPlaces) +
357 wxString::FromDouble(faultCurrent[1] * baseCurrent, m_decimalPlaces) +
" A";
359 wxString::FromDouble(faultCurrent[2] * baseCurrent, m_decimalPlaces) +
" A";
362 case ElectricalUnit::UNIT_kA: {
365 wxString::FromDouble(faultCurrent[0] * baseCurrent / 1e3, m_decimalPlaces) +
" kA";
367 wxString::FromDouble(faultCurrent[1] * baseCurrent / 1e3, m_decimalPlaces) +
370 wxString::FromDouble(faultCurrent[2] * baseCurrent / 1e3, m_decimalPlaces) +
378 case DATA_SC_VOLTAGE: {
379 double faultVoltage[3] = { std::abs(data.faultVoltage[0]), std::abs(data.faultVoltage[1]),
380 std::abs(data.faultVoltage[2]) };
382 case ElectricalUnit::UNIT_PU: {
384 "Va = " + wxString::FromDouble(faultVoltage[0], m_decimalPlaces) +
" p.u.";
385 str +=
"\nVb = " + wxString::FromDouble(faultVoltage[1], m_decimalPlaces) +
" p.u.";
386 str +=
"\nVc = " + wxString::FromDouble(faultVoltage[2], m_decimalPlaces) +
" p.u.";
389 case ElectricalUnit::UNIT_V: {
391 "Va = " + wxString::FromDouble(faultVoltage[0] * baseVoltage, m_decimalPlaces) +
394 wxString::FromDouble(faultVoltage[1] * baseVoltage, m_decimalPlaces) +
" V";
396 wxString::FromDouble(faultVoltage[2] * baseVoltage, m_decimalPlaces) +
" V";
399 case ElectricalUnit::UNIT_kV: {
402 wxString::FromDouble(faultVoltage[0] * baseVoltage / 1e3, m_decimalPlaces) +
" kV";
404 wxString::FromDouble(faultVoltage[1] * baseVoltage / 1e3, m_decimalPlaces) +
407 wxString::FromDouble(faultVoltage[2] * baseVoltage / 1e3, m_decimalPlaces) +
415 case DATA_SC_POWER: {
416 double scPower = data.scPower;
417 if (!data.isConnected) scPower = 0.0;
419 case ElectricalUnit::UNIT_PU: {
420 SetText(wxString::FromDouble(scPower, m_decimalPlaces) +
" p.u.");
422 case ElectricalUnit::UNIT_VA: {
423 SetText(wxString::FromDouble(scPower * systemPowerBase, m_decimalPlaces) +
" VA");
425 case ElectricalUnit::UNIT_kVA: {
426 SetText(wxString::FromDouble(scPower * systemPowerBase / 1e3, m_decimalPlaces) +
429 case ElectricalUnit::UNIT_MVA: {
430 SetText(wxString::FromDouble(scPower * systemPowerBase / 1e6, m_decimalPlaces) +
438 SetText(_(
"THD = ") + wxString::FromDouble(data.thd, m_decimalPlaces) +
"%");
445 case TYPE_SYNC_GENERATOR: {
449 double baseVoltage = syncGenerator->GetValueFromUnit(data.nominalVoltage, data.nominalVoltageUnit);
450 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * baseVoltage);
451 bool busParentOnline =
false;
453 if (parentList.size() == 1) {
454 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
455 if (busParent) busParentOnline = busParent->GetElectricalData().isConnected;
457 switch (m_dataType) {
461 case DATA_ACTIVE_POWER: {
462 double activePower = data.activePower;
463 if (!syncGenerator->
IsOnline() || !busParentOnline) activePower = 0.0;
465 case ElectricalUnit::UNIT_PU: {
466 SetText(wxString::FromDouble(activePower, m_decimalPlaces) +
" p.u.");
468 case ElectricalUnit::UNIT_W: {
469 SetText(wxString::FromDouble(activePower * systemPowerBase, m_decimalPlaces) +
" W");
471 case ElectricalUnit::UNIT_kW: {
472 SetText(wxString::FromDouble(activePower * systemPowerBase / 1e3, m_decimalPlaces) +
475 case ElectricalUnit::UNIT_MW: {
476 SetText(wxString::FromDouble(activePower * systemPowerBase / 1e6, m_decimalPlaces) +
483 case DATA_REACTIVE_POWER: {
484 double reactivePower = data.reactivePower;
485 if (!syncGenerator->
IsOnline() || !busParentOnline) reactivePower = 0.0;
487 case ElectricalUnit::UNIT_PU: {
488 SetText(wxString::FromDouble(reactivePower, m_decimalPlaces) +
" p.u.");
490 case ElectricalUnit::UNIT_var: {
491 SetText(wxString::FromDouble(reactivePower * systemPowerBase, m_decimalPlaces) +
494 case ElectricalUnit::UNIT_kvar: {
495 SetText(wxString::FromDouble(reactivePower * systemPowerBase / 1e3, m_decimalPlaces) +
498 case ElectricalUnit::UNIT_Mvar: {
499 SetText(wxString::FromDouble(reactivePower * systemPowerBase / 1e6, m_decimalPlaces) +
506 case DATA_SC_CURRENT: {
507 double faultCurrent[3] = { std::abs(data.faultCurrent[0]), std::abs(data.faultCurrent[1]),
508 std::abs(data.faultCurrent[2]) };
510 case ElectricalUnit::UNIT_PU: {
512 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
513 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
514 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
517 case ElectricalUnit::UNIT_A: {
519 "Ia = " + wxString::FromDouble(faultCurrent[0] * baseCurrent, m_decimalPlaces) +
522 wxString::FromDouble(faultCurrent[1] * baseCurrent, m_decimalPlaces) +
" A";
524 wxString::FromDouble(faultCurrent[2] * baseCurrent, m_decimalPlaces) +
" A";
527 case ElectricalUnit::UNIT_kA: {
530 wxString::FromDouble(faultCurrent[0] * baseCurrent / 1e3, m_decimalPlaces) +
" kA";
532 wxString::FromDouble(faultCurrent[1] * baseCurrent / 1e3, m_decimalPlaces) +
535 wxString::FromDouble(faultCurrent[2] * baseCurrent / 1e3, m_decimalPlaces) +
549 Line* line =
static_cast<Line*
>(m_element);
552 double baseVoltage = data.nominalVoltage;
553 if (data.nominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage *= 1e3;
554 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * baseVoltage);
555 bool busParentOnline =
false;
557 if (parentList.size() == 2) {
558 Bus* busParent1 =
dynamic_cast<Bus*
>(parentList[0]);
559 Bus* busParent2 =
dynamic_cast<Bus*
>(parentList[1]);
560 if (busParent1 && busParent2) {
561 if (busParent1->GetElectricalData().isConnected && busParent1->GetElectricalData().isConnected)
562 busParentOnline =
true;
565 switch (m_dataType) {
569 case DATA_PF_ACTIVE: {
570 double activePF = std::real(data.powerFlow[m_direction]);
571 if (!line->
IsOnline() || !busParentOnline) activePF = 0.0;
573 case ElectricalUnit::UNIT_PU: {
574 SetText(wxString::FromDouble(activePF, m_decimalPlaces) +
" p.u.");
576 case ElectricalUnit::UNIT_W: {
577 SetText(wxString::FromDouble(activePF * systemPowerBase, m_decimalPlaces) +
" W");
579 case ElectricalUnit::UNIT_kW: {
580 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e3, m_decimalPlaces) +
583 case ElectricalUnit::UNIT_MW: {
584 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e6, m_decimalPlaces) +
591 case DATA_PF_REACTIVE: {
592 double reactivePF = std::imag(data.powerFlow[m_direction]);
593 if (!line->
IsOnline() || !busParentOnline) reactivePF = 0.0;
595 case ElectricalUnit::UNIT_PU: {
596 SetText(wxString::FromDouble(reactivePF, m_decimalPlaces) +
" p.u.");
598 case ElectricalUnit::UNIT_var: {
599 SetText(wxString::FromDouble(reactivePF * systemPowerBase, m_decimalPlaces) +
" var");
601 case ElectricalUnit::UNIT_kvar: {
602 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e3, m_decimalPlaces) +
605 case ElectricalUnit::UNIT_Mvar: {
606 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e6, m_decimalPlaces) +
613 case DATA_PF_LOSSES: {
614 double losses = std::abs(std::real(data.powerFlow[0]) + std::real(data.powerFlow[1]));
615 if (!line->
IsOnline() || !busParentOnline) losses = 0.0;
617 case ElectricalUnit::UNIT_PU: {
618 SetText(wxString::FromDouble(losses, m_decimalPlaces) +
" p.u.");
620 case ElectricalUnit::UNIT_W: {
621 SetText(wxString::FromDouble(losses * systemPowerBase, m_decimalPlaces) +
" W");
623 case ElectricalUnit::UNIT_kW: {
624 SetText(wxString::FromDouble(losses * systemPowerBase / 1e3, m_decimalPlaces) +
" kW");
626 case ElectricalUnit::UNIT_MW: {
627 SetText(wxString::FromDouble(losses * systemPowerBase / 1e6, m_decimalPlaces) +
" MW");
633 case DATA_PF_CURRENT: {
634 double current = std::abs(data.current[m_direction]);
635 if (!line->
IsOnline() || !busParentOnline) current = 0.0;
637 case ElectricalUnit::UNIT_PU: {
638 SetText(wxString::FromDouble(current, m_decimalPlaces) +
" p.u.");
640 case ElectricalUnit::UNIT_A: {
641 SetText(wxString::FromDouble(current * baseCurrent, m_decimalPlaces) +
" A");
643 case ElectricalUnit::UNIT_kA: {
644 SetText(wxString::FromDouble(current * baseCurrent / 1e3, m_decimalPlaces) +
" kA");
650 case DATA_SC_CURRENT: {
651 double faultCurrent[3] = { std::abs(data.faultCurrent[m_direction][0]),
652 std::abs(data.faultCurrent[m_direction][1]),
653 std::abs(data.faultCurrent[m_direction][2]) };
654 if (!line->
IsOnline()) faultCurrent[0] = faultCurrent[1] = faultCurrent[2] = 0.0;
656 case ElectricalUnit::UNIT_PU: {
658 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
659 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
660 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
663 case ElectricalUnit::UNIT_A: {
665 "Ia = " + wxString::FromDouble(faultCurrent[0] * baseCurrent, m_decimalPlaces) +
668 wxString::FromDouble(faultCurrent[1] * baseCurrent, m_decimalPlaces) +
" A";
670 wxString::FromDouble(faultCurrent[2] * baseCurrent, m_decimalPlaces) +
" A";
673 case ElectricalUnit::UNIT_kA: {
676 wxString::FromDouble(faultCurrent[0] * baseCurrent / 1e3, m_decimalPlaces) +
" kA";
678 wxString::FromDouble(faultCurrent[1] * baseCurrent / 1e3, m_decimalPlaces) +
681 wxString::FromDouble(faultCurrent[2] * baseCurrent / 1e3, m_decimalPlaces) +
694 case TYPE_TRANSFORMER: {
698 double baseVoltage[2] = { data.primaryNominalVoltage, data.secondaryNominalVoltage };
699 bool busParentOnline =
false;
701 if (parentList.size() == 2) {
702 Bus* busParent1 =
dynamic_cast<Bus*
>(parentList[0]);
703 Bus* busParent2 =
dynamic_cast<Bus*
>(parentList[1]);
704 if (busParent1 && busParent2) {
705 if (busParent1->GetElectricalData().isConnected && busParent1->GetElectricalData().isConnected)
706 busParentOnline =
true;
710 if (data.primaryNominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage[0] *= 1e3;
711 if (data.secondaryNominalVoltageUnit == ElectricalUnit::UNIT_kV) baseVoltage[1] *= 1e3;
713 double baseCurrent[2] = { systemPowerBase / (std::sqrt(3.0) * baseVoltage[0]),
714 systemPowerBase / (std::sqrt(3.0) * baseVoltage[1]) };
715 switch (m_dataType) {
719 case DATA_PF_ACTIVE: {
720 double activePF = std::real(data.powerFlow[m_direction]);
721 if (!transformer->
IsOnline() || !busParentOnline) activePF = 0.0;
723 case ElectricalUnit::UNIT_PU: {
724 SetText(wxString::FromDouble(activePF, m_decimalPlaces) +
" p.u.");
726 case ElectricalUnit::UNIT_W: {
727 SetText(wxString::FromDouble(activePF * systemPowerBase, m_decimalPlaces) +
" W");
729 case ElectricalUnit::UNIT_kW: {
730 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e3, m_decimalPlaces) +
733 case ElectricalUnit::UNIT_MW: {
734 SetText(wxString::FromDouble(activePF * systemPowerBase / 1e6, m_decimalPlaces) +
741 case DATA_PF_REACTIVE: {
742 double reactivePF = std::imag(data.powerFlow[m_direction]);
743 if (!transformer->
IsOnline() || !busParentOnline) reactivePF = 0.0;
745 case ElectricalUnit::UNIT_PU: {
746 SetText(wxString::FromDouble(reactivePF, m_decimalPlaces) +
" p.u.");
748 case ElectricalUnit::UNIT_var: {
749 SetText(wxString::FromDouble(reactivePF * systemPowerBase, m_decimalPlaces) +
" var");
751 case ElectricalUnit::UNIT_kvar: {
752 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e3, m_decimalPlaces) +
755 case ElectricalUnit::UNIT_Mvar: {
756 SetText(wxString::FromDouble(reactivePF * systemPowerBase / 1e6, m_decimalPlaces) +
763 case DATA_PF_LOSSES: {
764 double losses = std::abs(std::real(data.powerFlow[0]) + std::real(data.powerFlow[1]));
765 if (!transformer->
IsOnline() || !busParentOnline) losses = 0.0;
767 case ElectricalUnit::UNIT_PU: {
768 SetText(wxString::FromDouble(losses, m_decimalPlaces) +
" p.u.");
770 case ElectricalUnit::UNIT_W: {
771 SetText(wxString::FromDouble(losses * systemPowerBase, m_decimalPlaces) +
" W");
773 case ElectricalUnit::UNIT_kW: {
774 SetText(wxString::FromDouble(losses * systemPowerBase / 1e3, m_decimalPlaces) +
" kW");
776 case ElectricalUnit::UNIT_MW: {
777 SetText(wxString::FromDouble(losses * systemPowerBase / 1e6, m_decimalPlaces) +
" MW");
783 case DATA_PF_CURRENT: {
784 double current = std::abs(data.current[m_direction]);
785 if (!transformer->
IsOnline() || !busParentOnline) current = 0.0;
787 case ElectricalUnit::UNIT_PU: {
788 SetText(wxString::FromDouble(current, m_decimalPlaces) +
" p.u.");
790 case ElectricalUnit::UNIT_A: {
791 SetText(wxString::FromDouble(current * baseCurrent[m_direction], m_decimalPlaces) +
794 case ElectricalUnit::UNIT_kA: {
796 wxString::FromDouble(current * baseCurrent[m_direction] / 1e3, m_decimalPlaces) +
803 case DATA_SC_CURRENT: {
804 double faultCurrent[3] = { std::abs(data.faultCurrent[m_direction][0]),
805 std::abs(data.faultCurrent[m_direction][1]),
806 std::abs(data.faultCurrent[m_direction][2]) };
807 if (!transformer->
IsOnline()) faultCurrent[0] = faultCurrent[1] = faultCurrent[2] = 0.0;
809 case ElectricalUnit::UNIT_PU: {
811 "Ia = " + wxString::FromDouble(faultCurrent[0], m_decimalPlaces) +
" p.u.";
812 str +=
"\nIb = " + wxString::FromDouble(faultCurrent[1], m_decimalPlaces) +
" p.u.";
813 str +=
"\nIc = " + wxString::FromDouble(faultCurrent[2], m_decimalPlaces) +
" p.u.";
816 case ElectricalUnit::UNIT_A: {
819 wxString::FromDouble(faultCurrent[0] * baseCurrent[m_direction], m_decimalPlaces) +
823 wxString::FromDouble(faultCurrent[1] * baseCurrent[m_direction], m_decimalPlaces) +
827 wxString::FromDouble(faultCurrent[2] * baseCurrent[m_direction], m_decimalPlaces) +
831 case ElectricalUnit::UNIT_kA: {
832 wxString str =
"Ia = " +
833 wxString::FromDouble(faultCurrent[0] * baseCurrent[m_direction] / 1e3,
837 wxString::FromDouble(faultCurrent[1] * baseCurrent[m_direction] / 1e3,
841 wxString::FromDouble(faultCurrent[2] * baseCurrent[m_direction] / 1e3,
850 case DATA_TRANSFORMER_TAP: {
851 double tap = data.turnsRatio;
852 if (m_unit == ElectricalUnit::UNIT_NONE)
853 SetText(_(
"Tap = ") + wxString::FromDouble(tap, m_decimalPlaces));
855 SetText(_(
"Tap = ") + wxString::FromDouble(tap, m_decimalPlaces) +
" p.u.");
863 Load* load =
static_cast<Load*
>(m_element);
866 std::complex<double> sPower(data.activePower, data.reactivePower);
867 if (data.loadType == CONST_IMPEDANCE && load->
IsOnline()) {
868 std::complex<double> v =
static_cast<Bus*
>(load->
GetParentList()[0])->GetElectricalData().voltage;
869 sPower = std::pow(std::abs(v), 2) * sPower;
871 bool busParentOnline =
false;
873 if (parentList.size() == 1) {
874 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
876 busParentOnline = busParent->GetElectricalData().isConnected;
879 if (!load->
IsOnline() || !busParentOnline) sPower = std::complex<double>(0.0, 0.0);
880 switch (m_dataType) {
884 case DATA_ACTIVE_POWER: {
886 case ElectricalUnit::UNIT_PU: {
887 SetText(wxString::FromDouble(sPower.real(), m_decimalPlaces) +
" p.u.");
889 case ElectricalUnit::UNIT_W: {
890 SetText(wxString::FromDouble(sPower.real() * systemPowerBase, m_decimalPlaces) +
" W");
892 case ElectricalUnit::UNIT_kW: {
893 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e3, m_decimalPlaces) +
896 case ElectricalUnit::UNIT_MW: {
897 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e6, m_decimalPlaces) +
904 case DATA_REACTIVE_POWER: {
906 case ElectricalUnit::UNIT_PU: {
907 SetText(wxString::FromDouble(sPower.imag(), m_decimalPlaces) +
" p.u.");
909 case ElectricalUnit::UNIT_var: {
910 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase, m_decimalPlaces) +
913 case ElectricalUnit::UNIT_kvar: {
914 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e3, m_decimalPlaces) +
917 case ElectricalUnit::UNIT_Mvar: {
918 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e6, m_decimalPlaces) +
930 case TYPE_SYNC_MOTOR: {
935 bool busParentOnline =
false;
937 if (parentList.size() == 1) {
938 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
940 busParentOnline = busParent->GetElectricalData().isConnected;
942 std::complex<double> sPower(data.activePower, data.reactivePower);
943 if (!syncMotor->
IsOnline() || !busParentOnline) sPower = std::complex<double>(0.0, 0.0);
944 switch (m_dataType) {
948 case DATA_ACTIVE_POWER: {
950 case ElectricalUnit::UNIT_PU: {
951 SetText(wxString::FromDouble(sPower.real(), m_decimalPlaces) +
" p.u.");
953 case ElectricalUnit::UNIT_W: {
954 SetText(wxString::FromDouble(sPower.real() * systemPowerBase, m_decimalPlaces) +
" W");
956 case ElectricalUnit::UNIT_kW: {
957 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e3, m_decimalPlaces) +
960 case ElectricalUnit::UNIT_MW: {
961 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e6, m_decimalPlaces) +
968 case DATA_REACTIVE_POWER: {
970 case ElectricalUnit::UNIT_PU: {
971 SetText(wxString::FromDouble(sPower.imag(), m_decimalPlaces) +
" p.u.");
973 case ElectricalUnit::UNIT_var: {
974 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase, m_decimalPlaces) +
977 case ElectricalUnit::UNIT_kvar: {
978 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e3, m_decimalPlaces) +
981 case ElectricalUnit::UNIT_Mvar: {
982 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e6, m_decimalPlaces) +
994 case TYPE_IND_MOTOR: {
998 bool busParentOnline =
false;
1000 if (parentList.size() == 1) {
1001 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
1003 busParentOnline = busParent->GetElectricalData().isConnected;
1005 std::complex<double> sPower(data.activePower, data.reactivePower);
1006 if (!indMotor->
IsOnline() || !busParentOnline) sPower = std::complex<double>(0.0, 0.0);
1007 switch (m_dataType) {
1011 case DATA_ACTIVE_POWER: {
1013 case ElectricalUnit::UNIT_PU: {
1014 SetText(wxString::FromDouble(sPower.real(), m_decimalPlaces) +
" p.u.");
1016 case ElectricalUnit::UNIT_W: {
1017 SetText(wxString::FromDouble(sPower.real() * systemPowerBase, m_decimalPlaces) +
" W");
1019 case ElectricalUnit::UNIT_kW: {
1020 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e3, m_decimalPlaces) +
1023 case ElectricalUnit::UNIT_MW: {
1024 SetText(wxString::FromDouble(sPower.real() * systemPowerBase / 1e6, m_decimalPlaces) +
1031 case DATA_REACTIVE_POWER: {
1033 case ElectricalUnit::UNIT_PU: {
1034 SetText(wxString::FromDouble(sPower.imag(), m_decimalPlaces) +
" p.u.");
1036 case ElectricalUnit::UNIT_var: {
1037 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase, m_decimalPlaces) +
1040 case ElectricalUnit::UNIT_kvar: {
1041 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e3, m_decimalPlaces) +
1044 case ElectricalUnit::UNIT_Mvar: {
1045 SetText(wxString::FromDouble(sPower.imag() * systemPowerBase / 1e6, m_decimalPlaces) +
1057 case TYPE_CAPACITOR: {
1061 double reativePower = data.reactivePower;
1063 bool busParentOnline =
false;
1065 if (parentList.size() == 1) {
1066 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
1068 busParentOnline = busParent->GetElectricalData().isConnected;
1071 if (!capacitor->
IsOnline() || !busParentOnline)
1074 std::complex<double> v =
1075 static_cast<Bus*
>(capacitor->
GetParentList()[0])->GetElectricalData().voltage;
1076 reativePower *= std::pow(std::abs(v), 2);
1078 switch (m_dataType) {
1082 case DATA_REACTIVE_POWER: {
1084 case ElectricalUnit::UNIT_PU: {
1085 SetText(wxString::FromDouble(reativePower, m_decimalPlaces) +
" p.u.");
1087 case ElectricalUnit::UNIT_var: {
1088 SetText(wxString::FromDouble(reativePower * systemPowerBase, m_decimalPlaces) +
" var");
1090 case ElectricalUnit::UNIT_kvar: {
1091 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e3, m_decimalPlaces) +
1094 case ElectricalUnit::UNIT_Mvar: {
1095 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e6, m_decimalPlaces) +
1107 case TYPE_INDUCTOR: {
1111 double reativePower = data.reactivePower;
1113 bool busParentOnline =
false;
1115 if (parentList.size() == 1) {
1116 Bus* busParent =
dynamic_cast<Bus*
>(parentList[0]);
1118 busParentOnline = busParent->GetElectricalData().isConnected;
1121 if (!inductor->
IsOnline() || !busParentOnline)
1124 std::complex<double> v =
1125 static_cast<Bus*
>(inductor->
GetParentList()[0])->GetElectricalData().voltage;
1126 reativePower *= std::pow(std::abs(v), 2);
1128 switch (m_dataType) {
1132 case DATA_REACTIVE_POWER: {
1134 case ElectricalUnit::UNIT_PU: {
1135 SetText(wxString::FromDouble(reativePower, m_decimalPlaces) +
" p.u.");
1137 case ElectricalUnit::UNIT_var: {
1138 SetText(wxString::FromDouble(reativePower * systemPowerBase, m_decimalPlaces) +
" var");
1140 case ElectricalUnit::UNIT_kvar: {
1141 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e3, m_decimalPlaces) +
1144 case ElectricalUnit::UNIT_Mvar: {
1145 SetText(wxString::FromDouble(reativePower * systemPowerBase / 1e6, m_decimalPlaces) +
1157 case TYPE_HARMCURRENT: {
1160 auto data = harmCurrent->GetElectricalData();
1161 switch (m_dataType) {
1177 copy->m_gcTextList.clear();
1178 copy->m_updateTextRectangle =
true;
1191rapidxml::xml_node<>* Text::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
1193 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Text");
1194 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
1196 SaveCADProperties(doc, elementNode);
1198 auto textProperties = XMLParser::AppendNode(doc, elementNode,
"TextProperties");
1199 auto elementType = XMLParser::AppendNode(doc, textProperties,
"ElementType");
1200 XMLParser::SetNodeValue(doc, elementType, m_elementTypeText);
1201 auto elementNumber = XMLParser::AppendNode(doc, textProperties,
"ElementNumber");
1202 XMLParser::SetNodeValue(doc, elementNumber, m_elementNumber);
1203 auto dataType = XMLParser::AppendNode(doc, textProperties,
"DataType");
1204 XMLParser::SetNodeValue(doc, dataType, m_dataType);
1205 auto dataUnit = XMLParser::AppendNode(doc, textProperties,
"DataUnit");
1206 XMLParser::SetNodeValue(doc, dataUnit,
static_cast<int>(m_unit));
1207 auto direction = XMLParser::AppendNode(doc, textProperties,
"Direction");
1208 XMLParser::SetNodeValue(doc, direction, m_direction);
1209 auto decimalPlaces = XMLParser::AppendNode(doc, textProperties,
"DecimalPlaces");
1210 XMLParser::SetNodeValue(doc, decimalPlaces, m_decimalPlaces);
1215bool Text::OpenElement(rapidxml::xml_node<>* elementNode)
1217 if (!OpenCADProperties(elementNode))
return false;
1219 auto textProperties = elementNode->first_node(
"TextProperties");
1220 if (!textProperties)
return false;
1222 SetElementTypeText(
static_cast<ElementType
>(XMLParser::GetNodeValueDouble(textProperties,
"ElementType")));
1223 SetDataType(
static_cast<DataType
>(XMLParser::GetNodeValueDouble(textProperties,
"DataType")));
1224 SetUnit(
static_cast<ElectricalUnit
>(XMLParser::GetNodeValueDouble(textProperties,
"DataUnit")));
1225 SetDirection(XMLParser::GetNodeValueDouble(textProperties,
"Direction"));
1226 SetDecimalPlaces(XMLParser::GetNodeValueDouble(textProperties,
"DecimalPlaces"));
1227 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.
This class manages the graphical and power elements. It is responsible for handling the user's intera...