Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
Gain.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 "Gain.h"
19#include "../../forms/GainForm.h"
20
21Gain::Gain(int id) : ControlElement(id)
22{
23 m_triPts.resize(3);
24 SetValue(m_value);
25 Node* nodeIn = new Node(m_position + wxPoint2DDouble(-m_width / 2, 0), Node::NodeType::NODE_IN, m_borderSize);
26 nodeIn->StartMove(m_position);
27 Node* nodeOut = new Node(m_position + wxPoint2DDouble(m_width / 2, 0), Node::NodeType::NODE_OUT, m_borderSize);
28 nodeOut->SetAngle(180.0);
29 nodeOut->StartMove(m_position);
30 m_nodeList.push_back(nodeIn);
31 m_nodeList.push_back(nodeOut);
32}
33
34Gain::~Gain()
35{
36 //if(m_glText) delete m_glText;
37 if (m_gcText) delete m_gcText;
38 for (auto& node : m_nodeList) if (node) delete node;
39 m_nodeList.clear();
40}
41//void Gain::Draw(wxPoint2DDouble translation, double scale) const
42//{
43// if(m_selected) {
44// glColor4dv(m_selectionColour.GetRGBA());
45// double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
46// std::vector<wxPoint2DDouble> m_triSelectedPts;
47// if(m_angle == 0.0) {
48// m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(borderSize / 2, borderSize / 1.5));
49// m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(borderSize / 2, -borderSize / 1.5));
50// m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(-borderSize, 0));
51// } else if(m_angle == 90.0) {
52// m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(borderSize / 1.5, borderSize / 2));
53// m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(-borderSize / 1.5, borderSize / 2));
54// m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(0, -borderSize));
55// } else if(m_angle == 180.0) {
56// m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(borderSize, 0));
57// m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(-borderSize / 2, borderSize / 1.5));
58// m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(-borderSize / 2, -borderSize / 1.5));
59// } else if(m_angle == 270.0) {
60// m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(0, borderSize));
61// m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(-borderSize / 1.5, -borderSize / 2));
62// m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(borderSize / 1.5, -borderSize / 2));
63// }
64// DrawTriangle(m_triSelectedPts);
65// }
66// glLineWidth(1.0);
67// glColor4d(1.0, 1.0, 1.0, 1.0);
68// DrawTriangle(m_triPts);
69// glColor4d(0.0, 0.0, 0.0, 1.0);
70// DrawTriangle(m_triPts, GL_LINE_LOOP);
71//
72// // Plot number.
73// glColor4d(0.0, 0.0, 0.0, 1.0);
74// if(m_angle == 0.0)
75// m_glText->Draw(m_position + wxPoint2DDouble(-m_width / 2 + m_glText->GetWidth() / 2 + 2 + m_borderSize, 0.0));
76// else if(m_angle == 90.0)
77// m_glText->Draw(m_position + wxPoint2DDouble(0.0, -m_height / 2 + m_glText->GetHeight() / 2 + 2 + m_borderSize));
78// else if(m_angle == 180.0)
79// m_glText->Draw(m_position + wxPoint2DDouble(m_width / 2 - m_glText->GetWidth() / 2 - 2 - m_borderSize, 0.0));
80// else if(m_angle == 270.0)
81// m_glText->Draw(m_position + wxPoint2DDouble(0.0, m_height / 2 - m_glText->GetHeight() / 2 - 2 - m_borderSize));
82//
83// glColor4d(0.0, 0.0, 0.0, 1.0);
84// DrawNodes();
85//}
86
87void Gain::DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext* gc) const
88{
89 if (m_selected) {
90 gc->SetPen(*wxTRANSPARENT_PEN);
91 gc->SetBrush(wxBrush(m_selectionColour));
92 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
93 std::vector<wxPoint2DDouble> m_triSelectedPts;
94 if (m_angle == 0.0) {
95 m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(borderSize / 2, borderSize / 1.5));
96 m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(borderSize / 2, -borderSize / 1.5));
97 m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(-borderSize, 0));
98 }
99 else if (m_angle == 90.0) {
100 m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(borderSize / 1.5, borderSize / 2));
101 m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(-borderSize / 1.5, borderSize / 2));
102 m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(0, -borderSize));
103 }
104 else if (m_angle == 180.0) {
105 m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(borderSize, 0));
106 m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(-borderSize / 2, borderSize / 1.5));
107 m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(-borderSize / 2, -borderSize / 1.5));
108 }
109 else if (m_angle == 270.0) {
110 m_triSelectedPts.push_back(m_triPts[0] - wxPoint2DDouble(0, borderSize));
111 m_triSelectedPts.push_back(m_triPts[1] - wxPoint2DDouble(-borderSize / 1.5, -borderSize / 2));
112 m_triSelectedPts.push_back(m_triPts[2] - wxPoint2DDouble(borderSize / 1.5, -borderSize / 2));
113 }
114 DrawDCTriangle(m_triSelectedPts, gc);
115 }
116 //glLineWidth(1.0);
117 //glColor4d(1.0, 1.0, 1.0, 1.0);
118 //DrawTriangle(m_triPts);
119 //glColor4d(0.0, 0.0, 0.0, 1.0);
120 //DrawTriangle(m_triPts, GL_LINE_LOOP);
121
122 gc->SetPen(wxPen(wxColour(0, 0, 0, 255), 1));
123 gc->SetBrush(wxBrush(wxColour(255, 255, 255, 255)));
124 DrawDCTriangle(m_triPts, gc);
125
126 // Plot number.
127 if (m_angle == 0.0)
128 m_gcText->Draw(m_position + wxPoint2DDouble(-m_width / 2 + 2 + m_borderSize, -m_gcText->GetHeight() / 2), gc);
129 else if (m_angle == 90.0)
130 m_gcText->Draw(m_position + wxPoint2DDouble(-m_gcText->GetWidth() / 2, -m_height / 2 + 2 + m_borderSize), gc);
131 else if (m_angle == 180.0)
132 m_gcText->Draw(m_position + wxPoint2DDouble(m_width / 2 - m_gcText->GetWidth() - 2 - m_borderSize, -m_gcText->GetHeight() / 2), gc);
133 else if (m_angle == 270.0)
134 m_gcText->Draw(m_position + wxPoint2DDouble(-m_gcText->GetWidth() / 2, m_height / 2 - m_gcText->GetHeight() - 2 - m_borderSize), gc);
135
136 gc->SetPen(*wxTRANSPARENT_PEN);
137 gc->SetBrush(wxBrush(wxColour(0, 0, 0, 255)));
138 DrawDCNodes(gc);
139}
140
141bool Gain::ShowForm(wxWindow* parent, Element* element)
142{
143 GainForm form(parent, this);
144 form.CenterOnParent();
145 if (form.ShowModal() == wxID_OK) {
146 return true;
147 }
148 return false;
149}
150
151void Gain::Rotate(bool clockwise)
152{
153 if (clockwise)
154 m_angle += 90.0;
155 else
156 m_angle -= 90.0;
157 if (m_angle >= 360.0)
158 m_angle = 0.0;
159 else if (m_angle < 0)
160 m_angle = 270.0;
161
162 UpdatePoints();
163
164 for (auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
165 Node* node = *it;
166 node->Rotate(clockwise);
167 }
168}
169
170void Gain::SetValue(double value)
171{
172 m_value = value;
173 wxString text = "";
174 if (std::abs(m_value) > 1e3 || std::abs(m_value) < 1e-3)
175 text = wxString::Format("%g", m_value);
176 else
177 text = StringFromDouble(m_value);
178
179 if (m_gcText)
180 m_gcText->SetText(text);
181 else
182 m_gcText = new GCText(text);
183
184 m_width = m_gcText->GetWidth() + 18 + 2 * m_borderSize;
185 m_height = m_gcText->GetHeight() + 18 + 2 * m_borderSize;
186
187 if (m_width > m_height)
188 m_height = m_width;
189 else
190 m_width = m_height;
191
192 SetPosition(m_position); // Update rectangle.
193
194 UpdatePoints();
195}
196
197void Gain::UpdatePoints()
198{
199 if (m_nodeList.size() != 0) {
200 if (m_angle == 0.0) {
201 m_triPts[0] = m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize);
202 m_triPts[1] = m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize);
203 m_triPts[2] = m_position + wxPoint2DDouble(m_width / 2 - m_borderSize, 0);
204 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
205 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(m_width / 2 - 2, 0));
206 }
207 else if (m_angle == 90.0) {
208 m_triPts[0] = m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize);
209 m_triPts[1] = m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize);
210 m_triPts[2] = m_position + wxPoint2DDouble(0, m_height / 2 - m_borderSize);
211 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
212 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2 - 2));
213 }
214 else if (m_angle == 180.0) {
215 m_triPts[0] = m_position + wxPoint2DDouble(-m_width / 2 + m_borderSize, 0);
216 m_triPts[1] = m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize);
217 m_triPts[2] = m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize);
218 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
219 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2 + 2, 0));
220 }
221 else if (m_angle == 270.0) {
222 m_triPts[0] = m_position + wxPoint2DDouble(0, -m_height / 2 + m_borderSize);
223 m_triPts[1] = m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize);
224 m_triPts[2] = m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize);
225 m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
226 m_nodeList[1]->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2 + 2));
227 }
228 }
229}
230
231void Gain::Move(wxPoint2DDouble position)
232{
233 SetPosition(m_movePos + position - m_moveStartPt);
234 UpdatePoints();
235}
236
237bool Gain::Solve(double* input, double timeStep)
238{
239 if (!input) {
240 m_output = 0.0;
241 return true;
242 }
243 m_output = input[0] * m_value;
244 return true;
245}
246
248{
249 Gain* copy = new Gain(m_elementID);
250 *copy = *this;
251 //copy->m_glText = m_glText->GetCopy();
252 copy->m_gcText = m_gcText->GetCopy();
253 return copy;
254}
255
257{
258 SetValue(m_value);
259 //if (!m_glText->IsTextureOK()) return false;
260 return true;
261}
262
263rapidxml::xml_node<>* Gain::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
264{
265 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "Gain");
266 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
267
268 SaveCADProperties(doc, elementNode);
269 SaveControlNodes(doc, elementNode);
270
271 // Element properties
272 auto value = XMLParser::AppendNode(doc, elementNode, "Value");
273 XMLParser::SetNodeValue(doc, value, m_value);
274
275 return elementNode;
276}
277
278bool Gain::OpenElement(rapidxml::xml_node<>* elementNode)
279{
280 if (!OpenCADProperties(elementNode)) return false;
281 if (!OpenControlNodes(elementNode)) return false;
282
283 // Element properties
284 double value = XMLParser::GetNodeValueDouble(elementNode, "Value");
285 SetValue(value);
286 return true;
287}
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
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
static wxString StringFromDouble(double value, int minDecimal=1, int maxDecimals=13)
Convert a double value to string.
Definition Element.cpp:533
Class to draw text on Graphics Context using wxWidgets.
Definition GCText.h:32
virtual GCText * GetCopy()
Get a deep text copy.
Definition GCText.cpp:161
virtual void Draw(wxPoint2DDouble position, wxGraphicsContext *gc, double angle=0.0, wxColour colour= *wxBLACK) const
Draw the text in wxGraphicsContext.
Definition GCText.cpp:35
virtual void SetText(wxString text)
Set correctly a new text string.
Definition GCText.cpp:68
Form to edit the gain control data.
Definition GainForm.h:32
Provide an output multiplying the input by a constant.
Definition Gain.h:37
virtual Element * GetCopy()
Get a the element copy.
Definition Gain.cpp:247
virtual bool UpdateText()
Update the OpenGL text in the element (if present).
Definition Gain.cpp:256
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.
Definition Gain.cpp:141
virtual bool Solve(double *input, double timeStep)
Multiply the input by a constant.
Definition Gain.cpp:237
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
Definition Gain.cpp:87
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Definition Gain.cpp:231
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Gain.cpp:151
Node of a control element. This class manages the user interaction with the connection and control el...