Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
Machines.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 "Machines.h"
19
20#include "../controlElement/ControlElementContainer.h"
21#include "../controlElement/ControlElementSolver.h"
22
23Machines::Machines() : PowerElement() {}
24bool Machines::AddParent(Element* parent, wxPoint2DDouble position)
25{
26 if(parent) {
27 m_parentList.push_back(parent);
28 parent->AddChild(this);
29 wxPoint2DDouble parentPt =
30 parent->RotateAtPosition(position, -parent->GetAngle()); // Rotate click to horizontal position.
31 parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus.
32 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); // Rotate back.
33
34 m_position = parentPt + wxPoint2DDouble(-100.0, 0.0); // Shifts the position to the left of the bus.
35 m_width = m_height = 50.0;
36 m_rect = wxRect2DDouble(m_position.m_x - 25.0, m_position.m_y - 25.0, m_width, m_height);
37
38 m_pointList.push_back(parentPt);
39 m_pointList.push_back(GetSwitchPoint(parent, parentPt, m_position));
40 m_pointList.push_back(m_position + wxPoint2DDouble(35.0, 0.0));
41 m_pointList.push_back(m_position + wxPoint2DDouble(25.0, 0.0));
42 m_inserted = true;
43
44 wxRect2DDouble genRect(0, 0, 0, 0);
45 m_switchRect.push_back(genRect); // Push a general rectangle.
47 UpdatePowerFlowArrowsPosition();
48 return true;
49 }
50 return false;
51}
52
53//void Machines::Draw(wxPoint2DDouble translation, double scale) const
54//{
55// OpenGLColour elementColour;
56// if(m_online) {
57// if(m_dynEvent)
58// elementColour = m_dynamicEventColour;
59// else
60// elementColour = m_onlineElementColour;
61// } else
62// elementColour = m_offlineElementColour;
63//
64// if(m_inserted) {
65// // Draw Selection (layer 1).
66// if(m_selected) {
67// glLineWidth(1.5 + m_borderSize * 2.0);
68// glColor4dv(m_selectionColour.GetRGBA());
69// DrawCircle(m_position, 25.0 + (m_borderSize + 1.5) / scale, 20, GL_POLYGON);
70// DrawLine(m_pointList);
71//
72// // Draw node selection.
73// DrawCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, GL_POLYGON);
74// }
75//
76// // Draw Machines (layer 2).
77// glLineWidth(1.5);
78//
79// // Draw node.
80// glColor4dv(elementColour.GetRGBA());
81// DrawCircle(m_pointList[0], 5.0, 10, GL_POLYGON);
82//
83// DrawLine(m_pointList);
84//
85// DrawSwitches();
86// DrawPowerFlowPts();
87//
88// glColor4d(1.0, 1.0, 1.0, 1.0);
89// DrawCircle(m_position, 25.0, 20, GL_POLYGON);
90//
91// glColor4dv(elementColour.GetRGBA());
92// DrawCircle(m_position, 25.0, 20);
93//
94// // Draw machine symbol.
95// glLineWidth(2.0);
96// DrawSymbol();
97// }
98//}
99
100void Machines::DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext* gc) const
101{
102 wxColour elementColour;
103 if (m_online) {
104 if (m_dynEvent)
105 elementColour = m_dynamicEventColour;
106 else
107 elementColour = m_onlineElementColour;
108 }
109 else
110 elementColour = m_offlineElementColour;
111
112 if (m_inserted) {
113 // Draw Selection (layer 1).
114 if (m_selected) {
115 gc->SetPen(wxPen(m_selectionColour, 2 + m_borderSize * 2.0));
116 gc->SetBrush(*wxTRANSPARENT_BRUSH);
117 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
118
119 gc->SetPen(*wxTRANSPARENT_PEN);
120 gc->SetBrush(wxBrush(m_selectionColour));
121 DrawDCCircle(m_position, 25.0 + (m_borderSize + 1.5) / scale, 20, gc);
122
123 // Draw nodes selection.
124 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, gc);
125 }
126
127 // Draw Machines (layer 2).
128 // Draw node.
129 gc->SetPen(*wxTRANSPARENT_PEN);
130 gc->SetBrush(wxBrush(elementColour));
131 DrawDCCircle(m_pointList[0], 5.0, 10, gc);
132
133 gc->SetPen(wxPen(wxColour(elementColour), 2));
134 gc->SetBrush(*wxTRANSPARENT_BRUSH);
135 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
136 DrawDCCircle(m_position, 25.0, 20.0, gc);
137
138 DrawDCSwitches(gc);
140
141 gc->SetPen(*wxTRANSPARENT_PEN);
142 gc->SetBrush(*wxWHITE_BRUSH);
143 DrawDCCircle(m_position, 25.0, 20.0, gc);
144
145 gc->SetPen(wxPen(elementColour, 2));
146 gc->SetBrush(*wxTRANSPARENT_BRUSH);
147 DrawDCCircle(m_position, 25.0, 20.0, gc);
148
149 // Draw machine symbol.
150 DrawDCSymbol(gc);
151 }
152}
153
154void Machines::DrawDC(wxPoint2DDouble translation, double scale, wxDC& dc) const
155{
156 wxColour elementColour;
157 if (m_online) {
158 if (m_dynEvent)
159 elementColour = m_dynamicEventColour;
160 else
161 elementColour = m_onlineElementColour;
162 }
163 else
164 elementColour = m_offlineElementColour;
165
166 std::vector<wxPoint> pointListInt;
167 for(auto& pt : m_pointList) {
168 pointListInt.emplace_back(static_cast<int>(pt.m_x), static_cast<int>(pt.m_y));
169 }
170
171 if (m_inserted) {
172 // Draw Selection (layer 1).
173 if (m_selected) {
174 dc.SetPen(wxPen(m_selectionColour, 2 + m_borderSize * 2.0));
175 dc.SetBrush(*wxTRANSPARENT_BRUSH);
176 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
177
178 dc.SetPen(*wxTRANSPARENT_PEN);
179 dc.SetBrush(wxBrush(m_selectionColour));
180 DrawDCCircle(m_position, 25.0 + (m_borderSize + 1.5) / scale, dc);
181
182 // Draw nodes selection.
183 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, dc);
184 }
185
186 // Draw Machines (layer 2).
187 // Draw node.
188 dc.SetPen(*wxTRANSPARENT_PEN);
189 dc.SetBrush(wxBrush(elementColour));
190 DrawDCCircle(m_pointList[0], 5.0, dc);
191
192 dc.SetPen(wxPen(wxColour(elementColour), 2));
193 dc.SetBrush(*wxTRANSPARENT_BRUSH);
194 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
195 DrawDCCircle(m_position, 25.0, dc);
196
197 DrawDCSwitches(dc);
199
200 dc.SetPen(*wxTRANSPARENT_PEN);
201 dc.SetBrush(*wxWHITE_BRUSH);
202 DrawDCCircle(m_position, 25.0, dc);
203
204 dc.SetPen(wxPen(elementColour, 2));
205 dc.SetBrush(*wxTRANSPARENT_BRUSH);
206 DrawDCCircle(m_position, 25.0, dc);
207
208 // Draw machine symbol.
209 DrawDCSymbol(dc);
210 }
211}
212
213void Machines::UpdateSwitchesPosition()
214{
215 if(m_parentList[0]) {
216 m_pointList[1] = GetSwitchPoint(m_parentList[0], m_pointList[0], m_pointList[2]);
217 } else {
218 m_pointList[1] = m_pointList[0];
219 }
221}
222
223void Machines::Move(wxPoint2DDouble position)
224{
225 SetPosition(m_movePos + position - m_moveStartPt);
226 for(int i = 2; i < (int)m_pointList.size(); i++) {
227 m_pointList[i] = m_movePts[i] + position - m_moveStartPt;
228 }
229 if(!m_parentList[0]) {
230 m_pointList[0] = m_movePts[0] + position - m_moveStartPt;
231 }
232 UpdateSwitchesPosition();
233 UpdatePowerFlowArrowsPosition();
234}
235
236void Machines::MoveNode(Element* element, wxPoint2DDouble position)
237{
238 if(element) {
239 if(element == m_parentList[0]) {
240 m_pointList[0] = m_movePts[0] + position - m_moveStartPt;
241 }
242 } else {
243 if(m_activeNodeID == 1) {
244 m_pointList[0] = m_movePts[0] + position - m_moveStartPt;
245 if(m_parentList[0]) {
246 m_parentList[0]->RemoveChild(this);
247 m_parentList[0] = nullptr;
248 m_online = false;
249 }
250 }
251 }
252
253 // Recalculate switches positions
254 UpdateSwitchesPosition();
255 UpdatePowerFlowArrowsPosition();
256}
257
258void Machines::StartMove(wxPoint2DDouble position)
259{
260 m_moveStartPt = position;
261 m_movePts = m_pointList;
262 m_movePos = m_position;
263}
264
265void Machines::RotateNode(Element* parent, bool clockwise)
266{
267 double rotAngle = m_rotationAngle;
268 if(!clockwise) rotAngle = -m_rotationAngle;
269
270 if(parent == m_parentList[0]) {
271 m_pointList[0] = parent->RotateAtPosition(m_pointList[0], rotAngle);
272 UpdateSwitchesPosition();
273 UpdatePowerFlowArrowsPosition();
274 }
275}
276
278{
279 if(parent == m_parentList[0]) {
280 m_parentList[0] = nullptr;
281 m_online = false;
282 UpdateSwitchesPosition();
283 UpdatePowerFlowArrowsPosition();
284 }
285}
286
287bool Machines::NodeContains(wxPoint2DDouble position)
288{
289 wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize,
290 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize);
291
292 if(nodeRect.Contains(position)) {
293 m_activeNodeID = 1;
294 return true;
295 }
296
297 m_activeNodeID = 0;
298 return false;
299}
300
302{
303 if(parent && m_activeNodeID != 0) {
304 wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize,
305 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize);
306
307 if(parent->Intersects(nodeRect)) {
308 m_parentList[0] = parent;
309
310 // Centralize the node on bus.
311 wxPoint2DDouble parentPt =
312 parent->RotateAtPosition(m_pointList[0], -parent->GetAngle()); // Rotate click to horizontal position.
313 parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus.
314 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle());
315 m_pointList[0] = parentPt;
316
317 UpdateSwitchesPosition();
318 UpdatePowerFlowArrowsPosition();
319 return true;
320 } else {
321 m_parentList[0] = nullptr;
322 m_online = false;
323 }
324 }
325 return false;
326}
327
329{
330 if(m_parentList[0]) {
331 wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize,
332 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize);
333
334 if(!m_parentList[0]->Intersects(nodeRect)) {
335 m_parentList[0]->RemoveChild(this);
336 m_parentList[0] = nullptr;
337 m_online = false;
338 UpdateSwitchesPosition();
339 UpdatePowerFlowArrowsPosition();
340 }
341 }
342}
343
344void Machines::Rotate(bool clockwise)
345{
346 double rotAngle = m_rotationAngle;
347 if(!clockwise) rotAngle = -m_rotationAngle;
348
349 m_angle += rotAngle;
350 if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
351 m_pointList[2] = RotateAtPosition(m_pointList[2], rotAngle);
352 m_pointList[3] = RotateAtPosition(m_pointList[3], rotAngle);
353 UpdateSwitchesPosition();
354 UpdatePowerFlowArrowsPosition();
355}
356
357void Machines::UpdatePowerFlowArrowsPosition()
358{
359 std::vector<wxPoint2DDouble> edges;
360 switch(m_pfDirection) {
362 m_powerFlowArrow.clear();
363 } break;
365 edges.push_back(m_pointList[2]);
366 edges.push_back(m_pointList[1]);
367 } break;
369 edges.push_back(m_pointList[1]);
370 edges.push_back(m_pointList[2]);
371 } break;
372 default:
373 break;
374 }
375
377}
378
380{
381 m_pfDirection = pfDirection;
382 UpdatePowerFlowArrowsPosition();
383}
PowerFlowDirection
Direction of power flow arrows.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
virtual bool Intersects(wxRect2DDouble rect) const =0
Check if the element's rect intersects other rect.
wxPoint2DDouble GetPosition() const
Get the element position.
Definition Element.h:186
double GetAngle() const
Get the element angle.
Definition Element.h:211
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
Definition Element.cpp:27
virtual wxPoint2DDouble RotateAtPosition(wxPoint2DDouble pointToRotate, double angle, bool degrees=true) const
Rotate a point as element position being the origin.
Definition Element.cpp:292
virtual void AddChild(Element *child)
Add a child to the child list.
Definition Element.cpp:566
virtual void DrawDCCircle(wxPoint2DDouble position, double radius, int numSegments, wxGraphicsContext *gc) const
Draw a circle using device context.
Definition Element.cpp:177
virtual void RemoveParent(Element *parent)
Remove a parent.
Definition Machines.cpp:277
virtual bool Intersects(wxRect2DDouble rect) const
Check if the element's rect intersects other rect.
Definition Machines.h:46
virtual void SetPowerFlowDirection(PowerFlowDirection pfDirection)
Set the direction of the power flow.
Definition Machines.cpp:379
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Definition Machines.cpp:223
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
Definition Machines.cpp:100
virtual void UpdateNodes()
Update the nodes according to the parents. If a parent is removed, use this method.
Definition Machines.cpp:328
virtual bool NodeContains(wxPoint2DDouble position)
Check if a node contains a point. If contains, set the attributes related to node movement.
Definition Machines.cpp:287
virtual void RotateNode(Element *parent, bool clockwise=true)
Rotate a node.
Definition Machines.cpp:265
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Machines.cpp:24
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Machines.cpp:258
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Machines.cpp:344
virtual void MoveNode(Element *element, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
Definition Machines.cpp:236
virtual bool SetNodeParent(Element *parent)
Set a perent to the node. If all conditions are met, a new parent are added to the element and the po...
Definition Machines.cpp:301
Abstract class of power elements.
virtual void CalculatePowerFlowPts(std::vector< wxPoint2DDouble > edges)
Calculate the points of the power flow arrows.
virtual void DrawDCSwitches(wxGraphicsContext *gc) const
Draw switch.
virtual void UpdateSwitches()
Update the switch position.
virtual void DrawDCPowerFlowPts(wxGraphicsContext *gc) const
Draw power flow arrows.
virtual wxPoint2DDouble GetSwitchPoint(Element *parent, wxPoint2DDouble parentPoint, wxPoint2DDouble secondPoint) const
Get the correct switch position.