summaryrefslogtreecommitdiffstats
path: root/Project/Divider.cpp
blob: 8cd314076c7c0c0429754213a85a2a71517f4b50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 *  Copyright (C) 2017  Thales Lima Oliveira <thales@ufu.br>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "ConnectionLine.h"
#include "Divider.h"
#include <wx/pen.h>
#include <wx/brush.h>

Divider::Divider(int id) : MathOperation(id) {}
Divider::~Divider() {}
void Divider::DrawSymbol() const
{
    // Plot divider.
    glLineWidth(2.0);
    std::vector<wxPoint2DDouble> mSymbol;
    mSymbol.push_back(m_position + wxPoint2DDouble(-5, 0));
    mSymbol.push_back(m_position + wxPoint2DDouble(5, 0));
    glColor4d(0.0, 0.3, 1.0, 1.0);
    DrawLine(mSymbol, GL_LINES);
    DrawCircle(m_position + wxPoint2DDouble(0, -3), 2, 10, GL_POLYGON);
    DrawCircle(m_position + wxPoint2DDouble(0, 3), 2, 10, GL_POLYGON);
}

void Divider::DrawDCSymbol(wxGraphicsContext* gc) const
{
    // Plot divider.
    gc->SetPen(wxPen(wxColour(0, 77, 255, 255), 2));
    gc->SetBrush(*wxTRANSPARENT_BRUSH);
    wxPoint2DDouble mSymbol[2];
    mSymbol[0] = m_position + wxPoint2DDouble(-5, 0);
    mSymbol[1] = m_position + wxPoint2DDouble(5, 0);
    gc->DrawLines(2, mSymbol);

    gc->SetPen(*wxTRANSPARENT_PEN);
    gc->SetBrush(wxBrush(wxColour(0, 77, 255, 255)));
    DrawDCCircle(m_position + wxPoint2DDouble(0, -3), 2, 10, gc);
    DrawDCCircle(m_position + wxPoint2DDouble(0, 3), 2, 10, gc);
}

bool Divider::Solve(double* input, double timeStep)
{
    // Get the input vector from connection lines (can't use default (one) input argument)
    std::vector<double> inputVector;
    for(auto itN = m_nodeList.begin(), itNEnd = m_nodeList.end(); itN != itNEnd; ++itN) {
        Node* node = *itN;
        if(node->GetNodeType() != Node::NodeType::NODE_OUT) {
            if(!node->IsConnected()) {
                inputVector.push_back(0.0);
            } else {
                for(auto itC = m_childList.begin(), itCEnd = m_childList.end(); itC != itCEnd; ++itC) {
                    ConnectionLine* cLine = static_cast<ConnectionLine*>(*itC);
                    auto nodeList = cLine->GetNodeList();
                    for(auto itCN = nodeList.begin(), itCNEnd = nodeList.end(); itCN != itCNEnd; ++itCN) {
                        Node* childNode = *itCN;
                        if(childNode == node) {
                            inputVector.push_back(cLine->GetValue());
                            break;
                        }
                    }
                }
            }
        }
    }
    if(inputVector.size() != 2) return false;

    // If the denominator is zero, set the output a big number (1e15).
    if(std::abs(inputVector[1]) < 1e-15) {
        m_output = 1e15;
    } else {
        m_output = inputVector[0] / inputVector[1];
    }

    return true;
}

Element* Divider::GetCopy()
{
    Divider* copy = new Divider(m_elementID);
    *copy = *this;
    return copy;
}

rapidxml::xml_node<>* Divider::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
{
    auto elementNode = XMLParser::AppendNode(doc, elementListNode, "Divider");
    XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);

    SaveCADProperties(doc, elementNode);
    SaveControlNodes(doc, elementNode);

    return elementNode;
}

bool Divider::OpenElement(rapidxml::xml_node<>* elementNode)
{
    if(!OpenCADProperties(elementNode)) return false;
    if(!OpenControlNodes(elementNode)) return false;

    StartMove(m_position);
    UpdatePoints();

    return true;
}