Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
ControlElement.cpp
1/*
2 * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "ControlElement.h"
19#ifdef USING_WX_3_0_X
20#include "utils/DegreesAndRadians.h"
21#endif
22
23Node::Node(wxPoint2DDouble position, NodeType nodeType, double borderSize)
24{
25 double totalRadius = m_radius + borderSize;
26 m_rect = wxRect2DDouble(position.m_x - totalRadius, position.m_y - totalRadius, totalRadius * 2, totalRadius * 2);
27 m_nodeType = nodeType;
28
29 m_triPts.push_back(GetPosition() + wxPoint2DDouble(-m_radius - m_rect.GetSize().GetWidth() / 2, m_radius));
30 m_triPts.push_back(GetPosition() + wxPoint2DDouble(-m_radius - m_rect.GetSize().GetWidth() / 2, -m_radius));
31 m_triPts.push_back(GetPosition() + wxPoint2DDouble(-m_radius + 1, 0));
32}
33
34Node::~Node() {}
35void Node::SetPosition(wxPoint2DDouble position)
36{
37 m_rect = wxRect2DDouble(position.m_x - m_rect.m_width / 2, position.m_y - m_rect.m_height / 2, m_rect.m_width,
38 m_rect.m_height);
39 m_triPts[0] = GetPosition() + wxPoint2DDouble(-m_radius - m_rect.GetSize().GetWidth() / 2, m_radius);
40 m_triPts[1] = GetPosition() + wxPoint2DDouble(-m_radius - m_rect.GetSize().GetWidth() / 2, -m_radius);
41 m_triPts[2] = GetPosition() + wxPoint2DDouble(-m_radius + 1, 0);
42
43 // Rotate according to the angle (node rect center as reference)
44 if (m_angle != 0.0) RotateTriPt(m_angle);
45}
46
47void Node::StartMove(wxPoint2DDouble position)
48{
49 m_moveStartPt = position;
50 m_movePos = m_rect.GetPosition() - wxPoint2DDouble(-m_rect.m_width / 2, -m_rect.m_height / 2);
51}
52
53void Node::Move(wxPoint2DDouble position) { SetPosition(m_movePos + position - m_moveStartPt); }
54wxPoint2DDouble Node::GetPosition() const
55{
56 return m_rect.GetPosition() + wxPoint2DDouble(m_rect.GetSize().GetWidth() / 2, m_rect.GetSize().GetHeight() / 2);
57}
58
59void Node::RotateTriPt(double angle)
60{
61 double radAngle = wxDegToRad(angle);
62 wxPoint2DDouble rectCenter =
63 m_rect.GetPosition() + wxPoint2DDouble(m_rect.GetSize().GetWidth() / 2.0, m_rect.GetSize().GetHeight() / 2.0);
64 m_triPts[0] = wxPoint2DDouble(std::cos(radAngle) * (m_triPts[0].m_x - rectCenter.m_x) -
65 std::sin(radAngle) * (m_triPts[0].m_y - rectCenter.m_y) + rectCenter.m_x,
66 std::sin(radAngle) * (m_triPts[0].m_x - rectCenter.m_x) +
67 std::cos(radAngle) * (m_triPts[0].m_y - rectCenter.m_y) + rectCenter.m_y);
68 m_triPts[1] = wxPoint2DDouble(std::cos(radAngle) * (m_triPts[1].m_x - rectCenter.m_x) -
69 std::sin(radAngle) * (m_triPts[1].m_y - rectCenter.m_y) + rectCenter.m_x,
70 std::sin(radAngle) * (m_triPts[1].m_x - rectCenter.m_x) +
71 std::cos(radAngle) * (m_triPts[1].m_y - rectCenter.m_y) + rectCenter.m_y);
72 m_triPts[2] = wxPoint2DDouble(std::cos(radAngle) * (m_triPts[2].m_x - rectCenter.m_x) -
73 std::sin(radAngle) * (m_triPts[2].m_y - rectCenter.m_y) + rectCenter.m_x,
74 std::sin(radAngle) * (m_triPts[2].m_x - rectCenter.m_x) +
75 std::cos(radAngle) * (m_triPts[2].m_y - rectCenter.m_y) + rectCenter.m_y);
76}
77
78void Node::Rotate(bool clockwise)
79{
80 if (clockwise)
81 m_angle += 90.0;
82 else
83 m_angle -= 90.0;
84 if (m_angle >= 360.0)
85 m_angle = 0.0;
86 else if (m_angle < 0)
87 m_angle = 270.0;
88
89 // Update input triangle points.
90 m_triPts[0] = GetPosition() + wxPoint2DDouble(-m_radius - m_rect.GetSize().GetWidth() / 2, m_radius);
91 m_triPts[1] = GetPosition() + wxPoint2DDouble(-m_radius - m_rect.GetSize().GetWidth() / 2, -m_radius);
92 m_triPts[2] = GetPosition() + wxPoint2DDouble(-m_radius + 1, 0);
93
94 // Rotate according to the angle (node rect center as reference)
95 if (m_angle != 0.0) RotateTriPt(m_angle);
96}
97
98bool Node::Contains(wxPoint2DDouble position) const
99{
100 if (m_connected) return false;
101 return m_rect.Contains(position);
102}
103
104Node* Node::GetCopy() const
105{
106 Node* copy = new Node();
107 *copy = *this;
108 return copy;
109}
110
111ControlElement::ControlElement(int id) : Element() { m_elementID = id; }
112
113ControlElement::~ControlElement()
114{
115}
116
117//void ControlElement::DrawNodes() const
118//{
119// for (auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
120// Node* node = *it;
121// DrawCircle(node->GetPosition(), node->GetRadius(), 10, GL_POLYGON);
122// if (node->GetNodeType() == Node::NodeType::NODE_IN) { DrawTriangle(node->GetInTrianglePts()); }
123// }
124//}
125
126void ControlElement::DrawDCNodes(wxGraphicsContext* gc) const
127{
128 for (auto node : m_nodeList) {
129 DrawDCCircle(node->GetPosition(), node->GetRadius(), 10, gc);
130 if (node->GetNodeType() == Node::NodeType::NODE_IN) { DrawDCTriangle(node->GetInTrianglePts(), gc); }
131 }
132}
133
134void ControlElement::StartMove(wxPoint2DDouble position)
135{
136 m_moveStartPt = position;
137 m_movePos = m_position;
138 for (int i = 0; i < (int)m_nodeList.size(); ++i) { m_nodeList[i]->StartMove(position); }
139}
140
141void ControlElement::Move(wxPoint2DDouble position)
142{
143 SetPosition(m_movePos + position - m_moveStartPt);
144 for (int i = 0; i < (int)m_nodeList.size(); ++i) { m_nodeList[i]->Move(position); }
145}
146
147bool ControlElement::Solve(double* input, double timeStep)
148{
149 if (input)
150 m_output = input[0];
151 else
152 m_output = 0.0;
153 return true;
154}
155
156void ControlElement::ReplaceNode(Node* oldNode, Node* newNode)
157{
158 for (unsigned int i = 0; i < m_nodeList.size(); i++) {
159 if (m_nodeList[i] == oldNode) m_nodeList[i] = newNode;
160 }
161}
162
163ControlElement* ControlElement::GetControlElementFromID(std::vector< std::shared_ptr<ControlElement> > elementList, int id)
164{
165 for (auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
166 ControlElement* element = it->get();
167 if (element->GetID() == id) return element;
168 }
169 return nullptr;
170}
171
172void ControlElement::SaveControlNodes(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementNode)
173{
174 auto nodeList = XMLParser::AppendNode(doc, elementNode, "NodeList");
175 int id = 0;
176 for (auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
177 Node* node = *it;
178 node->SetID(id);
179 auto nodeN = XMLParser::AppendNode(doc, nodeList, "Node");
180 XMLParser::SetNodeAttribute(doc, nodeN, "ID", id);
181 auto nodePosition = XMLParser::AppendNode(doc, nodeN, "Position");
182 auto posNodeX = XMLParser::AppendNode(doc, nodePosition, "X");
183 XMLParser::SetNodeValue(doc, posNodeX, node->GetPosition().m_x);
184 auto posNodeY = XMLParser::AppendNode(doc, nodePosition, "Y");
185 XMLParser::SetNodeValue(doc, posNodeY, node->GetPosition().m_y);
186 auto angle = XMLParser::AppendNode(doc, nodeN, "Angle");
187 XMLParser::SetNodeValue(doc, angle, node->GetAngle());
188 auto nodeType = XMLParser::AppendNode(doc, nodeN, "Type");
189 XMLParser::SetNodeValue(doc, nodeType, static_cast<int>(node->GetNodeType()));
190 id++;
191 }
192}
193
194bool ControlElement::OpenControlNodes(rapidxml::xml_node<>* elementNode)
195{
196 // Clear old nodes
197 for (auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) delete* it;
198 m_nodeList.clear();
199
200 auto nodeList = elementNode->first_node("NodeList");
201 if (!nodeList) return false;
202 auto nodeN = nodeList->first_node("Node");
203 while (nodeN) {
204 auto nodePosition = nodeN->first_node("Position");
205 double nodePosX = XMLParser::GetNodeValueDouble(nodePosition, "X");
206 double nodePosY = XMLParser::GetNodeValueDouble(nodePosition, "Y");
207 double nodeAngle = XMLParser::GetNodeValueDouble(nodeN, "Angle");
208 Node::NodeType nodeType = static_cast<Node::NodeType>(XMLParser::GetNodeValueInt(nodeN, "Type"));
209 Node* node = new Node(wxPoint2DDouble(nodePosX, nodePosY), nodeType, 2.0);
210 node->SetAngle(nodeAngle);
211 m_nodeList.push_back(node);
212 nodeN = nodeN->next_sibling("Node");
213 }
214 return true;
215}
216
217bool ControlElement::Initialize()
218{
219 m_solved = false;
220 m_output = 0.0;
221 return true;
222}
Base class of a control element. Provide general methods to other control classes.
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
virtual int GetID() const
Get the element ID.
Definition Element.h:271
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
Definition Element.cpp:27
virtual void DrawDCTriangle(std::vector< wxPoint2DDouble > points, wxGraphicsContext *gc) const
Draw rectangle.
Definition Element.cpp:237
virtual void DrawDCCircle(wxPoint2DDouble position, double radius, int numSegments, wxGraphicsContext *gc) const
Draw a circle using device context.
Definition Element.cpp:177
Node of a control element. This class manages the user interaction with the connection and control el...