Power System Platform  2026w11a-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, wxWindow* workspace)
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(*this);
183 return copy;
184}
185
186rapidxml::xml_node<>* RateLimiter::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
187{
188 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "RateLimiter");
189 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
190
191 SaveCADProperties(doc, elementNode);
192 SaveControlNodes(doc, elementNode);
193
194 // Element properties
195 auto upLimit = XMLParser::AppendNode(doc, elementNode, "UpperLimit");
196 XMLParser::SetNodeValue(doc, upLimit, m_upLimit);
197 auto lowLimit = XMLParser::AppendNode(doc, elementNode, "LowerLimit");
198 XMLParser::SetNodeValue(doc, lowLimit, m_lowLimit);
199
200 return elementNode;
201}
202
203bool RateLimiter::OpenElement(rapidxml::xml_node<>* elementNode)
204{
205 if (!OpenCADProperties(elementNode)) return false;
206 if (!OpenControlNodes(elementNode)) return false;
207
208 // Element properties
209 m_upLimit = XMLParser::GetNodeValueDouble(elementNode, "UpperLimit");
210 m_lowLimit = XMLParser::GetNodeValueDouble(elementNode, "LowerLimit");
211
212 StartMove(m_position);
213 UpdatePoints();
214 return true;
215}
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, wxWindow *workspace=nullptr)
Show element data form.