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(m_closedSwitchColour));
121 gc->SetBrush(wxBrush(m_openedSwitchColour));
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(m_closedSwitchColour));
151 dc.SetBrush(wxBrush(m_openedSwitchColour));
167 m_switchSize, m_switchSize, parent->GetAngle(), dc);
175 double arrowRate = 100.0;
177 if(edges.size() < 2)
return;
180 for(
int i = 0; i < (int)m_powerFlowArrow.size(); i++) m_powerFlowArrow[i].clear();
181 m_powerFlowArrow.clear();
183 for(
int i = 1; i < (int)edges.size(); i++) {
184 wxPoint2DDouble pt1 = edges[i - 1];
185 wxPoint2DDouble pt2 = edges[i];
187 double angle = std::atan2(pt2.m_y - pt1.m_y, pt2.m_x - pt1.m_x);
189 wxPoint2DDouble rotPt2(
190 std::cos(-angle) * (pt2.m_x - pt1.m_x) - std::sin(-angle) * (pt2.m_y - pt1.m_y) + pt1.m_x,
191 std::sin(-angle) * (pt2.m_x - pt1.m_x) + std::cos(-angle) * (pt2.m_y - pt1.m_y) + pt1.m_y);
193 int numArrows = std::abs(pt1.m_x - rotPt2.m_x) / arrowRate;
194 if(numArrows == 0) numArrows = 1;
196 for(
int i = 0; i < numArrows; i++) {
197 wxPoint2DDouble arrowCenter(pt1.m_x + ((rotPt2.m_x - pt1.m_x) /
double(numArrows + 1)) *
double(i + 1),
198 pt1.m_y + ((rotPt2.m_y - pt1.m_y) /
double(numArrows + 1)) *
double(i + 1));
200 std::vector<wxPoint2DDouble> triPts;
201 triPts.push_back(arrowCenter + wxPoint2DDouble(5.0, 0.0));
202 triPts.push_back(arrowCenter + wxPoint2DDouble(-5.0, 5.0));
203 triPts.push_back(arrowCenter + wxPoint2DDouble(-5.0, -5.0));
206 for(
int i = 0; i < 3; i++) {
207 triPts[i] = wxPoint2DDouble(
208 std::cos(angle) * (triPts[i].m_x - pt1.m_x) - std::sin(angle) * (triPts[i].m_y - pt1.m_y) + pt1.m_x,
209 std::sin(angle) * (triPts[i].m_x - pt1.m_x) + std::cos(angle) * (triPts[i].m_y - pt1.m_y) +
212 m_powerFlowArrow.push_back(triPts);
227 gc->SetPen(*wxTRANSPARENT_PEN);
229 gc->SetBrush(wxBrush(m_powerFlowArrowColour));
230 for (
auto arrow : m_powerFlowArrow) {
DrawDCTriangle(arrow, gc); }
236 dc.SetPen(*wxTRANSPARENT_PEN);
238 dc.SetBrush(wxBrush(m_powerFlowArrowColour));
239 for (
auto arrow : m_powerFlowArrow) {
240 std::vector<wxPoint> arrowPts;
241 for (
auto& pt : arrow) {
242 arrowPts.emplace_back(
static_cast<int>(pt.m_x),
static_cast<int>(pt.m_y));
249double PowerElement::GetValueFromUnit(
double value,
ElectricalUnit valueUnit)
270bool PowerElement::OpenCADProperties(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
272 auto cadPropNode = elementNode->first_node(
"CADProperties");
273 if(!cadPropNode)
return false;
275 auto position = cadPropNode->first_node(
"Position");
276 double posX = XMLParser::GetNodeValueDouble(position,
"X");
277 double posY = XMLParser::GetNodeValueDouble(position,
"Y");
278 auto size = cadPropNode->first_node(
"Size");
279 m_width = XMLParser::GetNodeValueDouble(size,
"Width");
280 m_height = XMLParser::GetNodeValueDouble(size,
"Height");
281 double angle = XMLParser::GetNodeValueDouble(cadPropNode,
"Angle");
284 auto nodePosition = cadPropNode->first_node(
"NodePosition");
285 double nodePosX = XMLParser::GetNodeValueDouble(nodePosition,
"X");
286 double nodePosY = XMLParser::GetNodeValueDouble(nodePosition,
"Y");
288 int parentID = XMLParser::GetNodeValueInt(cadPropNode,
"ParentID");
292 m_parentList.push_back(
nullptr);
293 m_pointList.push_back(wxPoint2DDouble(nodePosX, nodePosY));
294 m_pointList.push_back(wxPoint2DDouble(nodePosX, nodePosY));
295 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -m_height / 2.0 - 10.0));
296 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -m_height / 2.0));
298 wxRect2DDouble genRect(0, 0, 0, 0);
299 m_switchRect.push_back(genRect);
304 AddParent(parentList[parentID], wxPoint2DDouble(nodePosX, nodePosY));
309 Move(wxPoint2DDouble(posX, posY));
312 int numRot = angle / m_rotationAngle;
313 bool clockwise =
true;
315 numRot = std::abs(numRot);
318 for(
int i = 0; i < numRot; i++)
Rotate(clockwise);
323void PowerElement::SaveCADProperties(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementNode)
325 auto cadProp = XMLParser::AppendNode(doc, elementNode,
"CADProperties");
326 auto position = XMLParser::AppendNode(doc, cadProp,
"Position");
327 auto posX = XMLParser::AppendNode(doc, position,
"X");
328 XMLParser::SetNodeValue(doc, posX, m_position.m_x);
329 auto posY = XMLParser::AppendNode(doc, position,
"Y");
330 XMLParser::SetNodeValue(doc, posY, m_position.m_y);
331 auto size = XMLParser::AppendNode(doc, cadProp,
"Size");
332 auto width = XMLParser::AppendNode(doc, size,
"Width");
333 XMLParser::SetNodeValue(doc, width, m_width);
334 auto height = XMLParser::AppendNode(doc, size,
"Height");
335 XMLParser::SetNodeValue(doc, height, m_height);
336 auto angle = XMLParser::AppendNode(doc, cadProp,
"Angle");
337 XMLParser::SetNodeValue(doc, angle, m_angle);
338 auto nodePos = XMLParser::AppendNode(doc, cadProp,
"NodePosition");
339 auto nodePosX = XMLParser::AppendNode(doc, nodePos,
"X");
340 XMLParser::SetNodeValue(doc, nodePosX, m_pointList[0].m_x);
341 auto nodePosY = XMLParser::AppendNode(doc, nodePos,
"Y");
342 XMLParser::SetNodeValue(doc, nodePosY, m_pointList[0].m_y);
343 auto parentID = XMLParser::AppendNode(doc, cadProp,
"ParentID");
344 Element* parent = m_parentList[0];
345 if(parent) XMLParser::SetNodeValue(doc, parentID, parent->
GetID());
348void PowerElement::SaveSwitchingData(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* electricalNode)
350 auto switchingList = XMLParser::AppendNode(doc, electricalNode,
"SwitchingList");
351 for(
int i = 0; i < static_cast<int>(m_swData.
swType.size()); i++) {
352 auto switching = XMLParser::AppendNode(doc, switchingList,
"Switching");
353 XMLParser::SetNodeAttribute(doc, switching,
"ID", i);
354 auto swType = XMLParser::AppendNode(doc, switching,
"Type");
355 XMLParser::SetNodeValue(doc, swType,
static_cast<int>(m_swData.
swType[i]));
356 auto swTime = XMLParser::AppendNode(doc, switching,
"Time");
357 XMLParser::SetNodeValue(doc, swTime, m_swData.
swTime[i]);
361bool PowerElement::OpenSwitchingData(rapidxml::xml_node<>* electricalNode)
363 auto switchingList = electricalNode->first_node(
"SwitchingList");
364 if(!switchingList)
return false;
365 auto swNode = switchingList->first_node(
"Switching");
368 m_swData.
swTime.push_back(XMLParser::GetNodeValueDouble(swNode,
"Time"));
369 swNode = swNode->next_sibling(
"Switching");
ElectricalUnit
Electrical units.
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 void DrawDCSwitches(wxGraphicsContext *gc) const
Draw switch.
virtual bool SwitchesContains(wxPoint2DDouble position) const
Check if switch contains position.
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.
std::vector< double > swTime
std::vector< SwitchingType > swType