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();
131void Load::DrawDC(wxPoint2DDouble translation,
double scale, wxGraphicsContext* gc)
const
133 wxColour elementColour;
136 elementColour = m_dynamicEventColour;
138 elementColour = m_onlineElementColour;
141 elementColour = m_offlineElementColour;
146 gc->SetPen(wxPen(m_selectionColour, 2 + m_borderSize * 2.0));
147 gc->SetBrush(*wxTRANSPARENT_BRUSH);
149 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
151 gc->SetPen(*wxTRANSPARENT_PEN);
152 gc->SetBrush(wxBrush(m_selectionColour));
154 std::vector<wxPoint2DDouble> selTriangPts;
155 selTriangPts.push_back(m_triangPts[0] + m_position +
156 wxPoint2DDouble(-m_borderSize / scale, -m_borderSize / scale));
157 selTriangPts.push_back(m_triangPts[1] + m_position +
158 wxPoint2DDouble(m_borderSize / scale, -m_borderSize / scale));
159 selTriangPts.push_back(m_triangPts[2] + m_position + wxPoint2DDouble(0.0, m_borderSize / scale));
164 gc->Translate(m_position.m_x, m_position.m_y);
165 gc->Rotate(wxDegToRad(m_angle));
166 gc->Translate(-m_position.m_x, -m_position.m_y);
171 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, gc);
175 gc->SetPen(wxPen(elementColour, 2));
176 gc->SetBrush(*wxTRANSPARENT_BRUSH);
177 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
180 gc->SetPen(*wxTRANSPARENT_PEN);
181 gc->SetBrush(wxBrush(elementColour));
187 std::vector<wxPoint2DDouble> triangPts;
188 for (
int i = 0; i < 3; i++) { triangPts.push_back(m_triangPts[i] + m_position); }
190 gc->Translate(m_position.m_x, m_position.m_y);
191 gc->Rotate(wxDegToRad(m_angle));
192 gc->Translate(-m_position.m_x, -m_position.m_y);
193 gc->SetPen(*wxTRANSPARENT_PEN);
194 gc->SetBrush(wxBrush(elementColour));
200void Load::DrawDC(wxPoint2DDouble translation,
double scale, wxDC& dc)
const
202 wxColour elementColour;
205 elementColour = m_dynamicEventColour;
207 elementColour = m_onlineElementColour;
210 elementColour = m_offlineElementColour;
212 std::vector<wxPoint> pointListInt;
213 for (
auto& pt : m_pointList) {
214 pointListInt.emplace_back(
static_cast<int>(pt.m_x),
static_cast<int>(pt.m_y));
216 wxPoint pos = wxPoint(
static_cast<int>(m_position.m_x),
static_cast<int>(m_position.m_y));
221 dc.SetPen(wxPen(m_selectionColour, 2 + m_borderSize * 2.0));
222 dc.SetBrush(*wxTRANSPARENT_BRUSH);
224 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
226 dc.SetPen(*wxTRANSPARENT_PEN);
227 dc.SetBrush(wxBrush(m_selectionColour));
230 wxPoint selTriangPts[3];
231 p = m_triangPts[0] + m_position + wxPoint2DDouble(-m_borderSize / scale, -m_borderSize / scale);
232 selTriangPts[0] = RotateAround(p, m_position, m_angle);
233 p = m_triangPts[1] + m_position + wxPoint2DDouble(m_borderSize / scale, -m_borderSize / scale);
234 selTriangPts[1] = RotateAround(p, m_position, m_angle);
235 p = m_triangPts[2] + m_position + wxPoint2DDouble(0.0, m_borderSize / scale);
236 selTriangPts[2] = RotateAround(p, m_position, m_angle);
238 dc.DrawPolygon(3, selTriangPts);
241 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, dc);
245 dc.SetPen(wxPen(elementColour, 2));
246 dc.SetBrush(*wxTRANSPARENT_BRUSH);
247 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
250 dc.SetPen(*wxTRANSPARENT_PEN);
251 dc.SetBrush(wxBrush(elementColour));
258 wxPoint triangPts[3];
261 for (
int i = 0; i < 3; i++) {
262 p = m_triangPts[i] + m_position;
263 triangPts[i] = RotateAround(p, m_position, m_angle);
265 dc.SetPen(*wxTRANSPARENT_PEN);
266 dc.SetBrush(wxBrush(elementColour));
267 dc.DrawPolygon(3, triangPts);
273 double rotAngle = m_rotationAngle;
274 if (!clockwise) rotAngle = -m_rotationAngle;
277 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
280 UpdateSwitchesPosition();
281 UpdatePowerFlowArrowsPosition();
288 wxMenu* textMenu =
new wxMenu();
290 textMenu->Append(ID_TXT_NAME, _(
"Name"));
291 textMenu->Append(ID_TXT_ACTIVE_POWER, _(
"Active power"));
292 textMenu->Append(ID_TXT_REACTIVE_POWER, _(
"Reactive power"));
293 textMenu->SetClientData(menu.GetClientData());
296 menu.AppendSubMenu(textMenu, _(
"Add text"));
304 wxLogDebug(
"Before form constructor");
306 loadForm.CenterOnParent();
307 wxLogDebug(
"Before ShowModal");
308 if (loadForm.ShowModal() == wxID_OK) {
309 wxLogDebug(
"After ShowModal");
319 data.activePower = m_electricalData.activePower;
320 data.activePowerUnit = m_electricalData.activePowerUnit;
322 data.reactivePower = m_electricalData.reactivePower;
323 data.reactivePowerUnit = m_electricalData.reactivePowerUnit;
325 switch (data.activePowerUnit) {
327 data.activePower = data.activePower / systemPowerBase;
331 data.activePower = (data.activePower * 1e3) / systemPowerBase;
335 data.activePower = (data.activePower * 1e6) / systemPowerBase;
341 switch (data.reactivePowerUnit) {
343 data.reactivePower = data.reactivePower / systemPowerBase;
347 data.reactivePower = (data.reactivePower * 1e3) / systemPowerBase;
351 data.reactivePower = (data.reactivePower * 1e6) / systemPowerBase;
370 wxString tipText = m_electricalData.name;
373 double activePower = m_electricalData.activePower;
374 double reactivePower = m_electricalData.reactivePower;
379 if (m_online && m_electricalData.loadType == CONST_IMPEDANCE) {
380 std::complex<double> v =
static_cast<Bus*
>(m_parentList[0])->GetElectricalData().voltage;
381 reactivePower *= std::pow(std::abs(v), 2);
382 activePower *= std::pow(std::abs(v), 2);
385 tipText += _(
"\nP = ") + wxString::FromDouble(activePower, 5);
386 switch (m_electricalData.activePowerUnit) {
388 tipText += _(
" p.u.");
402 tipText += _(
"\nQ = ") + wxString::FromDouble(reactivePower, 5);
403 switch (m_electricalData.reactivePowerUnit) {
405 tipText += _(
" p.u.");
408 tipText += _(
" var");
411 tipText += _(
" kvar");
414 tipText += _(
" Mvar");
425 if (!m_electricalData.plotLoad)
return false;
426 plotData.SetName(m_electricalData.name);
427 plotData.SetCurveType(ElementPlotData::CurveType::CT_LOAD);
429 std::vector<double> absVoltage, activePower, reactivePower, current;
430 for (
unsigned int i = 0; i < m_electricalData.voltageVector.size(); ++i) {
431 absVoltage.push_back(std::abs(m_electricalData.voltageVector[i]));
432 activePower.push_back(std::real(m_electricalData.electricalPowerVector[i]));
433 reactivePower.push_back(std::imag(m_electricalData.electricalPowerVector[i]));
434 current.push_back(std::abs(std::complex<double>(activePower[i], -reactivePower[i]) /
435 std::conj(m_electricalData.voltageVector[i])));
438 plotData.AddData(absVoltage, _(
"Voltage"));
439 plotData.AddData(activePower, _(
"Active power"));
440 plotData.AddData(reactivePower, _(
"Reactive power"));
441 plotData.AddData(current, _(
"Current"));
446rapidxml::xml_node<>* Load::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
448 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Load");
449 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
451 SaveCADProperties(doc, elementNode);
453 auto electricalProp = XMLParser::AppendNode(doc, elementNode,
"ElectricalProperties");
454 auto isOnline = XMLParser::AppendNode(doc, electricalProp,
"IsOnline");
455 XMLParser::SetNodeValue(doc, isOnline, m_online);
456 auto name = XMLParser::AppendNode(doc, electricalProp,
"Name");
457 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
458 auto activePower = XMLParser::AppendNode(doc, electricalProp,
"ActivePower");
459 XMLParser::SetNodeValue(doc, activePower, m_electricalData.activePower);
460 XMLParser::SetNodeAttribute(doc, activePower,
"UnitID",
static_cast<int>(m_electricalData.activePowerUnit));
461 auto reactivePower = XMLParser::AppendNode(doc, electricalProp,
"ReactivePower");
462 XMLParser::SetNodeValue(doc, reactivePower, m_electricalData.reactivePower);
463 XMLParser::SetNodeAttribute(doc, reactivePower,
"UnitID",
static_cast<int>(m_electricalData.reactivePowerUnit));
464 auto loadType = XMLParser::AppendNode(doc, electricalProp,
"LoadType");
465 XMLParser::SetNodeValue(doc, loadType, m_electricalData.loadType);
467 auto stability = XMLParser::AppendNode(doc, electricalProp,
"Stability");
468 auto plotLoad = XMLParser::AppendNode(doc, stability,
"PlotLoad");
469 XMLParser::SetNodeValue(doc, plotLoad, m_electricalData.plotLoad);
470 auto useCompLoad = XMLParser::AppendNode(doc, stability,
"UseCompositeLoad");
471 XMLParser::SetNodeValue(doc, useCompLoad, m_electricalData.useCompLoad);
472 auto activePowerCompl = XMLParser::AppendNode(doc, stability,
"ActivePowerComposition");
473 auto pzl = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantImpedance");
474 XMLParser::SetNodeValue(doc, pzl, m_electricalData.constImpedanceActive);
475 auto pil = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantCurrent");
476 XMLParser::SetNodeValue(doc, pil, m_electricalData.constCurrentActive);
477 auto ppl = XMLParser::AppendNode(doc, activePowerCompl,
"ConstantPower");
478 XMLParser::SetNodeValue(doc, ppl, m_electricalData.constPowerActive);
479 auto reactivePowerCompl = XMLParser::AppendNode(doc, stability,
"ReactivePowerComposition");
480 auto qzl = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantImpedance");
481 XMLParser::SetNodeValue(doc, qzl, m_electricalData.constImpedanceReactive);
482 auto qil = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantCurrent");
483 XMLParser::SetNodeValue(doc, qil, m_electricalData.constCurrentReactive);
484 auto qpl = XMLParser::AppendNode(doc, reactivePowerCompl,
"ConstantPower");
485 XMLParser::SetNodeValue(doc, qpl, m_electricalData.constPowerReactive);
487 SaveSwitchingData(doc, electricalProp);
492bool Load::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
494 if (!OpenCADProperties(elementNode, parentList))
return false;
496 m_triangPts.push_back(wxPoint2DDouble(-m_width / 2.0, -m_height / 2.0));
497 m_triangPts.push_back(wxPoint2DDouble(m_width / 2.0, -m_height / 2.0));
498 m_triangPts.push_back(wxPoint2DDouble(0.0, m_height / 2.0));
500 auto electricalProp = elementNode->first_node(
"ElectricalProperties");
501 if (!electricalProp)
return false;
503 SetOnline(XMLParser::GetNodeValueInt(electricalProp,
"IsOnline"));
504 m_electricalData.name = electricalProp->first_node(
"Name")->value();
505 m_electricalData.activePower = XMLParser::GetNodeValueDouble(electricalProp,
"ActivePower");
506 m_electricalData.activePowerUnit =
507 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"ActivePower",
"UnitID"));
508 m_electricalData.reactivePower = XMLParser::GetNodeValueDouble(electricalProp,
"ReactivePower");
509 m_electricalData.reactivePowerUnit =
510 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"ReactivePower",
"UnitID"));
511 m_electricalData.loadType =
static_cast<LoadType
>(XMLParser::GetNodeValueInt(electricalProp,
"LoadType"));
513 auto stability = electricalProp->first_node(
"Stability");
515 m_electricalData.plotLoad = XMLParser::GetNodeValueInt(stability,
"PlotLoad");
516 m_electricalData.useCompLoad = XMLParser::GetNodeValueInt(stability,
"UseCompositeLoad");
517 auto activePowerComp = stability->first_node(
"ActivePowerComposition");
518 m_electricalData.constImpedanceActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantImpedance");
519 m_electricalData.constCurrentActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantCurrent");
520 m_electricalData.constPowerActive = XMLParser::GetNodeValueDouble(activePowerComp,
"ConstantPower");
521 auto reactivePowerComp = stability->first_node(
"ReactivePowerComposition");
522 m_electricalData.constImpedanceReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantImpedance");
523 m_electricalData.constCurrentReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantCurrent");
524 m_electricalData.constPowerReactive = XMLParser::GetNodeValueDouble(reactivePowerComp,
"ConstantPower");
527 if (!OpenSwitchingData(electricalProp))
return false;
ElectricalUnit
Electrical units.
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 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 DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
virtual void SetDynamicEvent(bool dynEvent=true)
Set if the power element have dynamic event.
virtual void DrawDCSwitches(wxGraphicsContext *gc) const
Draw switch.
virtual void UpdateSwitches()
Update the switch position.
virtual void DrawDCPowerFlowPts(wxGraphicsContext *gc) const
Draw power flow arrows.
virtual wxPoint2DDouble GetSwitchPoint(Element *parent, wxPoint2DDouble parentPoint, wxPoint2DDouble secondPoint) const
Get the correct switch position.
Abstract class for shunt power elements.
std::vector< double > swTime