20#include "DegreesAndRadians.h"
26 m_busColour.Set(0, 78, 255, 255);
27 m_onlineElementColour.Set(51, 51, 51, 255);
28 m_offlineElementColour.Set(128, 128, 128, 255);
29 m_closedSwitchColour.Set(0, 102, 0, 255);
30 m_openedSwitchColour.Set(255, 26, 26, 255);
31 m_powerFlowArrowColour.Set(255, 130, 0, 255);
32 m_dynamicEventColour.Set(255, 130, 0, 255);
40 wxPoint2DDouble parentPoint,
41 wxPoint2DDouble secondPoint)
const
43 double swLineSize = 25.0;
44 wxPoint2DDouble swPoint = wxPoint2DDouble(parentPoint.m_x, parentPoint.m_y - swLineSize);
50 wxPoint2DDouble(std::cos(wxDegToRad(-angle)) * (secondPoint.m_x - parentPoint.m_x) -
51 std::sin(wxDegToRad(-angle)) * (secondPoint.m_y - parentPoint.m_y) + parentPoint.m_x,
52 std::sin(wxDegToRad(-angle)) * (secondPoint.m_x - parentPoint.m_x) +
53 std::cos(wxDegToRad(-angle)) * (secondPoint.m_y - parentPoint.m_y) + parentPoint.m_y);
56 if(secondPoint.m_y > parentPoint.m_y) angle -= 180.0;
57 return wxPoint2DDouble(std::cos(wxDegToRad(angle)) * (swPoint.m_x - parentPoint.m_x) -
58 std::sin(wxDegToRad(angle)) * (swPoint.m_y - parentPoint.m_y) + parentPoint.m_x,
59 std::sin(wxDegToRad(angle)) * (swPoint.m_x - parentPoint.m_x) +
60 std::cos(wxDegToRad(angle)) * (swPoint.m_y - parentPoint.m_y) + parentPoint.m_y);
65 for(
int i = 0; i < (int)m_switchRect.size(); i++) {
67 if(m_switchRect[i].
Contains(position))
return true;
76 wxPoint2DDouble swCenter = wxPoint2DDouble((m_pointList[0].m_x + m_pointList[1].m_x) / 2.0,
77 (m_pointList[0].m_y + m_pointList[1].m_y) / 2.0);
78 m_switchRect[0] = wxRect2DDouble(swCenter.m_x - m_switchSize / 2.0, swCenter.m_y - m_switchSize / 2.0, m_switchSize,
112 gc->SetPen(*wxTRANSPARENT_PEN);
115 for (
auto parent : m_parentList) {
118 gc->SetBrush(wxBrush(guiColour->swClose));
121 gc->SetBrush(wxBrush(guiColour->swOpen));
125 gc->Translate(m_switchRect[i].
GetPosition().m_x + m_switchSize / 2.0,
126 m_switchRect[i].GetPosition().m_y + m_switchSize / 2.0);
127 gc->Rotate(wxDegToRad(parent->GetAngle()));
128 gc->Translate(-m_switchRect[i].
GetPosition().m_x - m_switchSize / 2.0,
129 -m_switchRect[i].GetPosition().m_y - m_switchSize / 2.0);
131 wxPoint2DDouble switchPos = m_switchRect[i].GetPosition();
132 gc->DrawRectangle(switchPos.m_x, switchPos.m_y, m_switchSize, m_switchSize);
142 dc.SetPen(*wxTRANSPARENT_PEN);
145 for (
auto parent : m_parentList) {
148 dc.SetBrush(wxBrush(guiColour->swClose));
151 dc.SetBrush(wxBrush(guiColour->swOpen));
155 m_switchSize, m_switchSize, parent->GetAngle(), dc);
163 double arrowRate = 100.0;
165 if(edges.size() < 2)
return;
168 for(
int i = 0; i < (int)m_powerFlowArrow.size(); i++) m_powerFlowArrow[i].clear();
169 m_powerFlowArrow.clear();
171 for(
int i = 1; i < (int)edges.size(); i++) {
172 wxPoint2DDouble pt1 = edges[i - 1];
173 wxPoint2DDouble pt2 = edges[i];
175 double angle = std::atan2(pt2.m_y - pt1.m_y, pt2.m_x - pt1.m_x);
177 wxPoint2DDouble rotPt2(
178 std::cos(-angle) * (pt2.m_x - pt1.m_x) - std::sin(-angle) * (pt2.m_y - pt1.m_y) + pt1.m_x,
179 std::sin(-angle) * (pt2.m_x - pt1.m_x) + std::cos(-angle) * (pt2.m_y - pt1.m_y) + pt1.m_y);
181 int numArrows = std::abs(pt1.m_x - rotPt2.m_x) / arrowRate;
182 if(numArrows == 0) numArrows = 1;
184 for(
int i = 0; i < numArrows; i++) {
185 wxPoint2DDouble arrowCenter(pt1.m_x + ((rotPt2.m_x - pt1.m_x) /
double(numArrows + 1)) *
double(i + 1),
186 pt1.m_y + ((rotPt2.m_y - pt1.m_y) /
double(numArrows + 1)) *
double(i + 1));
188 std::vector<wxPoint2DDouble> triPts;
189 triPts.push_back(arrowCenter + wxPoint2DDouble(5.0, 0.0));
190 triPts.push_back(arrowCenter + wxPoint2DDouble(-5.0, 5.0));
191 triPts.push_back(arrowCenter + wxPoint2DDouble(-5.0, -5.0));
194 for(
int i = 0; i < 3; i++) {
195 triPts[i] = wxPoint2DDouble(
196 std::cos(angle) * (triPts[i].m_x - pt1.m_x) - std::sin(angle) * (triPts[i].m_y - pt1.m_y) + pt1.m_x,
197 std::sin(angle) * (triPts[i].m_x - pt1.m_x) + std::cos(angle) * (triPts[i].m_y - pt1.m_y) +
200 m_powerFlowArrow.push_back(triPts);
215 gc->SetPen(*wxTRANSPARENT_PEN);
217 gc->SetBrush(wxBrush(guiColour->pfArrow));
218 for (
auto arrow : m_powerFlowArrow) {
DrawDCTriangle(arrow, gc); }
224 dc.SetPen(*wxTRANSPARENT_PEN);
226 dc.SetBrush(wxBrush(guiColour->pfArrow));
227 for (
auto arrow : m_powerFlowArrow) {
228 std::vector<wxPoint> arrowPts;
229 for (
auto& pt : arrow) {
230 arrowPts.emplace_back(
static_cast<int>(pt.m_x),
static_cast<int>(pt.m_y));
237double PowerElement::GetValueFromUnit(
double value, ElectricalUnit valueUnit)
const
240 case ElectricalUnit::UNIT_kV:
241 case ElectricalUnit::UNIT_kA:
242 case ElectricalUnit::UNIT_kW:
243 case ElectricalUnit::UNIT_kVA:
244 case ElectricalUnit::UNIT_kvar: {
247 case ElectricalUnit::UNIT_MW:
248 case ElectricalUnit::UNIT_MVA:
249 case ElectricalUnit::UNIT_Mvar: {
258bool PowerElement::OpenCADProperties(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
260 auto cadPropNode = elementNode->first_node(
"CADProperties");
261 if(!cadPropNode)
return false;
263 auto position = cadPropNode->first_node(
"Position");
264 double posX = XMLParser::GetNodeValueDouble(position,
"X");
265 double posY = XMLParser::GetNodeValueDouble(position,
"Y");
266 auto size = cadPropNode->first_node(
"Size");
267 m_width = XMLParser::GetNodeValueDouble(size,
"Width");
268 m_height = XMLParser::GetNodeValueDouble(size,
"Height");
269 double angle = XMLParser::GetNodeValueDouble(cadPropNode,
"Angle");
272 auto nodePosition = cadPropNode->first_node(
"NodePosition");
273 double nodePosX = XMLParser::GetNodeValueDouble(nodePosition,
"X");
274 double nodePosY = XMLParser::GetNodeValueDouble(nodePosition,
"Y");
276 int parentID = XMLParser::GetNodeValueInt(cadPropNode,
"ParentID");
280 m_parentList.push_back(
nullptr);
281 m_pointList.push_back(wxPoint2DDouble(nodePosX, nodePosY));
282 m_pointList.push_back(wxPoint2DDouble(nodePosX, nodePosY));
283 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -m_height / 2.0 - 10.0));
284 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -m_height / 2.0));
286 wxRect2DDouble genRect(0, 0, 0, 0);
287 m_switchRect.push_back(genRect);
292 AddParent(parentList[parentID], wxPoint2DDouble(nodePosX, nodePosY));
297 Move(wxPoint2DDouble(posX, posY));
300 int numRot = angle / m_rotationAngle;
301 bool clockwise =
true;
303 numRot = std::abs(numRot);
306 for(
int i = 0; i < numRot; i++)
Rotate(clockwise);
311void PowerElement::SaveCADProperties(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementNode)
313 auto cadProp = XMLParser::AppendNode(doc, elementNode,
"CADProperties");
314 auto position = XMLParser::AppendNode(doc, cadProp,
"Position");
315 auto posX = XMLParser::AppendNode(doc, position,
"X");
316 XMLParser::SetNodeValue(doc, posX, m_position.m_x);
317 auto posY = XMLParser::AppendNode(doc, position,
"Y");
318 XMLParser::SetNodeValue(doc, posY, m_position.m_y);
319 auto size = XMLParser::AppendNode(doc, cadProp,
"Size");
320 auto width = XMLParser::AppendNode(doc, size,
"Width");
321 XMLParser::SetNodeValue(doc, width, m_width);
322 auto height = XMLParser::AppendNode(doc, size,
"Height");
323 XMLParser::SetNodeValue(doc, height, m_height);
324 auto angle = XMLParser::AppendNode(doc, cadProp,
"Angle");
325 XMLParser::SetNodeValue(doc, angle, m_angle);
326 auto nodePos = XMLParser::AppendNode(doc, cadProp,
"NodePosition");
327 auto nodePosX = XMLParser::AppendNode(doc, nodePos,
"X");
328 XMLParser::SetNodeValue(doc, nodePosX, m_pointList[0].m_x);
329 auto nodePosY = XMLParser::AppendNode(doc, nodePos,
"Y");
330 XMLParser::SetNodeValue(doc, nodePosY, m_pointList[0].m_y);
331 auto parentID = XMLParser::AppendNode(doc, cadProp,
"ParentID");
332 Element* parent = m_parentList[0];
333 if(parent) XMLParser::SetNodeValue(doc, parentID, parent->
GetID());
336void PowerElement::SaveSwitchingData(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* electricalNode)
338 auto switchingList = XMLParser::AppendNode(doc, electricalNode,
"SwitchingList");
339 for(
int i = 0; i < static_cast<int>(m_swData.
swType.size()); i++) {
340 auto switching = XMLParser::AppendNode(doc, switchingList,
"Switching");
341 XMLParser::SetNodeAttribute(doc, switching,
"ID", i);
342 auto swType = XMLParser::AppendNode(doc, switching,
"Type");
343 XMLParser::SetNodeValue(doc, swType,
static_cast<int>(m_swData.
swType[i]));
344 auto swTime = XMLParser::AppendNode(doc, switching,
"Time");
345 XMLParser::SetNodeValue(doc, swTime, m_swData.
swTime[i]);
349bool PowerElement::OpenSwitchingData(rapidxml::xml_node<>* electricalNode)
351 auto switchingList = electricalNode->first_node(
"SwitchingList");
352 if(!switchingList)
return false;
353 auto swNode = switchingList->first_node(
"Switching");
356 m_swData.
swTime.push_back(XMLParser::GetNodeValueDouble(swNode,
"Time"));
357 swNode = swNode->next_sibling(
"Switching");
SwitchingType
Type of switching.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
virtual int GetID() const
Get the element ID.
wxPoint2DDouble GetPosition() const
Get the element position.
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,...
double GetAngle() const
Get the element angle.
virtual void DrawDCRectangle(wxPoint2DDouble position, double width, double height, double angle, wxDC &dc) const
Draw a circle.
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
virtual void DrawDCTriangle(std::vector< wxPoint2DDouble > points, wxGraphicsContext *gc) const
Draw rectangle.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
virtual bool Contains(wxPoint2DDouble position) const =0
Checks if the element contains a position.
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual void SetNominalVoltage(std::vector< double > nominalVoltage, std::vector< ElectricalUnit > nominalVoltageUnit)
Set nominal voltage of the element.
PowerElement()
Constructor.
virtual void CalculatePowerFlowPts(std::vector< wxPoint2DDouble > edges)
Calculate the points of the power flow arrows.
virtual bool SwitchesContains(wxPoint2DDouble position) const
Check if switch contains position.
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.
std::vector< double > swTime
std::vector< SwitchingType > swType