23 m_elementType = TYPE_LOAD;
26Load::Load(wxString name) :
Shunt()
28 m_elementType = TYPE_LOAD;
29 m_electricalData.name = name;
37 m_parentList.push_back(parent);
39 wxPoint2DDouble parentPt =
44 m_position = parentPt + wxPoint2DDouble(0.0, 100.0);
45 m_width = m_height = 20.0;
46 m_rect = wxRect2DDouble(m_position.m_x - 10.0, m_position.m_y - 10.0, m_width, m_height);
48 m_pointList.push_back(parentPt);
49 m_pointList.push_back(
GetSwitchPoint(parent, parentPt, m_position));
50 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -20.0));
51 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -10.0));
53 m_triangPts.push_back(wxPoint2DDouble(-m_width / 2.0, -m_height / 2.0));
54 m_triangPts.push_back(wxPoint2DDouble(m_width / 2.0, -m_height / 2.0));
55 m_triangPts.push_back(wxPoint2DDouble(0.0, m_height / 2.0));
59 wxRect2DDouble genRect(0, 0, 0, 0);
60 m_switchRect.push_back(genRect);
63 UpdatePowerFlowArrowsPosition();
72 wxColour elementColour;
77 elementColour = guiColour->enabled;
80 elementColour = guiColour->disable;
85 gc->SetPen(wxPen(guiColour->selection, 2 + m_borderSize * 2.0));
86 gc->SetBrush(*wxTRANSPARENT_BRUSH);
88 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
90 gc->SetPen(*wxTRANSPARENT_PEN);
91 gc->SetBrush(wxBrush(guiColour->selection));
93 std::vector<wxPoint2DDouble> selTriangPts;
94 selTriangPts.push_back(m_triangPts[0] + m_position +
95 wxPoint2DDouble(-m_borderSize / scale, -m_borderSize / scale));
96 selTriangPts.push_back(m_triangPts[1] + m_position +
97 wxPoint2DDouble(m_borderSize / scale, -m_borderSize / scale));
98 selTriangPts.push_back(m_triangPts[2] + m_position + wxPoint2DDouble(0.0, m_borderSize / scale));
103 gc->Translate(m_position.m_x, m_position.m_y);
104 gc->Rotate(wxDegToRad(m_angle));
105 gc->Translate(-m_position.m_x, -m_position.m_y);
110 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, gc);
114 gc->SetPen(wxPen(elementColour, 2));
115 gc->SetBrush(*wxTRANSPARENT_BRUSH);
116 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
119 gc->SetPen(*wxTRANSPARENT_PEN);
120 gc->SetBrush(wxBrush(elementColour));
126 std::vector<wxPoint2DDouble> triangPts;
127 for (
int i = 0; i < 3; i++) { triangPts.push_back(m_triangPts[i] + m_position); }
129 gc->Translate(m_position.m_x, m_position.m_y);
130 gc->Rotate(wxDegToRad(m_angle));
131 gc->Translate(-m_position.m_x, -m_position.m_y);
132 gc->SetPen(*wxTRANSPARENT_PEN);
133 gc->SetBrush(wxBrush(elementColour));
138 DrawStabilityEventGC(gc, translation, scale, guiColour);
145 wxColour elementColour;
148 elementColour = guiColour->eventElement;
150 elementColour = guiColour->enabled;
153 elementColour = guiColour->disable;
155 std::vector<wxPoint> pointListInt;
156 for (
auto& pt : m_pointList) {
157 pointListInt.emplace_back(
static_cast<int>(pt.m_x),
static_cast<int>(pt.m_y));
159 wxPoint pos = wxPoint(
static_cast<int>(m_position.m_x),
static_cast<int>(m_position.m_y));
164 dc.SetPen(wxPen(guiColour->selection, 2 + m_borderSize * 2.0));
165 dc.SetBrush(*wxTRANSPARENT_BRUSH);
167 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
169 dc.SetPen(*wxTRANSPARENT_PEN);
170 dc.SetBrush(wxBrush(guiColour->selection));
173 wxPoint selTriangPts[3];
174 p = m_triangPts[0] + m_position + wxPoint2DDouble(-m_borderSize / scale, -m_borderSize / scale);
175 selTriangPts[0] = RotateAround(p, m_position, m_angle);
176 p = m_triangPts[1] + m_position + wxPoint2DDouble(m_borderSize / scale, -m_borderSize / scale);
177 selTriangPts[1] = RotateAround(p, m_position, m_angle);
178 p = m_triangPts[2] + m_position + wxPoint2DDouble(0.0, m_borderSize / scale);
179 selTriangPts[2] = RotateAround(p, m_position, m_angle);
181 dc.DrawPolygon(3, selTriangPts);
184 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, dc);
188 dc.SetPen(wxPen(elementColour, 2));
189 dc.SetBrush(*wxTRANSPARENT_BRUSH);
190 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
193 dc.SetPen(*wxTRANSPARENT_PEN);
194 dc.SetBrush(wxBrush(elementColour));
201 wxPoint triangPts[3];
204 for (
int i = 0; i < 3; i++) {
205 p = m_triangPts[i] + m_position;
206 triangPts[i] = RotateAround(p, m_position, m_angle);
208 dc.SetPen(*wxTRANSPARENT_PEN);
209 dc.SetBrush(wxBrush(elementColour));
210 dc.DrawPolygon(3, triangPts);
216 double rotAngle = m_rotationAngle;
217 if (!clockwise) rotAngle = -m_rotationAngle;
220 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
223 UpdateSwitchesPosition();
224 UpdatePowerFlowArrowsPosition();
231 wxMenu* textMenu =
new wxMenu();
233 textMenu->Append(ID_TXT_NAME, _(
"Name"));
234 textMenu->Append(ID_TXT_ACTIVE_POWER, _(
"Active power"));
235 textMenu->Append(ID_TXT_REACTIVE_POWER, _(
"Reactive power"));
236 textMenu->SetClientData(menu.GetClientData());
239 menu.AppendSubMenu(textMenu, _(
"Add text"));
247 wxLogDebug(
"Before form constructor");
249 loadForm.CenterOnParent();
250 wxLogDebug(
"Before ShowModal");
251 if (loadForm.ShowModal() == wxID_OK) {
252 wxLogDebug(
"After ShowModal");
262 data.name = m_electricalData.name;
264 data.activePower = m_electricalData.activePower;
265 data.activePowerUnit = m_electricalData.activePowerUnit;
267 data.reactivePower = m_electricalData.reactivePower;
268 data.reactivePowerUnit = m_electricalData.reactivePowerUnit;
270 switch (data.activePowerUnit) {
271 case ElectricalUnit::UNIT_W: {
272 data.activePower = data.activePower / systemPowerBase;
273 data.activePowerUnit = ElectricalUnit::UNIT_PU;
275 case ElectricalUnit::UNIT_kW: {
276 data.activePower = (data.activePower * 1e3) / systemPowerBase;
277 data.activePowerUnit = ElectricalUnit::UNIT_PU;
279 case ElectricalUnit::UNIT_MW: {
280 data.activePower = (data.activePower * 1e6) / systemPowerBase;
281 data.activePowerUnit = ElectricalUnit::UNIT_PU;
286 switch (data.reactivePowerUnit) {
287 case ElectricalUnit::UNIT_var: {
288 data.reactivePower = data.reactivePower / systemPowerBase;
289 data.reactivePowerUnit = ElectricalUnit::UNIT_PU;
291 case ElectricalUnit::UNIT_kvar: {
292 data.reactivePower = (data.reactivePower * 1e3) / systemPowerBase;
293 data.reactivePowerUnit = ElectricalUnit::UNIT_PU;
295 case ElectricalUnit::UNIT_Mvar: {
296 data.reactivePower = (data.reactivePower * 1e6) / systemPowerBase;
297 data.reactivePowerUnit = ElectricalUnit::UNIT_PU;
315 wxString tipText = m_electricalData.name;
318 double activePower = m_electricalData.activePower;
319 double reactivePower = m_electricalData.reactivePower;
324 if (m_online && m_electricalData.loadType == CONST_IMPEDANCE) {
325 std::complex<double> v =
static_cast<Bus*
>(m_parentList[0])->GetElectricalData().voltage;
326 reactivePower *= std::pow(std::abs(v), 2);
327 activePower *= std::pow(std::abs(v), 2);
330 tipText += _(
"\nP = ") + wxString::FromDouble(activePower, 5);
331 switch (m_electricalData.activePowerUnit) {
332 case ElectricalUnit::UNIT_PU: {
333 tipText += _(
" p.u.");
335 case ElectricalUnit::UNIT_W: {
338 case ElectricalUnit::UNIT_kW: {
341 case ElectricalUnit::UNIT_MW: {
347 tipText += _(
"\nQ = ") + wxString::FromDouble(reactivePower, 5);
348 switch (m_electricalData.reactivePowerUnit) {
349 case ElectricalUnit::UNIT_PU: {
350 tipText += _(
" p.u.");
352 case ElectricalUnit::UNIT_var: {
353 tipText += _(
" var");
355 case ElectricalUnit::UNIT_kvar: {
356 tipText += _(
" kvar");
358 case ElectricalUnit::UNIT_Mvar: {
359 tipText += _(
" Mvar");
370 if (!m_electricalData.plotLoad)
return false;
371 plotData.SetName(m_electricalData.name);
372 plotData.SetCurveType(ElementPlotData::CurveType::CT_LOAD);
374 std::vector<double> absVoltage, activePower, reactivePower, current;
375 for (
unsigned int i = 0; i < m_electricalData.voltageVector.size(); ++i) {
376 absVoltage.push_back(std::abs(m_electricalData.voltageVector[i]));
377 activePower.push_back(std::real(m_electricalData.electricalPowerVector[i]));
378 reactivePower.push_back(std::imag(m_electricalData.electricalPowerVector[i]));
379 current.push_back(std::abs(std::complex<double>(activePower[i], -reactivePower[i]) /
380 std::conj(m_electricalData.voltageVector[i])));
383 plotData.AddData(absVoltage, _(
"Voltage"));
384 plotData.AddData(activePower, _(
"Active power"));
385 plotData.AddData(reactivePower, _(
"Reactive power"));
386 plotData.AddData(current, _(
"Current"));
391rapidxml::xml_node<>* Load::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
393 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Load");
394 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
396 SaveCADProperties(doc, elementNode);
398 auto electricalProp = XMLParser::AppendNode(doc, elementNode,
"ElectricalProperties");
399 auto isOnline = XMLParser::AppendNode(doc, electricalProp,
"IsOnline");
400 XMLParser::SetNodeValue(doc, isOnline, m_online);
401 auto name = XMLParser::AppendNode(doc, electricalProp,
"Name");
402 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
403 auto activePower = XMLParser::AppendNode(doc, electricalProp,
"ActivePower");
404 XMLParser::SetNodeValue(doc, activePower, m_electricalData.activePower);
405 XMLParser::SetNodeAttribute(doc, activePower,
"UnitID",
static_cast<int>(m_electricalData.activePowerUnit));
406 auto reactivePower = XMLParser::AppendNode(doc, electricalProp,
"ReactivePower");
407 XMLParser::SetNodeValue(doc, reactivePower, m_electricalData.reactivePower);
408 XMLParser::SetNodeAttribute(doc, reactivePower,
"UnitID",
static_cast<int>(m_electricalData.reactivePowerUnit));
409 auto loadType = XMLParser::AppendNode(doc, electricalProp,
"LoadType");
410 XMLParser::SetNodeValue(doc, loadType, m_electricalData.loadType);
412 auto stability = XMLParser::AppendNode(doc, electricalProp,
"Stability");
413 auto plotLoad = XMLParser::AppendNode(doc, stability,
"PlotLoad");
414 XMLParser::SetNodeValue(doc, plotLoad, m_electricalData.plotLoad);
415 auto useCompLoad = XMLParser::AppendNode(doc, stability,
"UseCompositeLoad");
416 XMLParser::SetNodeValue(doc, useCompLoad, m_electricalData.useCompLoad);
417 auto activePowerCompl = XMLParser::AppendNode(doc, stability,
"ActivePowerComposition");
418 auto pzl = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantImpedance");
419 XMLParser::SetNodeValue(doc, pzl, m_electricalData.constImpedanceActive);
420 auto pil = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantCurrent");
421 XMLParser::SetNodeValue(doc, pil, m_electricalData.constCurrentActive);
422 auto ppl = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantPower");
423 XMLParser::SetNodeValue(doc, ppl, m_electricalData.constPowerActive);
424 auto reactivePowerCompl = XMLParser::AppendNode(doc, stability,
"ReactivePowerComposition");
425 auto qzl = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantImpedance");
426 XMLParser::SetNodeValue(doc, qzl, m_electricalData.constImpedanceReactive);
427 auto qil = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantCurrent");
428 XMLParser::SetNodeValue(doc, qil, m_electricalData.constCurrentReactive);
429 auto qpl = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantPower");
430 XMLParser::SetNodeValue(doc, qpl, m_electricalData.constPowerReactive);
432 SaveSwitchingData(doc, electricalProp);
437bool Load::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
439 if (!OpenCADProperties(elementNode, parentList))
return false;
441 m_triangPts.push_back(wxPoint2DDouble(-m_width / 2.0, -m_height / 2.0));
442 m_triangPts.push_back(wxPoint2DDouble(m_width / 2.0, -m_height / 2.0));
443 m_triangPts.push_back(wxPoint2DDouble(0.0, m_height / 2.0));
445 auto electricalProp = elementNode->first_node(
"ElectricalProperties");
446 if (!electricalProp)
return false;
448 SetOnline(XMLParser::GetNodeValueInt(electricalProp,
"IsOnline"));
449 m_electricalData.name = electricalProp->first_node(
"Name")->value();
450 m_electricalData.activePower = XMLParser::GetNodeValueDouble(electricalProp,
"ActivePower");
451 m_electricalData.activePowerUnit =
452 static_cast<ElectricalUnit
>(XMLParser::GetAttributeValueInt(electricalProp,
"ActivePower",
"UnitID"));
453 m_electricalData.reactivePower = XMLParser::GetNodeValueDouble(electricalProp,
"ReactivePower");
454 m_electricalData.reactivePowerUnit =
455 static_cast<ElectricalUnit
>(XMLParser::GetAttributeValueInt(electricalProp,
"ReactivePower",
"UnitID"));
456 m_electricalData.loadType =
static_cast<LoadType
>(XMLParser::GetNodeValueInt(electricalProp,
"LoadType"));
458 auto stability = electricalProp->first_node(
"Stability");
460 m_electricalData.plotLoad = XMLParser::GetNodeValueInt(stability,
"PlotLoad");
461 m_electricalData.useCompLoad = XMLParser::GetNodeValueInt(stability,
"UseCompositeLoad");
462 auto activePowerComp = stability->first_node(
"ActivePowerComposition");
463 m_electricalData.constImpedanceActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantImpedance");
464 m_electricalData.constCurrentActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantCurrent");
465 m_electricalData.constPowerActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantPower");
466 auto reactivePowerComp = stability->first_node(
"ReactivePowerComposition");
467 m_electricalData.constImpedanceReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantImpedance");
468 m_electricalData.constCurrentReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantCurrent");
469 m_electricalData.constPowerReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantPower");
472 if (!OpenSwitchingData(electricalProp))
return false;
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 void GeneralMenuItens(wxMenu &menu)
Insert general itens to context menu.
wxPoint2DDouble GetPosition() const
Get the element position.
double GetAngle() const
Get the element angle.
virtual void DrawDCTriangle(std::vector< wxPoint2DDouble > points, wxGraphicsContext *gc) const
Draw 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.
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.
Loas shunt power element.
virtual wxString GetTipText() const
Get the tip text.
virtual void DrawDC(GUIColour *guiColour, wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
virtual bool GetContextMenu(wxMenu &menu)
Get the element contex menu.
virtual Element * GetCopy()
Get a the element copy.
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual bool AddParent(Element *parent, wxPoint2DDouble position, bool isOpening=false)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
virtual bool GetPlotData(ElementPlotData &plotData, PlotStudy study=PlotStudy::STABILITY)
Fill the plot data.
virtual bool ShowForm(wxWindow *parent, Element *element, wxWindow *workspace=nullptr)
Show element data form.
virtual void SetDynamicEvent(bool dynEvent=true)
Set if the power element have dynamic event.
virtual void DrawDCPowerFlowPts(GUIColour *guiColour, wxGraphicsContext *gc) const
Draw power flow arrows.
virtual void UpdateSwitches()
Update the switch position.
virtual void DrawDCSwitches(GUIColour *guiColour, wxGraphicsContext *gc) const
Draw switch.
virtual wxPoint2DDouble GetSwitchPoint(Element *parent, wxPoint2DDouble parentPoint, wxPoint2DDouble secondPoint) const
Get the correct switch position.
Abstract class for shunt power elements.
std::vector< double > swTime