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;
119void Sum::DrawDC(wxPoint2DDouble translation,
double scale, wxGraphicsContext* gc)
const
122 gc->SetPen(*wxTRANSPARENT_PEN);
123 gc->SetBrush(wxBrush(m_selectionColour));
124 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
125 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);
127 gc->SetPen(*wxBLACK_PEN);
128 gc->SetBrush(*wxWHITE_BRUSH);
129 gc->DrawRectangle(m_position.m_x - m_width / 2, m_position.m_y - m_height / 2, m_width, m_height);
132 gc->SetPen(wxPen(wxColour(0, 0, 0, 255), 2));
133 gc->SetBrush(*wxTRANSPARENT_BRUSH);
134 wxPoint2DDouble signalOffset[4];
135 wxPoint2DDouble sigmaOffset;
136 if (m_angle == 0.0) {
137 signalOffset[0] = wxPoint2DDouble(6, 0);
138 signalOffset[1] = wxPoint2DDouble(12, 0);
139 signalOffset[2] = wxPoint2DDouble(9, -3);
140 signalOffset[3] = wxPoint2DDouble(9, 3);
141 sigmaOffset = wxPoint2DDouble(6, 0);
143 else if (m_angle == 90.0) {
144 signalOffset[0] = wxPoint2DDouble(-3, 9);
145 signalOffset[1] = wxPoint2DDouble(3, 9);
146 signalOffset[2] = wxPoint2DDouble(0, 6);
147 signalOffset[3] = wxPoint2DDouble(0, 12);
148 sigmaOffset = wxPoint2DDouble(0, 6);
150 else if (m_angle == 180.0) {
151 signalOffset[0] = wxPoint2DDouble(-6, 0);
152 signalOffset[1] = wxPoint2DDouble(-12, 0);
153 signalOffset[2] = wxPoint2DDouble(-9, -3);
154 signalOffset[3] = wxPoint2DDouble(-9, 3);
155 sigmaOffset = wxPoint2DDouble(-6, 0);
157 else if (m_angle == 270.0) {
158 signalOffset[0] = wxPoint2DDouble(-3, -9);
159 signalOffset[1] = wxPoint2DDouble(3, -9);
160 signalOffset[2] = wxPoint2DDouble(0, -6);
161 signalOffset[3] = wxPoint2DDouble(0, -12);
162 sigmaOffset = wxPoint2DDouble(0, -6);
164 for (
unsigned int i = 0; i < m_nodeList.size() - 1; ++i) {
165 wxPoint2DDouble hLine[2];
166 hLine[0] = m_nodeList[i]->GetPosition() + signalOffset[0];
167 hLine[1] = m_nodeList[i]->GetPosition() + signalOffset[1];
168 gc->StrokeLines(2, hLine);
169 if (m_signalList[i] == SIGNAL_POSITIVE) {
170 wxPoint2DDouble vLine[2];
171 vLine[0] = m_nodeList[i]->GetPosition() + signalOffset[2];
172 vLine[1] = m_nodeList[i]->GetPosition() + signalOffset[3];
173 gc->StrokeLines(2, vLine);
178 gc->SetPen(wxPen(wxColour(0, 77, 255, 255), 2));
179 wxPoint2DDouble sigma[5];
180 sigma[0] = m_position + wxPoint2DDouble(4, 9) + sigmaOffset;
181 sigma[1] = m_position + wxPoint2DDouble(-6, 9) + sigmaOffset;
182 sigma[2] = m_position + wxPoint2DDouble(0, 0) + sigmaOffset;
183 sigma[3] = m_position + wxPoint2DDouble(-6, -9) + sigmaOffset;
184 sigma[4] = m_position + wxPoint2DDouble(4, -9) + sigmaOffset;
185 gc->StrokeLines(5, sigma);
187 gc->SetPen(*wxTRANSPARENT_PEN);
188 gc->SetBrush(*wxBLACK_BRUSH);
195 sumForm.CenterOnParent();
196 if (sumForm.ShowModal() == wxID_OK) {
202void Sum::UpdatePoints()
204 if (m_angle == 0.0 || m_angle == 180.0) {
205 m_height = 18.0 * (m_nodeList.size() - 1);
209 m_width = 18.0 * (m_nodeList.size() - 1);
213 for (
int i = 0; i < (int)m_nodeList.size() - 1; ++i) {
215 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 9 + 18 * i - m_height / 2));
216 else if (m_angle == 90.0)
217 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(m_width / 2 - 9 - 18 * i, -m_height / 2));
218 else if (m_angle == 180.0)
219 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, m_height / 2 - 9 - 18 * i));
220 else if (m_angle == 270.0)
221 m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(9 + 18 * i - m_width / 2, m_height / 2));
224 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
225 else if (m_angle == 90.0)
226 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
227 else if (m_angle == 180.0)
228 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
229 else if (m_angle == 270.0)
230 m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
237 Node* newNode =
new Node(wxPoint2DDouble(0, 0), Node::NodeType::NODE_IN, m_borderSize);
238 newNode->SetAngle(m_angle);
239 m_nodeList.insert(m_nodeList.end() - 1, newNode);
242void Sum::RemoveInNode()
244 Node* nodeToRemove = *(m_nodeList.end() - 2);
245 bool foundChild =
false;
246 for (
auto it = m_childList.begin(), itEnd = m_childList.end(); it != itEnd; ++it) {
248 auto childNodeList = child->GetNodeList();
249 for (
auto itN = childNodeList.begin(), itEndN = childNodeList.end(); itN != itEndN; ++itN) {
251 if (node == nodeToRemove) {
258 if (foundChild)
break;
260 m_nodeList.erase(m_nodeList.end() - 2);
269 if (m_angle >= 360.0)
271 else if (m_angle < 0)
276 for (
auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
278 node->Rotate(clockwise);
282bool Sum::Solve(
double* input,
double timeStep)
288 std::vector<double> inputVector;
289 for (
auto itN = m_nodeList.begin(), itNEnd = m_nodeList.end(); itN != itNEnd; ++itN) {
291 if (node->GetNodeType() != Node::NodeType::NODE_OUT) {
292 if (!node->IsConnected()) {
293 inputVector.push_back(0.0);
296 for (
auto itC = m_childList.begin(), itCEnd = m_childList.end(); itC != itCEnd; ++itC) {
298 auto nodeList = cLine->GetNodeList();
299 for (
auto itCN = nodeList.begin(), itCNEnd = nodeList.end(); itCN != itCNEnd; ++itCN) {
300 Node* childNode = *itCN;
301 if (childNode == node) {
302 inputVector.push_back(cLine->GetValue());
311 if (m_signalList.size() != inputVector.size())
return false;
314 for (
unsigned int i = 0; i < m_signalList.size(); ++i) {
315 if (m_signalList[i] == SIGNAL_POSITIVE)
316 m_output += inputVector[i];
317 else if (m_signalList[i] == SIGNAL_NEGATIVE)
318 m_output -= inputVector[i];
325 Sum* copy =
new Sum(m_elementID);
330rapidxml::xml_node<>* Sum::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
332 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"Sum");
333 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
335 SaveCADProperties(doc, elementNode);
336 SaveControlNodes(doc, elementNode);
339 auto signsNode = XMLParser::AppendNode(doc, elementNode,
"Signs");
340 for (
unsigned int i = 0; i < m_signalList.size(); ++i) {
341 auto value = XMLParser::AppendNode(doc, signsNode,
"Value");
342 XMLParser::SetNodeValue(doc, value,
static_cast<int>(m_signalList[i]));
348bool Sum::OpenElement(rapidxml::xml_node<>* elementNode)
350 if (!OpenCADProperties(elementNode))
return false;
351 if (!OpenControlNodes(elementNode))
return false;
353 m_signalList.clear();
354 auto signsNode = elementNode->first_node(
"Signs");
355 auto sign = signsNode->first_node(
"Value");
358 wxString(sign->value()).ToCLong(&value);
359 m_signalList.push_back(
static_cast<Sum::Signal
>(value));
360 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 Element * GetCopy()
Get a the element copy.
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.