20#include "../../forms/SumForm.h"
26 m_width = m_height = 36.0;
27 Node* nodeIn1 =
new Node(m_position + wxPoint2DDouble(-m_width / 2, 9 - m_height / 2), Node::NodeType::NODE_IN, m_borderSize);
28 nodeIn1->StartMove(m_position);
30 new Node(m_position + wxPoint2DDouble(-m_width / 2, 27 - m_height / 2), Node::NodeType::NODE_IN, m_borderSize);
31 nodeIn2->StartMove(m_position);
32 Node* nodeOut =
new Node(m_position + wxPoint2DDouble(m_width / 2, 0), Node::NodeType::NODE_OUT, m_borderSize);
33 nodeOut->SetAngle(180.0);
34 nodeOut->StartMove(m_position);
35 m_nodeList.push_back(nodeIn1);
36 m_nodeList.push_back(nodeIn2);
37 m_nodeList.push_back(nodeOut);
38 m_signalList.push_back(SIGNAL_POSITIVE);
39 m_signalList.push_back(SIGNAL_NEGATIVE);
46 for (
auto& node : m_nodeList) if (node) delete node;
50void Sum::DrawDC(
GUIColour* guiColour, wxPoint2DDouble translation,
double scale, wxGraphicsContext* gc)
const
53 gc->SetPen(*wxTRANSPARENT_PEN);
54 gc->SetBrush(wxBrush(guiColour->selection));
55 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
56 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);
58 gc->SetPen(wxPen(guiColour->enabled));
59 gc->SetBrush(wxBrush(guiColour->background));
60 gc->DrawRectangle(m_position.m_x - m_width / 2, m_position.m_y - m_height / 2, m_width, m_height);
63 gc->SetPen(wxPen(guiColour->enabled, 2));
64 gc->SetBrush(*wxTRANSPARENT_BRUSH);
65 wxPoint2DDouble signalOffset[4];
66 wxPoint2DDouble sigmaOffset;
68 signalOffset[0] = wxPoint2DDouble(6, 0);
69 signalOffset[1] = wxPoint2DDouble(12, 0);
70 signalOffset[2] = wxPoint2DDouble(9, -3);
71 signalOffset[3] = wxPoint2DDouble(9, 3);
72 sigmaOffset = wxPoint2DDouble(6, 0);
74 else if (m_angle == 90.0) {
75 signalOffset[0] = wxPoint2DDouble(-3, 9);
76 signalOffset[1] = wxPoint2DDouble(3, 9);
77 signalOffset[2] = wxPoint2DDouble(0, 6);
78 signalOffset[3] = wxPoint2DDouble(0, 12);
79 sigmaOffset = wxPoint2DDouble(0, 6);
81 else if (m_angle == 180.0) {
82 signalOffset[0] = wxPoint2DDouble(-6, 0);
83 signalOffset[1] = wxPoint2DDouble(-12, 0);
84 signalOffset[2] = wxPoint2DDouble(-9, -3);
85 signalOffset[3] = wxPoint2DDouble(-9, 3);
86 sigmaOffset = wxPoint2DDouble(-6, 0);
88 else if (m_angle == 270.0) {
89 signalOffset[0] = wxPoint2DDouble(-3, -9);
90 signalOffset[1] = wxPoint2DDouble(3, -9);
91 signalOffset[2] = wxPoint2DDouble(0, -6);
92 signalOffset[3] = wxPoint2DDouble(0, -12);
93 sigmaOffset = wxPoint2DDouble(0, -6);
95 for (
unsigned int i = 0; i < m_nodeList.size() - 1; ++i) {
96 wxPoint2DDouble hLine[2];
97 hLine[0] = m_nodeList[i]->GetPosition() + signalOffset[0];
98 hLine[1] = m_nodeList[i]->GetPosition() + signalOffset[1];
99 gc->StrokeLines(2, hLine);
100 if (m_signalList[i] == SIGNAL_POSITIVE) {
101 wxPoint2DDouble vLine[2];
102 vLine[0] = m_nodeList[i]->GetPosition() + signalOffset[2];
103 vLine[1] = m_nodeList[i]->GetPosition() + signalOffset[3];
104 gc->StrokeLines(2, vLine);
109 gc->SetPen(wxPen(guiColour->bus, 2));
110 wxPoint2DDouble sigma[5];
111 sigma[0] = m_position + wxPoint2DDouble(4, 9) + sigmaOffset;
112 sigma[1] = m_position + wxPoint2DDouble(-6, 9) + sigmaOffset;
113 sigma[2] = m_position + wxPoint2DDouble(0, 0) + sigmaOffset;
114 sigma[3] = m_position + wxPoint2DDouble(-6, -9) + sigmaOffset;
115 sigma[4] = m_position + wxPoint2DDouble(4, -9) + sigmaOffset;
116 gc->StrokeLines(5, sigma);
118 gc->SetPen(*wxTRANSPARENT_PEN);
119 gc->SetBrush(wxBrush(guiColour->enabled));
126 sumForm.CenterOnParent();
127 if (sumForm.ShowModal() == wxID_OK) {
133void Sum::UpdatePoints()
135 if (m_angle == 0.0 || m_angle == 180.0) {
136 m_height = 18.0 * (m_nodeList.size() - 1);
140 m_width = 18.0 * (m_nodeList.size() - 1);
144 for (
int i = 0; i < (int)m_nodeList.size() - 1; ++i) {
146 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 9 + 18 * i - m_height / 2));
147 else if (m_angle == 90.0)
148 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(m_width / 2 - 9 - 18 * i, -m_height / 2));
149 else if (m_angle == 180.0)
150 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, m_height / 2 - 9 - 18 * i));
151 else if (m_angle == 270.0)
152 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(9 + 18 * i - m_width / 2, m_height / 2));
155 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
156 else if (m_angle == 90.0)
157 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
158 else if (m_angle == 180.0)
159 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
160 else if (m_angle == 270.0)
161 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
168 Node* newNode =
new Node(wxPoint2DDouble(0, 0), Node::NodeType::NODE_IN, m_borderSize);
169 newNode->SetAngle(m_angle);
170 m_nodeList.insert(m_nodeList.end() - 1, newNode);
173void Sum::RemoveInNode()
175 Node* nodeToRemove = *(m_nodeList.end() - 2);
176 bool foundChild =
false;
177 for (
auto it = m_childList.begin(), itEnd = m_childList.end(); it != itEnd; ++it) {
179 auto childNodeList = child->GetNodeList();
180 for (
auto itN = childNodeList.begin(), itEndN = childNodeList.end(); itN != itEndN; ++itN) {
182 if (node == nodeToRemove) {
189 if (foundChild)
break;
191 m_nodeList.erase(m_nodeList.end() - 2);
200 if (m_angle >= 360.0)
202 else if (m_angle < 0)
207 for (
auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
209 node->Rotate(clockwise);
213bool Sum::Solve(
double* input,
double timeStep)
219 std::vector<double> inputVector;
220 for (
auto itN = m_nodeList.begin(), itNEnd = m_nodeList.end(); itN != itNEnd; ++itN) {
222 if (node->GetNodeType() != Node::NodeType::NODE_OUT) {
223 if (!node->IsConnected()) {
224 inputVector.push_back(0.0);
227 for (
auto itC = m_childList.begin(), itCEnd = m_childList.end(); itC != itCEnd; ++itC) {
229 auto nodeList = cLine->GetNodeList();
230 for (
auto itCN = nodeList.begin(), itCNEnd = nodeList.end(); itCN != itCNEnd; ++itCN) {
231 Node* childNode = *itCN;
232 if (childNode == node) {
233 inputVector.push_back(cLine->GetValue());
242 if (m_signalList.size() != inputVector.size())
return false;
245 for (
unsigned int i = 0; i < m_signalList.size(); ++i) {
246 if (m_signalList[i] == SIGNAL_POSITIVE)
247 m_output += inputVector[i];
248 else if (m_signalList[i] == SIGNAL_NEGATIVE)
249 m_output -= inputVector[i];
256 Sum* copy =
new Sum(*
this);
260rapidxml::xml_node<>* Sum::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
262 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Sum");
263 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
265 SaveCADProperties(doc, elementNode);
266 SaveControlNodes(doc, elementNode);
269 auto signsNode = XMLParser::AppendNode(doc, elementNode,
"Signs");
270 for (
unsigned int i = 0; i < m_signalList.size(); ++i) {
271 auto value = XMLParser::AppendNode(doc, signsNode,
"Value");
272 XMLParser::SetNodeValue(doc, value,
static_cast<int>(m_signalList[i]));
278bool Sum::OpenElement(rapidxml::xml_node<>* elementNode)
280 if (!OpenCADProperties(elementNode))
return false;
281 if (!OpenControlNodes(elementNode))
return false;
283 m_signalList.clear();
284 auto signsNode = elementNode->first_node(
"Signs");
285 auto sign = signsNode->first_node(
"Value");
288 wxString(sign->value()).ToCLong(&value);
289 m_signalList.push_back(
static_cast<Sum::Signal
>(value));
290 sign = sign->next_sibling(
"Value");
Connection between two control elements or other connection line and an element.
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...
virtual void RemoveChild(Element *child)
Remove a child from the list.
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
virtual void RemoveParent(Element *parent)
Remove a parent.
Node of a control element. This class manages the user interaction with the connection and control el...
Sum the all inputs (can choose the input signal).
virtual bool ShowForm(wxWindow *parent, Element *element, wxWindow *workspace=nullptr)
Show element data form.
virtual Element * GetCopy()
Get a the element copy.
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual void DrawDC(GUIColour *guiColour, wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.