Power System Platform  2026w23a-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
41void RateLimiter::DrawDC(GUIColour* guiColour, wxPoint2DDouble translation, double scale, wxGraphicsContext* gc) const
42{
43 if (m_selected) {
44 gc->SetPen(*wxTRANSPARENT_PEN);
45 gc->SetBrush(guiColour->selection);
46 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
47 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);
48 }
49 gc->SetPen(guiColour->enabled);
50 gc->SetBrush(guiColour->background);
51 gc->DrawRectangle(m_position.m_x - m_width / 2, m_position.m_y - m_height / 2, m_width, m_height);
52
53 // Plot symbol.
54 gc->SetBrush(*wxTRANSPARENT_BRUSH);
55 wxPoint2DDouble axis[4];
56 axis[0] = m_position + wxPoint2DDouble(-13, 0);
57 axis[1] = m_position + wxPoint2DDouble(13, 0);
58 axis[2] = m_position + wxPoint2DDouble(0, -13);
59 axis[3] = m_position + wxPoint2DDouble(0, 13);
60 gc->StrokeLines(2, &axis[0]);
61 gc->StrokeLines(2, &axis[2]);
62
63 gc->SetPen(wxPen(guiColour->bus, 2));
64 wxPoint2DDouble limSymbol[2];
65 limSymbol[0] = m_position + wxPoint2DDouble(10, -10);
66 limSymbol[1] = m_position + wxPoint2DDouble(-10, 10);
67 gc->StrokeLines(2, limSymbol);
68
69 gc->SetPen(*wxTRANSPARENT_PEN);
70 gc->SetBrush(guiColour->enabled);
71 DrawDCNodes(gc);
72}
73
74bool RateLimiter::ShowForm(wxWindow* parent, Element* element, wxWindow* workspace)
75{
76 RateLimiterForm form(parent, this);
77 form.CenterOnParent();
78 if (form.ShowModal() == wxID_OK) {
79 return true;
80 }
81 return false;
82}
83
84void RateLimiter::Rotate(bool clockwise)
85{
86 if (clockwise)
87 m_angle += 90.0;
88 else
89 m_angle -= 90.0;
90 if (m_angle >= 360.0)
91 m_angle = 0.0;
92 else if (m_angle < 0)
93 m_angle = 270.0;
94
95 UpdatePoints();
96
97 for (auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
98 Node* node = *it;
99 node->Rotate(clockwise);
100 }
101}
102
103void RateLimiter::UpdatePoints()
104{
105 if (m_angle == 0.0) {
106 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(-18, 0));
107 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(18, 0));
108 }
109 else if (m_angle == 90.0) {
110 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, -18));
111 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(0, 18));
112 }
113 else if (m_angle == 180.0) {
114 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(18, 0));
115 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(-18, 0));
116 }
117 else if (m_angle == 270.0) {
118 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, 18));
119 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(0, -18));
120 }
121}
122
123bool RateLimiter::Solve(double* input, double timeStep)
124{
125 if (!input) {
126 m_output = 0.0;
127 return true;
128 }
129 double rate = (input[0] - m_output) / timeStep;
130
131 bool reachLimit = false;
132 if (rate > m_upLimit) {
133 rate = m_upLimit;
134 reachLimit = true;
135 }
136 else if (rate < m_lowLimit) {
137 rate = m_lowLimit;
138 reachLimit = true;
139 }
140
141 if (reachLimit)
142 m_output += rate * timeStep;
143 else
144 m_output = input[0];
145 return true;
146}
147
149{
150 RateLimiter* copy = new RateLimiter(*this);
151 return copy;
152}
153
154rapidxml::xml_node<>* RateLimiter::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
155{
156 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "RateLimiter");
157 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
158
159 SaveCADProperties(doc, elementNode);
160 SaveControlNodes(doc, elementNode);
161
162 // Element properties
163 auto upLimit = XMLParser::AppendNode(doc, elementNode, "UpperLimit");
164 XMLParser::SetNodeValue(doc, upLimit, m_upLimit);
165 auto lowLimit = XMLParser::AppendNode(doc, elementNode, "LowerLimit");
166 XMLParser::SetNodeValue(doc, lowLimit, m_lowLimit);
167
168 return elementNode;
169}
170
171bool RateLimiter::OpenElement(rapidxml::xml_node<>* elementNode)
172{
173 if (!OpenCADProperties(elementNode)) return false;
174 if (!OpenControlNodes(elementNode)) return false;
175
176 // Element properties
177 m_upLimit = XMLParser::GetNodeValueDouble(elementNode, "UpperLimit");
178 m_lowLimit = XMLParser::GetNodeValueDouble(elementNode, "LowerLimit");
179
180 StartMove(m_position);
181 UpdatePoints();
182 return true;
183}
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:114
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 Element * GetCopy()
Get a the element copy.
virtual bool Solve(double *input, double timeStep)
Calculate the rate and limits it if exceeds.
virtual void DrawDC(GUIColour *guiColour, wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
virtual bool ShowForm(wxWindow *parent, Element *element, wxWindow *workspace=nullptr)
Show element data form.