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;
75 elementColour = guiColour->eventElement;
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));
141 wxColour elementColour;
144 elementColour = guiColour->eventElement;
146 elementColour = guiColour->enabled;
149 elementColour = guiColour->disable;
151 std::vector<wxPoint> pointListInt;
152 for (
auto& pt : m_pointList) {
153 pointListInt.emplace_back(
static_cast<int>(pt.m_x),
static_cast<int>(pt.m_y));
155 wxPoint pos = wxPoint(
static_cast<int>(m_position.m_x),
static_cast<int>(m_position.m_y));
160 dc.SetPen(wxPen(guiColour->selection, 2 + m_borderSize * 2.0));
161 dc.SetBrush(*wxTRANSPARENT_BRUSH);
163 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
165 dc.SetPen(*wxTRANSPARENT_PEN);
166 dc.SetBrush(wxBrush(guiColour->selection));
169 wxPoint selTriangPts[3];
170 p = m_triangPts[0] + m_position + wxPoint2DDouble(-m_borderSize / scale, -m_borderSize / scale);
171 selTriangPts[0] = RotateAround(p, m_position, m_angle);
172 p = m_triangPts[1] + m_position + wxPoint2DDouble(m_borderSize / scale, -m_borderSize / scale);
173 selTriangPts[1] = RotateAround(p, m_position, m_angle);
174 p = m_triangPts[2] + m_position + wxPoint2DDouble(0.0, m_borderSize / scale);
175 selTriangPts[2] = RotateAround(p, m_position, m_angle);
177 dc.DrawPolygon(3, selTriangPts);
180 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, dc);
184 dc.SetPen(wxPen(elementColour, 2));
185 dc.SetBrush(*wxTRANSPARENT_BRUSH);
186 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
189 dc.SetPen(*wxTRANSPARENT_PEN);
190 dc.SetBrush(wxBrush(elementColour));
197 wxPoint triangPts[3];
200 for (
int i = 0; i < 3; i++) {
201 p = m_triangPts[i] + m_position;
202 triangPts[i] = RotateAround(p, m_position, m_angle);
204 dc.SetPen(*wxTRANSPARENT_PEN);
205 dc.SetBrush(wxBrush(elementColour));
206 dc.DrawPolygon(3, triangPts);
212 double rotAngle = m_rotationAngle;
213 if (!clockwise) rotAngle = -m_rotationAngle;
216 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
219 UpdateSwitchesPosition();
220 UpdatePowerFlowArrowsPosition();
227 wxMenu* textMenu =
new wxMenu();
229 textMenu->Append(ID_TXT_NAME, _(
"Name"));
230 textMenu->Append(ID_TXT_ACTIVE_POWER, _(
"Active power"));
231 textMenu->Append(ID_TXT_REACTIVE_POWER, _(
"Reactive power"));
232 textMenu->SetClientData(menu.GetClientData());
235 menu.AppendSubMenu(textMenu, _(
"Add text"));
243 wxLogDebug(
"Before form constructor");
245 loadForm.CenterOnParent();
246 wxLogDebug(
"Before ShowModal");
247 if (loadForm.ShowModal() == wxID_OK) {
248 wxLogDebug(
"After ShowModal");
258 data.name = m_electricalData.name;
260 data.activePower = m_electricalData.activePower;
261 data.activePowerUnit = m_electricalData.activePowerUnit;
263 data.reactivePower = m_electricalData.reactivePower;
264 data.reactivePowerUnit = m_electricalData.reactivePowerUnit;
266 switch (data.activePowerUnit) {
267 case ElectricalUnit::UNIT_W: {
268 data.activePower = data.activePower / systemPowerBase;
269 data.activePowerUnit = ElectricalUnit::UNIT_PU;
271 case ElectricalUnit::UNIT_kW: {
272 data.activePower = (data.activePower * 1e3) / systemPowerBase;
273 data.activePowerUnit = ElectricalUnit::UNIT_PU;
275 case ElectricalUnit::UNIT_MW: {
276 data.activePower = (data.activePower * 1e6) / systemPowerBase;
277 data.activePowerUnit = ElectricalUnit::UNIT_PU;
282 switch (data.reactivePowerUnit) {
283 case ElectricalUnit::UNIT_var: {
284 data.reactivePower = data.reactivePower / systemPowerBase;
285 data.reactivePowerUnit = ElectricalUnit::UNIT_PU;
287 case ElectricalUnit::UNIT_kvar: {
288 data.reactivePower = (data.reactivePower * 1e3) / systemPowerBase;
289 data.reactivePowerUnit = ElectricalUnit::UNIT_PU;
291 case ElectricalUnit::UNIT_Mvar: {
292 data.reactivePower = (data.reactivePower * 1e6) / systemPowerBase;
293 data.reactivePowerUnit = ElectricalUnit::UNIT_PU;
311 wxString tipText = m_electricalData.name;
314 double activePower = m_electricalData.activePower;
315 double reactivePower = m_electricalData.reactivePower;
320 if (m_online && m_electricalData.loadType == CONST_IMPEDANCE) {
321 std::complex<double> v =
static_cast<Bus*
>(m_parentList[0])->GetElectricalData().voltage;
322 reactivePower *= std::pow(std::abs(v), 2);
323 activePower *= std::pow(std::abs(v), 2);
326 tipText += _(
"\nP = ") + wxString::FromDouble(activePower, 5);
327 switch (m_electricalData.activePowerUnit) {
328 case ElectricalUnit::UNIT_PU: {
329 tipText += _(
" p.u.");
331 case ElectricalUnit::UNIT_W: {
334 case ElectricalUnit::UNIT_kW: {
337 case ElectricalUnit::UNIT_MW: {
343 tipText += _(
"\nQ = ") + wxString::FromDouble(reactivePower, 5);
344 switch (m_electricalData.reactivePowerUnit) {
345 case ElectricalUnit::UNIT_PU: {
346 tipText += _(
" p.u.");
348 case ElectricalUnit::UNIT_var: {
349 tipText += _(
" var");
351 case ElectricalUnit::UNIT_kvar: {
352 tipText += _(
" kvar");
354 case ElectricalUnit::UNIT_Mvar: {
355 tipText += _(
" Mvar");
366 if (!m_electricalData.plotLoad)
return false;
367 plotData.SetName(m_electricalData.name);
368 plotData.SetCurveType(ElementPlotData::CurveType::CT_LOAD);
370 std::vector<double> absVoltage, activePower, reactivePower, current;
371 for (
unsigned int i = 0; i < m_electricalData.voltageVector.size(); ++i) {
372 absVoltage.push_back(std::abs(m_electricalData.voltageVector[i]));
373 activePower.push_back(std::real(m_electricalData.electricalPowerVector[i]));
374 reactivePower.push_back(std::imag(m_electricalData.electricalPowerVector[i]));
375 current.push_back(std::abs(std::complex<double>(activePower[i], -reactivePower[i]) /
376 std::conj(m_electricalData.voltageVector[i])));
379 plotData.AddData(absVoltage, _(
"Voltage"));
380 plotData.AddData(activePower, _(
"Active power"));
381 plotData.AddData(reactivePower, _(
"Reactive power"));
382 plotData.AddData(current, _(
"Current"));
387rapidxml::xml_node<>* Load::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
389 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Load");
390 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
392 SaveCADProperties(doc, elementNode);
394 auto electricalProp = XMLParser::AppendNode(doc, elementNode,
"ElectricalProperties");
395 auto isOnline = XMLParser::AppendNode(doc, electricalProp,
"IsOnline");
396 XMLParser::SetNodeValue(doc, isOnline, m_online);
397 auto name = XMLParser::AppendNode(doc, electricalProp,
"Name");
398 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
399 auto activePower = XMLParser::AppendNode(doc, electricalProp,
"ActivePower");
400 XMLParser::SetNodeValue(doc, activePower, m_electricalData.activePower);
401 XMLParser::SetNodeAttribute(doc, activePower,
"UnitID",
static_cast<int>(m_electricalData.activePowerUnit));
402 auto reactivePower = XMLParser::AppendNode(doc, electricalProp,
"ReactivePower");
403 XMLParser::SetNodeValue(doc, reactivePower, m_electricalData.reactivePower);
404 XMLParser::SetNodeAttribute(doc, reactivePower,
"UnitID",
static_cast<int>(m_electricalData.reactivePowerUnit));
405 auto loadType = XMLParser::AppendNode(doc, electricalProp,
"LoadType");
406 XMLParser::SetNodeValue(doc, loadType, m_electricalData.loadType);
408 auto stability = XMLParser::AppendNode(doc, electricalProp,
"Stability");
409 auto plotLoad = XMLParser::AppendNode(doc, stability,
"PlotLoad");
410 XMLParser::SetNodeValue(doc, plotLoad, m_electricalData.plotLoad);
411 auto useCompLoad = XMLParser::AppendNode(doc, stability,
"UseCompositeLoad");
412 XMLParser::SetNodeValue(doc, useCompLoad, m_electricalData.useCompLoad);
413 auto activePowerCompl = XMLParser::AppendNode(doc, stability,
"ActivePowerComposition");
414 auto pzl = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantImpedance");
415 XMLParser::SetNodeValue(doc, pzl, m_electricalData.constImpedanceActive);
416 auto pil = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantCurrent");
417 XMLParser::SetNodeValue(doc, pil, m_electricalData.constCurrentActive);
418 auto ppl = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantPower");
419 XMLParser::SetNodeValue(doc, ppl, m_electricalData.constPowerActive);
420 auto reactivePowerCompl = XMLParser::AppendNode(doc, stability,
"ReactivePowerComposition");
421 auto qzl = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantImpedance");
422 XMLParser::SetNodeValue(doc, qzl, m_electricalData.constImpedanceReactive);
423 auto qil = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantCurrent");
424 XMLParser::SetNodeValue(doc, qil, m_electricalData.constCurrentReactive);
425 auto qpl = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantPower");
426 XMLParser::SetNodeValue(doc, qpl, m_electricalData.constPowerReactive);
428 SaveSwitchingData(doc, electricalProp);
433bool Load::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
435 if (!OpenCADProperties(elementNode, parentList))
return false;
437 m_triangPts.push_back(wxPoint2DDouble(-m_width / 2.0, -m_height / 2.0));
438 m_triangPts.push_back(wxPoint2DDouble(m_width / 2.0, -m_height / 2.0));
439 m_triangPts.push_back(wxPoint2DDouble(0.0, m_height / 2.0));
441 auto electricalProp = elementNode->first_node(
"ElectricalProperties");
442 if (!electricalProp)
return false;
444 SetOnline(XMLParser::GetNodeValueInt(electricalProp,
"IsOnline"));
445 m_electricalData.name = electricalProp->first_node(
"Name")->value();
446 m_electricalData.activePower = XMLParser::GetNodeValueDouble(electricalProp,
"ActivePower");
447 m_electricalData.activePowerUnit =
448 static_cast<ElectricalUnit
>(XMLParser::GetAttributeValueInt(electricalProp,
"ActivePower",
"UnitID"));
449 m_electricalData.reactivePower = XMLParser::GetNodeValueDouble(electricalProp,
"ReactivePower");
450 m_electricalData.reactivePowerUnit =
451 static_cast<ElectricalUnit
>(XMLParser::GetAttributeValueInt(electricalProp,
"ReactivePower",
"UnitID"));
452 m_electricalData.loadType =
static_cast<LoadType
>(XMLParser::GetNodeValueInt(electricalProp,
"LoadType"));
454 auto stability = electricalProp->first_node(
"Stability");
456 m_electricalData.plotLoad = XMLParser::GetNodeValueInt(stability,
"PlotLoad");
457 m_electricalData.useCompLoad = XMLParser::GetNodeValueInt(stability,
"UseCompositeLoad");
458 auto activePowerComp = stability->first_node(
"ActivePowerComposition");
459 m_electricalData.constImpedanceActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantImpedance");
460 m_electricalData.constCurrentActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantCurrent");
461 m_electricalData.constPowerActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantPower");
462 auto reactivePowerComp = stability->first_node(
"ReactivePowerComposition");
463 m_electricalData.constImpedanceReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantImpedance");
464 m_electricalData.constCurrentReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantCurrent");
465 m_electricalData.constPowerReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantPower");
468 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 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 bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
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