Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
RateLimiter.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 "RateLimiter.h"
19#include "../../forms/RateLimiterForm.h"
20#include <wx/pen.h>
21#include <wx/brush.h>
22
23RateLimiter::RateLimiter(int id) : ControlElement(id)
24{
25 m_width = m_height = 36.0;
26 Node* nodeIn = new Node(m_position + wxPoint2DDouble(-18, 0), Node::NodeType::NODE_IN, m_borderSize);
27 nodeIn->StartMove(m_position);
28 Node* nodeOut = new Node(m_position + wxPoint2DDouble(18, 0), Node::NodeType::NODE_OUT, m_borderSize);
29 nodeOut->SetAngle(180.0);
30 nodeOut->StartMove(m_position);
31 m_nodeList.push_back(nodeIn);
32 m_nodeList.push_back(nodeOut);
33}
34
35RateLimiter::~RateLimiter()
36{
37 for (auto& node : m_nodeList) if (node) delete node;
38 m_nodeList.clear();
39}
40
41//void RateLimiter::Draw(wxPoint2DDouble translation, double scale) const
42//{
43// glLineWidth(1.0);
44// if(m_selected) {
45// glColor4dv(m_selectionColour.GetRGBA());
46// double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
47// DrawRectangle(m_position, m_width + borderSize, m_height + borderSize);
48// }
49// glColor4d(1.0, 1.0, 1.0, 1.0);
50// DrawRectangle(m_position, m_width, m_height);
51// glColor4d(0.0, 0.0, 0.0, 1.0);
52// DrawRectangle(m_position, m_width, m_height, GL_LINE_LOOP);
53//
54// // Plot symbol.
55// std::vector<wxPoint2DDouble> axis;
56// axis.push_back(m_position + wxPoint2DDouble(-13, 0));
57// axis.push_back(m_position + wxPoint2DDouble(13, 0));
58// axis.push_back(m_position + wxPoint2DDouble(0, -13));
59// axis.push_back(m_position + wxPoint2DDouble(0, 13));
60// DrawLine(axis, GL_LINES);
61//
62// glLineWidth(2.0);
63// std::vector<wxPoint2DDouble> limSymbol;
64// limSymbol.push_back(m_position + wxPoint2DDouble(10, -10));
65// limSymbol.push_back(m_position + wxPoint2DDouble(-10, 10));
66// glColor4d(0.0, 0.3, 1.0, 1.0);
67// DrawLine(limSymbol);
68//
69// glColor4d(0.0, 0.0, 0.0, 1.0);
70// DrawNodes();
71//}
72
73void RateLimiter::DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext* gc) const
74{
75 if (m_selected) {
76 gc->SetPen(*wxTRANSPARENT_PEN);
77 gc->SetBrush(wxBrush(m_selectionColour));
78 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
79 gc->DrawRectangle(m_position.m_x - m_width / 2 - borderSize / 2, m_position.m_y - m_height / 2 - borderSize / 2, m_width + borderSize, m_height + borderSize);
80 }
81 gc->SetPen(*wxBLACK_PEN);
82 gc->SetBrush(*wxWHITE_BRUSH);
83 gc->DrawRectangle(m_position.m_x - m_width / 2, m_position.m_y - m_height / 2, m_width, m_height);
84
85 // Plot symbol.
86 gc->SetBrush(*wxTRANSPARENT_BRUSH);
87 wxPoint2DDouble axis[4];
88 axis[0] = m_position + wxPoint2DDouble(-13, 0);
89 axis[1] = m_position + wxPoint2DDouble(13, 0);
90 axis[2] = m_position + wxPoint2DDouble(0, -13);
91 axis[3] = m_position + wxPoint2DDouble(0, 13);
92 gc->StrokeLines(2, &axis[0]);
93 gc->StrokeLines(2, &axis[2]);
94
95 gc->SetPen(wxPen(wxColour(0, 77, 255, 255), 2));
96 wxPoint2DDouble limSymbol[2];
97 limSymbol[0] = m_position + wxPoint2DDouble(10, -10);
98 limSymbol[1] = m_position + wxPoint2DDouble(-10, 10);
99 gc->StrokeLines(2, limSymbol);
100
101 gc->SetPen(*wxTRANSPARENT_PEN);
102 gc->SetBrush(*wxBLACK_BRUSH);
103 DrawDCNodes(gc);
104}
105
106bool RateLimiter::ShowForm(wxWindow* parent, Element* element)
107{
108 RateLimiterForm form(parent, this);
109 form.CenterOnParent();
110 if (form.ShowModal() == wxID_OK) {
111 return true;
112 }
113 return false;
114}
115
116void RateLimiter::Rotate(bool clockwise)
117{
118 if (clockwise)
119 m_angle += 90.0;
120 else
121 m_angle -= 90.0;
122 if (m_angle >= 360.0)
123 m_angle = 0.0;
124 else if (m_angle < 0)
125 m_angle = 270.0;
126
127 UpdatePoints();
128
129 for (auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
130 Node* node = *it;
131 node->Rotate(clockwise);
132 }
133}
134
135void RateLimiter::UpdatePoints()
136{
137 if (m_angle == 0.0) {
138 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(-18, 0));
139 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(18, 0));
140 }
141 else if (m_angle == 90.0) {
142 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, -18));
143 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(0, 18));
144 }
145 else if (m_angle == 180.0) {
146 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(18, 0));
147 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(-18, 0));
148 }
149 else if (m_angle == 270.0) {
150 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, 18));
151 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(0, -18));
152 }
153}
154
155bool RateLimiter::Solve(double* input, double timeStep)
156{
157 if (!input) {
158 m_output = 0.0;
159 return true;
160 }
161 double rate = (input[0] - m_output) / timeStep;
162
163 bool reachLimit = false;
164 if (rate > m_upLimit) {
165 rate = m_upLimit;
166 reachLimit = true;
167 }
168 else if (rate < m_lowLimit) {
169 rate = m_lowLimit;
170 reachLimit = true;
171 }
172
173 if (reachLimit)
174 m_output += rate * timeStep;
175 else
176 m_output = input[0];
177 return true;
178}
179
181{
182 RateLimiter* copy = new RateLimiter(m_elementID);
183 *copy = *this;
184 return copy;
185}
186
187rapidxml::xml_node<>* RateLimiter::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
188{
189 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "RateLimiter");
190 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
191
192 SaveCADProperties(doc, elementNode);
193 SaveControlNodes(doc, elementNode);
194
195 // Element properties
196 auto upLimit = XMLParser::AppendNode(doc, elementNode, "UpperLimit");
197 XMLParser::SetNodeValue(doc, upLimit, m_upLimit);
198 auto lowLimit = XMLParser::AppendNode(doc, elementNode, "LowerLimit");
199 XMLParser::SetNodeValue(doc, lowLimit, m_lowLimit);
200
201 return elementNode;
202}
203
204bool RateLimiter::OpenElement(rapidxml::xml_node<>* elementNode)
205{
206 if (!OpenCADProperties(elementNode)) return false;
207 if (!OpenControlNodes(elementNode)) return false;
208
209 // Element properties
210 m_upLimit = XMLParser::GetNodeValueDouble(elementNode, "UpperLimit");
211 m_lowLimit = XMLParser::GetNodeValueDouble(elementNode, "LowerLimit");
212
213 StartMove(m_position);
214 UpdatePoints();
215 return true;
216}
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
Node of a control element. This class manages the user interaction with the connection and control el...
Form to edit the rate limit control data.
Limits the rising and/or falling rate.
Definition RateLimiter.h:33
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
virtual Element * GetCopy()
Get a the element copy.
virtual bool Solve(double *input, double timeStep)
Calculate the rate and limits it if exceeds.
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.