diff --git a/.github/screenshot.png b/.github/screenshot.png
new file mode 100644
index 0000000..eaa76d8
Binary files /dev/null and b/.github/screenshot.png differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..89fc649
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+*.suo
+*.user
+*.sln.docstates
+*.sln.metaproj
+*.sln.metaproj.tmp
+.vs/
+.vscode/
+*.cache
+[Bb]in/
+[Oo]bj/
+Build/
+Source/x64
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6802bc4
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..57c5eb8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# Beamax
+
+Beamax is an application for visually editing and analyzing continuous beam structures.
+
+
\ No newline at end of file
diff --git a/Samples/Example.bcb b/Samples/Example.bcb
new file mode 100644
index 0000000..dd5be6e
Binary files /dev/null and b/Samples/Example.bcb differ
diff --git a/Source/Analysis.cpp b/Source/Analysis.cpp
new file mode 100644
index 0000000..3fdd8a9
--- /dev/null
+++ b/Source/Analysis.cpp
@@ -0,0 +1,1101 @@
+#include
+#include
+#include
+#include "stdafx.h"
+#include "Analysis.h"
+
+Matrix::Matrix()
+{
+ _rows = 0;
+ _columns = 0;
+ _data = NULL;
+}
+
+Matrix::Matrix(int rows, int columns)
+{
+ _rows = rows;
+ _columns = columns;
+ _data = new double[rows * columns];
+ Fill(0.0);
+}
+
+Matrix::Matrix(int rows, int columns, double diagonal)
+{
+ _rows = rows;
+ _columns = columns;
+ _data = new double[rows * columns];
+ for (int i = 0; i < rows; i++)
+ {
+ for (int j = 0; j < columns; j++)
+ {
+ Set(i, j, (i == j) ? diagonal : 0.0);
+ }
+ }
+}
+
+Matrix::Matrix(Matrix& matrix)
+{
+ _rows = matrix._rows;
+ _columns = matrix._columns;
+ int size = _rows * _columns;
+ _data = new double[size];
+ for (int i = 0; i < size; i++)
+ {
+ _data[i] = matrix._data[i];
+ }
+}
+
+Matrix::~Matrix()
+{
+ if (_data != NULL)
+ {
+ delete _data;
+ _data = NULL;
+ }
+}
+
+void Matrix::Fill(double value)
+{
+ int size = _rows * _columns;
+ for (int i = 0; i < size; i++)
+ {
+ _data[i] = value;
+ }
+}
+
+void Matrix::Set(int row, int column, double value)
+{
+ _data[row * _columns + column] = value;
+}
+
+double& Matrix::Get(int row, int column)
+{
+ return _data[row * _columns + column];
+}
+
+Matrix& Matrix::operator=(Matrix& matrix)
+{
+ if (_data != NULL)
+ {
+ delete _data;
+ _data = NULL;
+ }
+ _rows = matrix._rows;
+ _columns = matrix._columns;
+ int size = _rows * _columns;
+ _data = new double[size];
+ for (int i = 0; i < size; i++)
+ {
+ _data[i] = matrix._data[i];
+ }
+ return *this;
+}
+
+double& Matrix::operator() (int row, int column)
+{
+ return Get(row, column);
+}
+
+void Matrix::Add(Matrix& a, Matrix& b)
+{
+ if (a.GetRows() == b.GetRows() && a.GetColumns() == b.GetColumns())
+ {
+ if (_data != NULL)
+ {
+ delete _data;
+ _data = NULL;
+ }
+ _rows = a.GetRows();
+ _columns = a.GetColumns();
+ _data = new double[_rows * _columns];
+ for (int i = 0; i < _rows; i++)
+ {
+ for (int j = 0; j < _columns; j++)
+ {
+ Set(i, j, a(i, j) + b(i, j));
+ }
+ }
+ }
+}
+
+void Matrix::Sub(Matrix& a, Matrix& b)
+{
+ if (a.GetRows() == b.GetRows() && a.GetColumns() == b.GetColumns())
+ {
+ if (_data != NULL)
+ {
+ delete _data;
+ _data = NULL;
+ }
+ _rows = a.GetRows();
+ _columns = a.GetColumns();
+ _data = new double[_rows * _columns];
+ for (int i = 0; i < _rows; i++)
+ {
+ for (int j = 0; j < _columns; j++)
+ {
+ Set(i, j, a(i, j) - b(i, j));
+ }
+ }
+ }
+}
+
+void Matrix::Mul(Matrix& a, Matrix& b)
+{
+ if (a.GetColumns() == b.GetRows())
+ {
+ _rows = a.GetRows();
+ _columns = b.GetColumns();
+ int length = a.GetColumns();
+ if (_data != NULL)
+ {
+ delete _data;
+ _data = NULL;
+ }
+ _data = new double[_rows * _columns];
+ for (int i = 0; i < _rows; i++)
+ {
+ for (int j = 0; j < _columns; j++)
+ {
+ double value = 0;
+ for (int k = 0; k < length; k++)
+ {
+ value += a(i, k) * b(k, j);
+ }
+ Set(i, j, value);
+ }
+ }
+ }
+}
+
+Matrix& Matrix::operator+=(Matrix& b)
+{
+ Matrix copy(*this);
+ Add(copy, b);
+ return *this;
+}
+
+Matrix& Matrix::operator-=(Matrix& b)
+{
+ Matrix copy(*this);
+ Sub(copy, b);
+ return *this;
+}
+
+Matrix& Matrix::operator*=(Matrix& b)
+{
+ Matrix copy(*this);
+ Mul(copy, b);
+ return *this;
+}
+
+void Matrix::operator*=(double scalar)
+{
+ for (int i = 0; i < GetRows(); i++)
+ {
+ for (int j = 0; j < GetColumns(); j++)
+ {
+ Set(i, j, Get(i, j) * scalar);
+ }
+ }
+}
+
+void Matrix::Solve(Matrix& matrix, Matrix& result)
+{
+ double d = matrix.Determinant();
+ if (fabs(d) > 0.00000000000001)
+ {
+ Matrix arg(2, 2);
+ double d1;
+ double d2;
+ for (int n = 0; n < 2; n++)
+ {
+ arg = matrix;
+ for (int i = 0; i < 2; i++)
+ {
+ arg(i, n) = result(i, 0);
+ }
+ if (n == 0)
+ {
+ d1 = arg.Determinant();
+ }
+ else
+ {
+ d2 = arg.Determinant();
+ }
+ }
+
+ Set(0, 0, d1 / d);
+ Set(1, 0, d2 / d);
+ }
+}
+
+double Matrix::Determinant()
+{
+ if (_rows != 2 || _columns != 2)
+ {
+ throw;
+ }
+ return Get(0, 0) * Get(1, 1) - Get(1, 0) * Get(0, 1);
+}
+
+void Matrix::Inverse()
+{
+ if (_rows != 2 || _columns != 2)
+ {
+ throw;
+ }
+ Matrix result(2, 1);
+ Matrix copy(*this);
+ Matrix unk1(2, 1);
+ Matrix unk2(2, 1);
+ result(0, 0) = 1;
+ result(1, 0) = 0;
+ unk1.Solve(copy, result);
+ result(0, 0) = 0;
+ result(1, 0) = 1;
+ unk2.Solve(copy, result);
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < 2; j++)
+ {
+ Set(i, j, j == 0 ? unk1(i, 0) : unk2(i, 0));
+ }
+ }
+}
+
+void List::Add(void* item)
+{
+ _current = _current->Next = CreateNode(_current, _current->Next, item);
+ if (_current->Next != NULL)
+ {
+ _current->Next->Prev = _current;
+ }
+}
+
+void List::Remove()
+{
+ struct Node* current;
+ if ((current = _current) != NULL)
+ {
+ struct Node* prev = _current->Prev;
+ struct Node* next = _current->Next;
+
+ if (Prev() != TRUE)
+ {
+ _root = _current->Next;
+ if (Next() == TRUE)
+ {
+ _root->Prev = NULL;
+ }
+ else
+ {
+ _current = NULL;
+ }
+ }
+ else
+ {
+ prev->Next = next;
+ if (next != NULL)
+ {
+ next->Prev = prev;
+ }
+ }
+ delete current->Data;
+ delete current;
+ }
+}
+
+void List::Clear()
+{
+ Reset();
+ while (!IsEmpty())
+ {
+ Remove();
+ }
+}
+
+int List::Prev()
+{
+ if (_current->Prev == NULL)
+ {
+ return FALSE;
+ }
+ _current = _current->Prev;
+ return TRUE;
+}
+
+void List::Reset()
+{
+ _current = _root;
+}
+
+
+Node* List::CreateNode(struct Node* previous, struct Node* next, void* data)
+{
+ struct Node* node = new Node;
+ node->Prev = previous;
+ node->Next = next;
+ node->Data = data;
+ return node;
+}
+
+void List::Insert(void* item)
+{
+ if (_root == NULL)
+ {
+ _current = _root = CreateNode(NULL, NULL, item);
+ }
+ else
+ {
+ _current = _root = _root->Prev = CreateNode(NULL, _root, item);
+ }
+}
+
+List::List()
+{
+ _root = NULL;
+ _current = NULL;
+}
+
+List::~List()
+{
+ Reset();
+ while (!IsEmpty())
+ {
+ Remove();
+ }
+}
+
+int List::Next()
+{
+ if (_current->Next == NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ _current = _current->Next;
+ }
+ return TRUE;
+}
+
+void SupportNode::SetForce(Matrix& matrix)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ _force(i, 0) = matrix(i, 0);
+ }
+}
+
+
+Matrix& SupportNode::GetForce()
+{
+ return _force;
+}
+
+void SupportNode::GetKnownRows(int rows[2])
+{
+ int j = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ if ((fabs(_state(i, 0)) < EPSILON) && (fabs(_state(i, 1)) < EPSILON))
+ {
+ rows[j] = i;
+ j = 1;
+ }
+ }
+}
+
+void SupportNode::GetUnknownRows(int rows[2])
+{
+ int j = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ if ((fabs(_state(i, 0)) > EPSILON) || (fabs(_state(i, 1)) > EPSILON))
+ {
+ rows[j] = i;
+ j = 1;
+ }
+ }
+}
+
+HingedSupportNode::HingedSupportNode(double position)
+{
+ _position = position;
+ _force = Matrix(4, 1);
+ _state = Matrix(4, 2);
+ _state(1, 0) = 1;
+ _state(3, 1) = 1;
+}
+
+FixedSupportNode::FixedSupportNode(double position)
+{
+ _position = position;
+ _force = Matrix(4, 1);
+ _state = Matrix(4, 2);
+ _state(2, 0) = 1;
+ _state(3, 1) = 1;
+}
+
+FreeSupportNode::FreeSupportNode(double position)
+{
+ _position = position;
+ _force = Matrix(4, 1);
+ _state = Matrix(4, 2);
+ _state(0, 0) = 1;
+ _state(1, 1) = 1;
+}
+
+double LoadNode::GetDistance(double)
+{
+ return 0.0;
+}
+
+Matrix& LoadNode::GetLoadVector(double)
+{
+ return _dummy;
+}
+
+LoadNode::LoadNode()
+{
+ _isSupportLoad = FALSE;
+ _dummy = Matrix(4, 1);
+}
+
+int LoadNode::IsLoadVector(double, double)
+{
+ return FALSE;
+}
+
+PointLoadNode::PointLoadNode(double start, double value)
+{
+ _value = value;
+ _start = start;
+ _vector = Matrix(4, 1);
+}
+
+double PointLoadNode::GetDistance(double start)
+{
+ if (!_isSupportLoad)
+ {
+ if (fabs(start - GetStart()) < EPSILON)
+ {
+ return 0.0;
+ }
+ if (start - GetStart() < EPSILON)
+ {
+ return GetStart() - start;
+ }
+ }
+ return (double)-1;
+}
+
+Matrix& PointLoadNode::GetLoadVector(double)
+{
+ if (!_isSupportLoad)
+ {
+ _vector(3, 0) = GetValue() * (-1.0);
+ }
+ return _vector;
+}
+
+int PointLoadNode::IsLoadVector(double start, double length)
+{
+ if (!_isSupportLoad && length < EPSILON)
+ {
+ if (fabs(start - GetStart()) < EPSILON)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+LineadDistributedLoadNode::LineadDistributedLoadNode(double start, double length, double value)
+{
+ _start = start;
+ _length = length;
+ _value = value;
+ _vector = Matrix(4, 1);
+}
+
+double LineadDistributedLoadNode::GetDistance(double start)
+{
+ if (fabs(start - GetStart()) < EPSILON)
+ {
+ return GetLength();
+ }
+ double end = GetStart() + GetLength();
+ if (fabs(start - end) < EPSILON || start > end)
+ {
+ return (double)-1;
+ }
+ if (start < GetStart())
+ {
+ return GetStart() - start;
+ }
+ return end - start;
+}
+
+Matrix& LineadDistributedLoadNode::GetLoadVector(double length)
+{
+ double p = length;
+ _vector(3, 0) = GetValue() * p * (-1.0);
+ p *= length;
+ _vector(2, 0) = GetValue() * p * (-1.0) / 2;
+ p *= length;
+ _vector(1, 0) = GetValue() * p / 6;
+ p *= length;
+ _vector(0, 0) = GetValue() * p / 24;
+ return _vector;
+}
+
+int LineadDistributedLoadNode::IsLoadVector(double start, double length)
+{
+ if (length > EPSILON)
+ {
+ if (((GetStart() - EPSILON) <= start) && (start <= (GetStart() + GetLength() - EPSILON)))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void Beam::InsertSupport(SupportNode* support)
+{
+ int Eingefuegt = FALSE;
+ _sections.Reset();
+ if (_sections.IsEmpty())
+ {
+ _sections.Insert(support);
+ Eingefuegt = TRUE;
+ }
+ while (!Eingefuegt)
+ {
+ if (fabs(((SupportNode*)_sections.GetItem())->GetPosition() - support->GetPosition()) < EPSILON) {
+ if (_sections.Prev() == FALSE)
+ _sections.Insert(support);
+ else
+ _sections.Add(support);
+ _sections.Remove();
+ Eingefuegt = TRUE;
+ }
+ else if (((SupportNode*)_sections.GetItem())->GetPosition() > support->GetPosition()) {
+ if (_sections.Prev() == FALSE)
+ _sections.Insert(support);
+ else
+ _sections.Add(support);
+
+ Eingefuegt = TRUE;
+ }
+ else
+ {
+ if (_sections.Next() == FALSE) {
+ _sections.Add(support);
+ Eingefuegt = TRUE;
+ }
+ }
+ }
+}
+
+void Beam::InsertLoad(LoadNode* load)
+{
+ int success = FALSE;
+ _loads.Reset();
+ if (_loads.IsEmpty())
+ {
+ _loads.Insert(load);
+ success = TRUE;
+ }
+ while (!success)
+ {
+ if ((((LoadNode *)_loads.GetItem())->GetStart()) > (load->GetStart()))
+ {
+ if (_loads.Prev() == FALSE)
+ {
+ _loads.Insert(load);
+ }
+ else
+ {
+ _loads.Add(load);
+ }
+ success = TRUE;
+ }
+ else
+ {
+ if (_loads.Next() == FALSE) {
+ _loads.Add(load);
+ success = TRUE;
+ }
+ }
+ }
+}
+
+void Beam::GetMatrix(Matrix& A, double distance)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ double p = 1;
+ for (int j = i; j < 4; j++)
+ {
+ A(i, j) = (i == j) ? 1.0 : p / Factorial(j - i);
+ p *= distance;
+ if ((i < 2) && (j > 1))
+ {
+ A(i, j) /= (-1 * _EI);
+ }
+ }
+ }
+}
+
+double Beam::GetDistance(double start, double end, int &pointLoad)
+{
+ double distance = end - start;
+ double currentDistance = 0;
+ int next = TRUE;
+ _loads.Reset();
+ if (_loads.IsEmpty())
+ {
+ next = FALSE;
+ }
+ while (next)
+ {
+ currentDistance = ((LoadNode *)_loads.GetItem())->GetDistance(start);
+ if (!(fabs(currentDistance + 1) < EPSILON))
+ {
+ if (currentDistance < distance)
+ {
+ if (currentDistance < EPSILON)
+ {
+ if (pointLoad == TRUE)
+ {
+ distance = 0.0;
+ }
+ }
+ else
+ {
+ distance = currentDistance;
+ }
+ }
+ }
+ if (_loads.Next() == FALSE)
+ {
+ next = FALSE;
+ }
+ }
+ return distance;
+}
+
+void Beam::GetLoadVector(Matrix& L, double start, double length)
+{
+ _loads.Reset();
+ if (!_loads.IsEmpty())
+ {
+ Matrix NewLastVektor(4, 1);
+ do
+ {
+ LoadNode* p = (LoadNode*)_loads.GetItem();
+ if (p->IsLoadVector(start, length))
+ {
+ NewLastVektor = p->GetLoadVector(length);
+ NewLastVektor(0, 0) /= _EI;
+ NewLastVektor(1, 0) /= _EI;
+ L += NewLastVektor;
+ }
+ }
+ while (_loads.Next());
+ }
+}
+
+void Beam::SetCurrentSupportForces(Matrix& forces, SupportNode* previous, Matrix& A, Matrix& L)
+{
+ SupportNode* current = (SupportNode*)_sections.GetItem();
+ Matrix matrix = Matrix(A);
+ Matrix loadVector = L;
+ Matrix _z1 = Matrix(2, 2);
+ Matrix _l1 = Matrix(2, 1);
+ double start = previous->GetPosition();
+ double end = current->GetPosition();
+ int isPointLoad = FALSE;
+ double distance;
+ while (start < end)
+ {
+ distance = GetDistance(start, end, isPointLoad);
+ isPointLoad = distance < EPSILON ? FALSE : TRUE;
+ if (distance > EPSILON)
+ {
+ Matrix A(4, 4);
+ GetMatrix(A, distance);
+ Matrix copy(matrix);
+ matrix.Mul(A, copy);
+ copy = loadVector;
+ loadVector.Mul(A, copy);
+ }
+ GetLoadVector(loadVector, start, distance);
+ start += distance;
+ }
+ GetLoadVector(loadVector, start, 0.0);
+ if (_sections.Next())
+ {
+ int zeilebe[2];
+ int zeileun[2];
+ previous->GetKnownRows(zeilebe);
+ previous->GetUnknownRows(zeileun);
+ zeilebe[0] = 0;
+ zeilebe[1] = 1;
+ zeileun[0] = 2;
+ zeileun[1] = 3;
+ Matrix z1(2, 2);
+ Matrix z2(2, 2);
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < 2; j++)
+ {
+ z1(i, j) = matrix(zeilebe[i], j);
+ z2(i, j) = matrix(zeileun[i], j);
+ }
+ }
+ Matrix l1(2, 1);
+ Matrix l2(2, 1);
+ for (int i = 0; i < 2; i++)
+ {
+ l1(i, 0) = loadVector(zeilebe[i], 0);
+ l2(i, 0) = loadVector(zeileun[i], 0);
+ }
+ z1.Inverse();
+ Matrix kk(2, 2);
+ Matrix lk(2, 1);
+ kk.Mul(z2, z1);
+ lk.Mul(kk, l1);
+ lk *= -1;
+ lk += l2;
+ _z1 = z1;
+ _l1 = l1;
+ Matrix transfer(4, 4, 1);
+ L.Fill(0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < 2; j++)
+ {
+ transfer(i + 2, j) = kk(i, j);
+ L(i + 2, 0) = lk(i, 0);
+ }
+ }
+ A.Mul(transfer, current->GetState());
+ matrix = A;
+ loadVector = L;
+ SetCurrentSupportForces(forces, current, A, L);
+ Matrix support(matrix);
+ Matrix supportForces(4, 1);
+ supportForces(3, 0) = forces(1, 0);
+ support *= forces;
+ support += loadVector;
+ current->SetForce(supportForces);
+ Matrix temp(2, 1);
+ forces.Fill(0.0);
+ for (int i = 0; i < 2; i++)
+ {
+ temp(i, 0) = support(i, 0);
+ }
+ temp -= _l1;
+ forces.Mul(_z1, temp);
+ }
+ else
+ {
+ Matrix A(2, 2);
+ Matrix result(2, 1);
+ int zeilebe[2];
+ Matrix support(matrix);
+ current->GetKnownRows(zeilebe);
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < 2; j++)
+ {
+ A(i, j) = matrix(zeilebe[i], j);
+ }
+ result(i, 0) = loadVector(zeilebe[i], 0);
+ }
+ result *= -1;
+ forces.Solve(A, result);
+ support *= forces;
+ support += loadVector;
+ _endState = support;
+ _endState *= -1;
+ for (int i = 0; i < 2; i++)
+ {
+ support(i, 0) = 0;
+ }
+ support(3, 0) *= -1;
+ current->SetForce(support);
+ }
+}
+
+Beam::Beam()
+{
+ _startState = Matrix(4, 1);
+ _endState = Matrix(4, 1);
+}
+
+Beam::~Beam()
+{
+ _loads.Clear();
+ _sections.Clear();
+}
+
+double Beam::Factorial(int value)
+{
+ if (value <= 1)
+ {
+ return (double)1;
+ }
+ return (double)value * Factorial(value - 1);
+}
+
+void Beam::ComputeSupportForces()
+{
+ SupportNode* current;
+ Matrix A(4, 2);
+ Matrix L(4, 1);
+ Matrix forces(2, 1);
+ Matrix support(4, 1);
+ int zeileun[2];
+ LoadNode* last;
+ _sections.Reset();
+ do {
+ current = ((SupportNode*)_sections.GetItem());
+ if (current->IsSupport())
+ {
+ if (!_loads.IsEmpty())
+ {
+ double position = current->GetPosition();
+ _loads.Reset();
+ do
+ {
+ last = ((LoadNode *)_loads.GetItem());
+ if (last->GetLength() == 0.0 && fabs(last->GetStart() - position) < EPSILON)
+ {
+ last->MarkSupportLoad();
+ }
+ }
+ while (_loads.Next());
+ }
+ }
+ }
+ while (_sections.Next());
+
+ _sections.Reset();
+
+ if (!_sections.IsEmpty())
+ {
+ current = ((SupportNode*)_sections.GetItem());
+ A = current->GetState();
+ if (_sections.Next())
+ {
+ SetCurrentSupportForces(forces, current, A, L);
+ }
+ current->GetUnknownRows(zeileun);
+ for (int i = 0; i < 2; i++)
+ {
+ if (zeileun[i] > 1)
+ {
+ support(zeileun[i], 0) = forces(i, 0);
+ }
+ }
+ current->SetForce(support);
+ for (int i = 0; i < 2; i++)
+ {
+ _startState(zeileun[i], 0) = forces(i, 0);
+ }
+ }
+}
+
+HRESULT __stdcall Beam::SetLength(double length)
+{
+ _length = length;
+ return S_OK;
+}
+
+HRESULT __stdcall Beam::SetEI(double modulusOfElasticity, double momentOfInertia)
+{
+ _EI = modulusOfElasticity * momentOfInertia;
+ return S_OK;
+}
+
+HRESULT Beam::CreateFixedSupport(double position)
+{
+ FixedSupportNode* obj = new FixedSupportNode(position);
+ InsertSupport(obj);
+ return S_OK;
+}
+
+HRESULT Beam::CreateHingedSupport(double position)
+{
+ HingedSupportNode* obj = new HingedSupportNode(position);
+ InsertSupport(obj);
+ return S_OK;
+}
+
+HRESULT Beam::CreateRollerSupport(double position)
+{
+ HingedSupportNode* obj = new HingedSupportNode(position);
+ InsertSupport(obj);
+ return S_OK;
+}
+
+HRESULT Beam::CreatePointLoad(double position, double value)
+{
+ if (position >= EPSILON)
+ {
+ PointLoadNode* obj = new PointLoadNode(position, value);
+ InsertLoad(obj);
+ }
+ return S_OK;
+}
+
+HRESULT Beam::CreateLinearDistributedLoad(double position, double value, double length)
+{
+ LineadDistributedLoadNode* obj = new LineadDistributedLoadNode(position, length, value);
+ InsertLoad(obj);
+ return S_OK;
+}
+
+HRESULT Beam::Analyse()
+{
+ SupportNode* support;
+ BOOL left = FALSE;
+ BOOL right = FALSE;
+ _sections.Reset();
+ if (!_sections.IsEmpty())
+ do
+ {
+ support = (SupportNode*)_sections.GetItem();
+ if (support != NULL)
+ {
+ if (support->GetPosition() == 0)
+ left = TRUE;
+ if (support->GetPosition() == _length)
+ right = TRUE;
+ }
+ }
+ while (_sections.Next());
+ if (!left)
+ {
+ InsertSupport(new FreeSupportNode(0));
+ }
+ if (!right)
+ {
+ InsertSupport(new FreeSupportNode(_length));
+ }
+ Section* Q;
+ Section* M;
+ Section* W;
+ ComputeSupportForces();
+ _sections.Reset();
+ Matrix state1(4, 1);
+ Matrix state2(4, 1);
+ Matrix A(4, 4);
+ Matrix L(4, 1);
+ double position = 0;
+ int isPointLoad = TRUE;
+ if (!_sections.IsEmpty())
+ {
+ do
+ {
+ double end = ((SupportNode*)_sections.GetItem())->GetPosition();
+ while (position < end)
+ {
+ double distance = GetDistance(position, end, isPointLoad);
+ isPointLoad = distance < EPSILON ? FALSE : TRUE;
+ if (distance > EPSILON)
+ {
+ A = Matrix(4, 4);
+ GetMatrix(A, distance);
+ A *= state2;
+ state2 = A;
+ }
+ L.Fill(0.0);
+ GetLoadVector(L, position, distance);
+ state2 += L;
+ if (distance > EPSILON)
+ {
+ // shear force
+ Q = new Section;
+ Q->Start = position;
+ Q->Length = distance;
+ Q->A4 = 0;
+ Q->A3 = 0;
+ Q->A2 = 0;
+ Q->A1 = (state2(3, 0) - state1(3, 0)) / distance;
+ Q->A0 = state1(3, 0);
+
+ // bending moment
+ M = new Section;
+ M->Start = position;
+ M->Length = distance;
+ M->A4 = 0;
+ M->A3 = 0;
+ M->A2 = (state2(3, 0) - state1(3, 0)) / (2 * distance);
+ M->A1 = state1(3, 0);
+ M->A0 = state1(2, 0);
+
+ // displacement
+ W = new Section;
+ double Q1 = state1(3, 0) * (-1);
+ double M1 = state1(2, 0) * (-1);
+ double phi1 = state1(1, 0) * _EI;
+ double w1 = state1(0, 0) * _EI;
+ double Q2 = state2(3, 0) * (-1);
+ W->Start = position;
+ W->Length = distance;
+ W->A4 = ((Q2 - Q1) / (24 * distance)) / _EI;
+ W->A3 = (Q1 / 6) / _EI;
+ W->A2 = (M1 / 2) / _EI;
+ W->A1 = phi1 / _EI;
+ W->A0 = w1 / _EI;
+ _shearForces.Insert(Q);
+ _bendingMoments.Insert(M);
+ _displacements.Insert(W);
+ }
+ position += distance;
+ state1 = state2;
+ }
+
+ if (position < EPSILON)
+ {
+ state2 = _startState;
+ }
+ else
+ {
+ if (fabs(position - _length) < EPSILON)
+ {
+ state2 += _endState;
+ }
+ else
+ {
+ SupportNode* support = (SupportNode*) _sections.GetItem();
+ state2 += support->GetForce();
+ }
+ }
+ state1 = state2;
+ }
+ while (_sections.Next());
+ }
+ _shearForces.Reset();
+ _bendingMoments.Reset();
+ _displacements.Reset();
+ return S_OK;
+}
+
+HRESULT Beam::GetNextSection(Section* shearForce, Section* bendingMoment, Section* displacement)
+{
+ memcpy(shearForce, _shearForces.GetItem(), sizeof(Section));
+ memcpy(bendingMoment, _bendingMoments.GetItem(), sizeof(Section));
+ memcpy(displacement, _displacements.GetItem(), sizeof(Section));
+ if (_shearForces.Next() && _bendingMoments.Next() && _displacements.Next())
+ {
+ return S_OK;
+ }
+ return S_FALSE;
+}
diff --git a/Source/Analysis.h b/Source/Analysis.h
new file mode 100644
index 0000000..616cc4e
--- /dev/null
+++ b/Source/Analysis.h
@@ -0,0 +1,212 @@
+#ifndef __Analysis__
+#define __Analysis__
+
+#include
+#include
+#include
+#include
+
+#define TRUE 1
+#define FALSE 0
+#define EPSILON 0.000001
+
+class Matrix
+{
+private:
+ int _rows;
+ int _columns;
+ double* _data;
+
+public:
+ Matrix();
+ Matrix(Matrix& Ma);
+ Matrix(int row, int column);
+ Matrix(int row, int column, double diagonal);
+ ~Matrix();
+ inline int GetRows() { return _rows; };
+ inline int GetColumns() { return _columns; };
+ void Set(int row, int column, double value);
+ double& Get(int row, int column);
+ void Fill(double value);
+ void Add(Matrix& a, Matrix& b);
+ void Mul(Matrix& a, Matrix& b);
+ void Sub(Matrix& a, Matrix& b);
+ double& operator()(int row, int column);
+ Matrix& operator=(Matrix& NewMatrix);
+ Matrix& operator+=(Matrix& Summand);
+ Matrix& operator-=(Matrix& Summand);
+ Matrix& operator*=(Matrix& Faktor);
+ void operator*=(double Scalar);
+
+ void Inverse();
+ double Determinant();
+ void Solve(Matrix& matrix, Matrix& result);
+};
+
+struct Node
+{
+ struct Node* Next;
+ struct Node* Prev;
+ void* Data;
+};
+
+class List
+{
+private:
+ struct Node* _root;
+ struct Node* _current;
+ Node* CreateNode(struct Node* previous, struct Node* next, void* data);
+
+public:
+ List();
+ ~List();
+ inline int IsEmpty() { return _root == NULL; };
+ inline void* GetItem() { return _current->Data; };
+ void Insert(void* item);
+ void Add(void* item);
+ void Remove();
+ int Next();
+ int Prev();
+ void Reset();
+ void Clear();
+};
+
+class SupportNode
+{
+protected:
+ double _position;
+ Matrix _state;
+ Matrix _force;
+
+public:
+ virtual int IsSupport() { return TRUE; }
+ inline double GetPosition() { return _position; };
+ inline Matrix& GetState() { return _state; };
+ Matrix& GetForce();
+ void SetForce(Matrix& matrix);
+ void GetKnownRows(int rows[2]);
+ void GetUnknownRows(int rows[2]);
+};
+
+class FixedSupportNode : public SupportNode
+{
+public:
+ FixedSupportNode(double StuetzStelle);
+ int IsSupport() { return TRUE; }
+};
+
+class HingedSupportNode : public SupportNode
+{
+public:
+ HingedSupportNode(double StuetzStelle);
+ int IsSupport() { return TRUE; }
+};
+
+class FreeSupportNode : public SupportNode
+{
+public:
+ FreeSupportNode(double StuetzStelle);
+ int IsSupport() { return FALSE; }
+};
+
+class LoadNode
+{
+protected:
+ double _start;
+ double _value;
+ double _length;
+ Matrix _dummy;
+ int _isSupportLoad;
+
+public:
+ LoadNode();
+
+ inline double GetValue() { return _value; };
+ inline double GetStart() { return _start; };
+ inline double GetLength() { return _length; };
+
+ void MarkSupportLoad() { _isSupportLoad = TRUE; }
+
+ virtual double GetDistance(double start);
+ virtual int IsLoadVector(double start, double length);
+ virtual Matrix& GetLoadVector(double delta);
+};
+
+class PointLoadNode : public LoadNode
+{
+private:
+ Matrix _vector;
+
+public:
+ PointLoadNode(double start, double value);
+ double GetDistance(double start);
+ int IsLoadVector(double start, double length);
+ Matrix& GetLoadVector(double length);
+};
+
+class LineadDistributedLoadNode : public LoadNode
+{
+private:
+ Matrix _vector;
+
+public:
+ LineadDistributedLoadNode(double start, double length, double value);
+ double GetDistance(double start);
+ int IsLoadVector(double start, double length);
+ Matrix& GetLoadVector(double length);
+};
+
+struct Section
+{
+ double Start;
+ double Length;
+ double A0;
+ double A1;
+ double A2;
+ double A3;
+ double A4;
+};
+
+
+class Beam
+{
+private:
+ double _length;
+ double _EI;
+
+public:
+ Matrix _startState;
+ Matrix _endState;
+ List _loads;
+ List _sections;
+ List _shearForces;
+ List _bendingMoments;
+ List _displacements;
+
+public:
+ Beam();
+ ~Beam();
+
+private:
+ void InsertSupport(SupportNode* load);
+ void InsertLoad(LoadNode* load);
+ double Factorial(int value);
+ void ComputeSupportForces();
+ void SetCurrentSupportForces(Matrix& forces, SupportNode* previous, Matrix& A, Matrix& L);
+ double GetDistance(double start, double end, int& isPointLoad);
+ void GetLoadVector(Matrix& L, double start, double distance);
+ void GetMatrix(Matrix& A, double distance);
+
+public:
+ HRESULT __stdcall SetLength(double length);
+ HRESULT __stdcall SetEI(double modulusOfElasticity, double momentOfInertia);
+ HRESULT __stdcall CreateFixedSupport(double position);
+ HRESULT __stdcall CreateHingedSupport(double position);
+ HRESULT __stdcall CreateRollerSupport(double position);
+ HRESULT __stdcall CreatePointLoad(double position, double value);
+ HRESULT __stdcall CreateLinearDistributedLoad(double position, double value, double length);
+ HRESULT __stdcall Analyse();
+ HRESULT __stdcall GetNextSection(Section* shearForce, Section* bendingMoment, Section* displacement);
+};
+
+#endif
diff --git a/Source/Application.cpp b/Source/Application.cpp
new file mode 100644
index 0000000..4ee9076
--- /dev/null
+++ b/Source/Application.cpp
@@ -0,0 +1,156 @@
+#include "stdafx.h"
+#include "Resource.h"
+#include "Application.h"
+#include "Dialog.h"
+#include "Object.h"
+#include "Document.h"
+#include "View.h"
+
+Application _application;
+
+IMPLEMENT_DYNAMIC(ApplicationWindow, CMDIFrameWnd)
+
+BEGIN_MESSAGE_MAP(ApplicationWindow, CMDIFrameWnd)
+ ON_WM_CREATE()
+ ON_WM_DESTROY()
+ ON_COMMAND(ID_HELP_INDEX, CMDIFrameWnd::OnHelpIndex)
+END_MESSAGE_MAP()
+
+static UINT _toolBarButtons[] =
+{
+ ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE, ID_SEPARATOR,
+ IDM_PROPERTIES, ID_SEPARATOR,
+ IDM_FIXED_SUPPORT, IDM_HINGED_SUPPORT, IDM_ROLLER_SUPPORT, ID_SEPARATOR,
+ IDM_POINT_LOAD, IDM_LINEAR_DISTRIBUTED_LOAD, ID_SEPARATOR,
+ IDM_DELETE, ID_SEPARATOR,
+ IDM_VIEW_CONTINUOUS_BEAM, IDM_VIEW_SHEAR_FORCE,
+ IDM_VIEW_BENDING_MOMENT, IDM_VIEW_DISPLACEMENT, ID_SEPARATOR,
+ IDM_VIEW_NUMERICAL_VALUES
+};
+
+int ApplicationWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
+ {
+ return -1;
+ }
+
+ // initialize toolbar
+ if (!_toolBar.Create(this) || !_toolBar.LoadBitmap(IDR_MAIN_FRAME) || !_toolBar.SetButtons(_toolBarButtons, sizeof(_toolBarButtons) / sizeof(UINT)))
+ {
+ return -1;
+ }
+ _toolBar.SetBarStyle(_toolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+ _toolBar.EnableDocking(CBRS_ALIGN_ANY);
+ EnableDocking(CBRS_ALIGN_ANY);
+ DockControlBar(&_toolBar);
+
+ _toolBar.SetWindowText("ToolBar");
+
+ // translate view buttons into check boxes
+ int image;
+ UINT style;
+ UINT id;
+
+ for (int i = 15; i <= 17; i++)
+ {
+ _toolBar.GetButtonInfo(i, id, style, image);
+ _toolBar.SetButtonInfo(i, id, TBBS_CHECKBOX, image);
+ }
+ _toolBar.GetButtonInfo(20, id, style, image);
+ _toolBar.SetButtonInfo(20, id, TBBS_CHECKBOX, image);
+
+ return 0;
+}
+
+BEGIN_MESSAGE_MAP(Application, CWinApp)
+ ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
+ ON_COMMAND(ID_FILE_NEW, OnFileCreate)
+ ON_COMMAND(IDM_ABOUT, OnAbout)
+ ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
+END_MESSAGE_MAP()
+
+extern "C" const GUID CLSID_System = { 0xC48F2271, 0x54E5, 0x11D1, { 0xBC, 0x97, 0x00, 0x80, 0x5F, 0x8C, 0x5D, 0x94 } };
+
+Application::Application()
+{
+ _beamLength = 10.0;
+ _beamCreate = TRUE;
+}
+
+BOOL Application::InitInstance()
+{
+ // initialize OLE libraries
+ if (!AfxOleInit())
+ {
+ return FALSE;
+ }
+
+ // enable application settings
+ LoadStdProfileSettings();
+
+ // register document and view class
+ CMultiDocTemplate * DocTemplate;
+ DocTemplate = new CMultiDocTemplate(IDR_DOCUMENT, RUNTIME_CLASS(Document), RUNTIME_CLASS(CMDIChildWnd), RUNTIME_CLASS(View));
+ AddDocTemplate(DocTemplate);
+
+ ApplicationWindow* applicationWindow = new ApplicationWindow;
+ if (!applicationWindow->LoadFrame(IDR_MAIN_FRAME))
+ {
+ return FALSE;
+ }
+
+ m_pMainWnd = applicationWindow;
+
+ // enable drag and drop
+ m_pMainWnd->DragAcceptFiles();
+
+ // register object factories
+ _oleTemplateServer.ConnectTemplate(CLSID_System, DocTemplate, FALSE);
+ COleTemplateServer::RegisterAll();
+
+ // if automation return
+ if (RunEmbedded() || RunAutomated())
+ {
+ return TRUE;
+ }
+
+ // add objects to system registry
+ _oleTemplateServer.UpdateRegistry(OAT_DISPATCH_OBJECT);
+ COleObjectFactory::UpdateRegistryAll();
+
+ m_pMainWnd->ShowWindow(m_nCmdShow);
+ m_pMainWnd->UpdateWindow();
+
+ // phrase command line
+ if (m_lpCmdLine[0] != '\0')
+ {
+ OpenDocumentFile(m_lpCmdLine);
+ }
+
+ return TRUE;
+}
+
+void Application::OnFileCreate()
+{
+ CreateBeamDialog dialog;
+
+ dialog.SetLength(_beamLength);
+ if (dialog.DoModal() == IDOK)
+ {
+ _beamLength = dialog.GetLength();
+ _beamCreate = TRUE;
+ }
+ else
+ {
+ _beamCreate = FALSE;
+ }
+
+ OnFileNew();
+}
+
+void Application::OnAbout(void)
+{
+ AboutDialog dialog;
+ dialog.DoModal();
+}
diff --git a/Source/Application.h b/Source/Application.h
new file mode 100644
index 0000000..33a202b
--- /dev/null
+++ b/Source/Application.h
@@ -0,0 +1,36 @@
+#ifndef __Beamax__
+#define __Beamax__
+
+class ApplicationWindow : public CMDIFrameWnd
+{
+private:
+ CToolBar _toolBar;
+
+protected:
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+
+ DECLARE_MESSAGE_MAP()
+ DECLARE_DYNAMIC(ApplicationWindow)
+};
+
+class Application : public CWinApp
+{
+private:
+ COleTemplateServer _oleTemplateServer;
+
+public:
+ Application();
+ virtual BOOL InitInstance();
+ void DefaultAnalysis();
+ void OnFileCreate();
+
+ double _beamLength;
+ BOOL _beamCreate;
+
+protected:
+ afx_msg void OnAbout(void);
+
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif
\ No newline at end of file
diff --git a/Source/Application.ico b/Source/Application.ico
new file mode 100644
index 0000000..35d685b
Binary files /dev/null and b/Source/Application.ico differ
diff --git a/Source/Application.rc b/Source/Application.rc
new file mode 100644
index 0000000..fb3ee0b
--- /dev/null
+++ b/Source/Application.rc
@@ -0,0 +1,348 @@
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+
+#include "Resource.h"
+#include "afxres.h"
+
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""Resource.h""\r\n"
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+IDR_MAIN_FRAME ICON "Application.ico"
+IDR_DOCUMENT ICON "Document.ico"
+IDR_MAIN_FRAME BITMAP "ToolBar.bmp"
+
+IDR_MAIN_FRAME MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM SEPARATOR
+ MENUITEM "Page Set&up...", ID_FILE_PRINT_SETUP
+ MENUITEM SEPARATOR
+ MENUITEM "Rescent File", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit\tCtrl+X", ID_APP_EXIT
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About...", IDM_ABOUT
+ END
+END
+
+IDR_DOCUMENT MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM "&Close", ID_FILE_CLOSE
+ MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
+ MENUITEM "Save &As...", ID_FILE_SAVE_AS
+ MENUITEM SEPARATOR
+ MENUITEM "Page Set&up...", ID_FILE_PRINT_SETUP
+ MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "Rescent File", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit\tCtrl+X", ID_APP_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Delete\tDel", IDM_DELETE
+ MENUITEM "&Properties", IDM_PROPERTIES
+ POPUP "&Create"
+ BEGIN
+ MENUITEM "&Fixed Support\tAlt+X", IDM_FIXED_SUPPORT
+ MENUITEM "&Hinged Support\tAlt+N", IDM_HINGED_SUPPORT
+ MENUITEM "&Roller Support\tAlt+R", IDM_ROLLER_SUPPORT
+ MENUITEM SEPARATOR
+ MENUITEM "&Point Load\tAlt+P", IDM_POINT_LOAD
+ MENUITEM "&Linear Distributed Load\tAlt+L",
+ IDM_LINEAR_DISTRIBUTED_LOAD
+
+ END
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Beam with Loads", IDM_VIEW_CONTINUOUS_BEAM
+ MENUITEM "&Shear Force", IDM_VIEW_SHEAR_FORCE
+ MENUITEM "&Bending Moment", IDM_VIEW_BENDING_MOMENT
+ MENUITEM "&Displacement", IDM_VIEW_DISPLACEMENT
+ MENUITEM SEPARATOR
+ MENUITEM "&Numerical Values", IDM_VIEW_NUMERICAL_VALUES
+ MENUITEM SEPARATOR
+ MENUITEM "&Toolbar", ID_VIEW_TOOLBAR, CHECKED
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&New View", ID_WINDOW_NEW
+ MENUITEM "&Cascade", ID_WINDOW_CASCADE
+ MENUITEM "&Tile", ID_WINDOW_TILE_HORZ
+ MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About...", IDM_ABOUT
+ END
+END
+
+IDR_MAIN_FRAME ACCELERATORS
+BEGIN
+ "X", ID_APP_EXIT, VIRTKEY, CONTROL, NOINVERT
+ "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
+ "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "P", ID_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ VK_F1, ID_HELP_INDEX, VIRTKEY, NOINVERT
+ VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT
+ VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT
+ "P", ID_PRINT, VIRTKEY, CONTROL, NOINVERT
+ VK_DELETE, IDM_DELETE, VIRTKEY, NOINVERT
+ "X", IDM_FIXED_SUPPORT, VIRTKEY, ALT, NOINVERT
+ "N", IDM_HINGED_SUPPORT, VIRTKEY, ALT, NOINVERT
+ "L", IDM_LINEAR_DISTRIBUTED_LOAD, VIRTKEY, ALT, NOINVERT
+ "P", IDM_POINT_LOAD, VIRTKEY, ALT, NOINVERT
+ "R", IDM_ROLLER_SUPPORT, VIRTKEY, ALT, NOINVERT
+END
+
+IDD_CREATE_BEAM DIALOGEX 12, 29, 152, 68
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "New Beam..."
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Beam length:",IDC_STATIC,9,18,43,8
+ EDITTEXT IDC_BEAM_LENGTH,57,16,64,12
+ PUSHBUTTON "OK",IDOK,24,46,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,80,46,48,14,WS_GROUP | NOT WS_TABSTOP
+ LTEXT "[m]",IDC_STATIC,125,18,14,8
+END
+
+IDD_PROPERTIES DIALOGEX 12, 29, 190, 89
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Properties"
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Modulus of elasticity:",IDC_STATIC,9,11,70,8
+ EDITTEXT IDC_MODULUS_OF_ELASTICITY,84,9,64,12
+ PUSHBUTTON "OK",IDOK,44,66,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,96,66,48,14,WS_GROUP | NOT WS_TABSTOP
+ LTEXT "[N/mm²]",IDC_STATIC,153,11,32,8
+ LTEXT "Moment of inertia:",IDC_STATIC,9,28,65,8
+ EDITTEXT IDC_MOMENT_OF_INERTIA,83,26,64,12
+ LTEXT "Axial area:",IDC_STATIC,10,44,65,8
+ EDITTEXT IDC_AXIAL_AREA,83,43,64,12
+ LTEXT "[cm^4]",IDC_STATIC,153,27,28,8
+ LTEXT "[cm²]",IDC_STATIC,153,45,23,8
+END
+
+IDD_HINGED_SUPPORT DIALOGEX 12, 29, 163, 76
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Hinged Support"
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Support position:",IDC_STATIC,12,18,56,8
+ EDITTEXT IDC_POSITION,69,16,62,12
+ PUSHBUTTON "OK",IDOK,28,53,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,84,53,48,14,WS_GROUP | NOT WS_TABSTOP
+ LTEXT "[m]",IDC_STATIC,135,18,12,8
+END
+
+IDD_FIXED_SUPPORT DIALOGEX 12, 29, 161, 76
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Fixed Support"
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Position:",IDC_STATIC,38,11,30,8
+ CONTROL "left end",IDC_POSITION_LEFT, "Button",BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP,74,10,68,12
+ CONTROL "right end",IDC_POSITION_RIGHT, "Button",
+ BS_AUTORADIOBUTTON,74,26,68,12
+ PUSHBUTTON "OK",IDOK,28,53,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,84,53,48,14,WS_GROUP | NOT WS_TABSTOP
+END
+
+IDD_POINT_LOAD DIALOGEX 18, 22, 153, 93
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Point Load"
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Load value:",IDC_STATIC,16,42,40,8
+ LTEXT "Load position:",IDC_STATIC,16,16,46,8
+ EDITTEXT IDC_POSITION,64,14,50,12
+ EDITTEXT IDC_VALUE,64,40,50,12
+ PUSHBUTTON "OK",IDOK,24,70,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,80,70,48,14,WS_GROUP | NOT WS_TABSTOP
+ LTEXT "[m]",IDC_STATIC,118,16,14,8
+ LTEXT "[KN]",IDC_STATIC,118,42,16,8
+END
+
+IDD_LINEAR_DISTRIBUTED_LOAD DIALOGEX 12, 22, 156, 92
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Linear Distributed Load"
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Load value:",IDC_STATIC,15,46,40,8
+ LTEXT "Load length:",IDC_STATIC,15,28,40,8
+ LTEXT "Load position:",IDC_STATIC,16,10,46,8
+ EDITTEXT IDC_POSITION,65,8,46,12
+ EDITTEXT IDC_LENGTH,65,26,46,12
+ EDITTEXT IDC_VALUE,65,44,46,12
+ LTEXT "[m]",IDC_STATIC,115,10,26,8
+ LTEXT "[m]",IDC_STATIC,115,28,26,8
+ LTEXT "[KN/m]",IDC_STATIC,116,46,24,8
+ PUSHBUTTON "OK",IDOK,26,69,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,82,69,48,14,WS_GROUP | NOT WS_TABSTOP
+END
+
+IDD_ABOUT DIALOGEX 15, 29, 182, 79
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Beamax"
+FONT 8, "Tahoma"
+BEGIN
+ LTEXT "Beamax 2.4",IDC_STATIC,15,8,82,8
+ PUSHBUTTON "OK",IDOK,124,59,50,14,NOT WS_TABSTOP
+END
+
+IDD_ROLLER_SUPPORT DIALOGEX 12, 29, 163, 76
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Roller Support"
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ LTEXT "Support position:",IDC_STATIC,12,18,56,8
+ EDITTEXT IDC_POSITION,69,16,62,12
+ PUSHBUTTON "OK",IDOK,28,53,48,14,WS_GROUP | NOT WS_TABSTOP
+ PUSHBUTTON "Cancel",IDCANCEL,84,53,48,14,WS_GROUP | NOT WS_TABSTOP
+ LTEXT "[m]",IDC_STATIC,135,18,12,8
+END
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ABOUT, DIALOG
+ BEGIN
+ RIGHTMARGIN, 181
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+STRINGTABLE
+BEGIN
+ IDR_MAIN_FRAME "Beamax"
+ IDR_DOCUMENT "\nBEAM\nBeamax.System\nBeamax-Files (*.bcb)\n.bcb\nBeamax.System\nBeamax.System"
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDS_APP_TITLE "Beamax"
+ AFX_IDS_IDLEMESSAGE "Ready"
+END
+
+STRINGTABLE
+BEGIN
+ ID_INDICATOR_EXT "EXT"
+ ID_INDICATOR_CAPS "CAP"
+ ID_INDICATOR_NUM "NUM"
+ ID_INDICATOR_SCRL "SCRL"
+ ID_INDICATOR_OVR "OVR"
+ ID_INDICATOR_REC "REC"
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDS_OPENFILE "Open"
+ AFX_IDS_SAVEFILE "Save As"
+ AFX_IDS_ALLFILTER "All Files (*.*)"
+ AFX_IDS_UNTITLED "Untitled"
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDP_INVALID_FILENAME "Invalid filename."
+ AFX_IDP_FAILED_TO_OPEN_DOC "Failed to open document."
+ AFX_IDP_FAILED_TO_SAVE_DOC "Failed to save document."
+ AFX_IDP_ASK_TO_SAVE "Save changes to the %1 document ""%2""?"
+ AFX_IDP_FAILED_TO_CREATE_DOC "Failed to create empty document."
+ AFX_IDP_FILE_TOO_LARGE "The file is too large to open."
+ AFX_IDP_FAILED_TO_LAUNCH_HELP "Failed to launch help."
+ AFX_IDP_INTERNAL_FAILURE "Internal application error."
+ AFX_IDP_COMMAND_FAILURE "Command failed."
+ AFX_IDP_FAILED_MEMORY_ALLOC "Insufficient memory to perform operation."
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDP_GET_NOT_SUPPORTED "Unable to read write-only property."
+ AFX_IDP_SET_NOT_SUPPORTED "Unable to write read-only property."
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDP_FAILED_INVALID_FORMAT "Unexpected file format."
+ AFX_IDP_FAILED_INVALID_PATH
+ "%1\nCannot find this file.\nPlease verify that the correct path and file name are given."
+ AFX_IDP_FAILED_DISK_FULL "Destination disk drive is full."
+ AFX_IDP_FAILED_ACCESS_READ
+ "Unable to read from %1, it is opened by someone else."
+ AFX_IDP_FAILED_ACCESS_WRITE
+ "Unable to write to %1, it is read-only or opened by someone else."
+ AFX_IDP_FAILED_IO_ERROR_READ
+ "An unexpected error occurred while reading %1."
+ AFX_IDP_FAILED_IO_ERROR_WRITE
+ "An unexpected error occurred while writing %1."
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDP_PARSE_INT "Please enter an integer."
+ AFX_IDP_PARSE_REAL "Please enter a number."
+ AFX_IDP_PARSE_INT_RANGE "Please enter an integer between %1 and %2."
+ AFX_IDP_PARSE_REAL_RANGE "Please enter a number between %1 and %2."
+ AFX_IDP_PARSE_STRING_SIZE "Please enter no more than %1 characters."
+ AFX_IDP_PARSE_RADIO_BUTTON "Please select a button."
+ AFX_IDP_PARSE_BYTE "Please enter an integer between 0 and 255."
+ AFX_IDP_PARSE_UINT "Please enter a positive integer."
+END
+
+#endif // English (U.S.) resources
+
diff --git a/Source/Beamax.sln b/Source/Beamax.sln
new file mode 100644
index 0000000..dd48689
--- /dev/null
+++ b/Source/Beamax.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26803.3009
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Beamax", ".\Beamax.vcxproj", "{52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Debug|x64.ActiveCfg = Debug|x64
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Debug|x64.Build.0 = Debug|x64
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Debug|x86.ActiveCfg = Debug|Win32
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Debug|x86.Build.0 = Debug|Win32
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Release|x64.ActiveCfg = Release|x64
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Release|x64.Build.0 = Release|x64
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Release|x86.ActiveCfg = Release|Win32
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {12567F0F-910B-47C4-9AAA-989046784C08}
+ EndGlobalSection
+EndGlobal
diff --git a/Source/Beamax.vcxproj b/Source/Beamax.vcxproj
new file mode 100644
index 0000000..bcc45ad
--- /dev/null
+++ b/Source/Beamax.vcxproj
@@ -0,0 +1,223 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {52646DDE-71DA-4A1D-B1F1-D1FE4EBBBBA7}
+ Beamax
+ MFCProj
+
+
+ $(SolutionDir)\..\Build\$(Platform)\$(Configuration)\
+ $(SolutionDir)\..\Build\Intermediate\$(Platform)\$(Configuration)\
+
+
+
+ Application
+ true
+ v142
+ Static
+
+
+ Application
+ false
+ v142
+ true
+ Static
+
+
+ Application
+ true
+ v142
+ Static
+
+
+ Application
+ false
+ v142
+ true
+ Static
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+
+
+ false
+ true
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ _DEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+ false
+
+
+
+
+ Use
+ Level3
+ Disabled
+ _WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+
+
+ false
+ true
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ _DEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+ false
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+
+
+ false
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ NDEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+ false
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ _WINDOWS;NDEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+
+
+ false
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ NDEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Dialog.cpp b/Source/Dialog.cpp
new file mode 100644
index 0000000..5f8ccf8
--- /dev/null
+++ b/Source/Dialog.cpp
@@ -0,0 +1,189 @@
+
+#include "stdafx.h"
+#include "Dialog.h"
+
+void CreateBeamDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_BEAM_LENGTH, _length);
+}
+
+void CreateBeamDialog::SetLength(double value)
+{
+ _length = value;
+}
+
+double CreateBeamDialog::GetLength()
+{
+ return _length;
+}
+
+void PropertiesDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_MODULUS_OF_ELASTICITY, _modulusOfElasticity);
+ DDX_Text(pDX, IDC_MOMENT_OF_INERTIA, _momentOfInertia);
+ DDX_Text(pDX, IDC_AXIAL_AREA, _axialArea);
+}
+
+void PropertiesDialog::SetModulusOfElasticity(double value)
+{
+ _modulusOfElasticity = value;
+}
+
+double PropertiesDialog::GetModulusOfElasticity()
+{
+ return _modulusOfElasticity;
+}
+
+void PropertiesDialog::SetMomentOfInertia(double value)
+{
+ _momentOfInertia = value;
+}
+
+double PropertiesDialog::GetMomentOfInertia()
+{
+ return _momentOfInertia;
+}
+
+void PropertiesDialog::SetAxialArea(double value)
+{
+ _axialArea = value;
+}
+
+double PropertiesDialog::GetAxialArea()
+{
+ return _axialArea;
+}
+
+BEGIN_MESSAGE_MAP(FixedSupportDialog, CDialog)
+ ON_COMMAND(IDC_POSITION_LEFT, OnPositionStart)
+ ON_COMMAND(IDC_POSITION_RIGHT, OnPositionEnd)
+END_MESSAGE_MAP()
+
+BOOL FixedSupportDialog::OnInitDialog()
+{
+ if (_position == TRUE)
+ ((CButton *)GetDlgItem(IDC_POSITION_LEFT))->SetCheck(1);
+ else
+ ((CButton *)GetDlgItem(IDC_POSITION_RIGHT))->SetCheck(1);
+
+ return TRUE;
+}
+
+void FixedSupportDialog::OnPositionStart()
+{
+ _position = TRUE;
+}
+
+void FixedSupportDialog::OnPositionEnd()
+{
+ _position = FALSE;
+}
+
+void FixedSupportDialog::SetPosition(BOOL value)
+{
+ _position = value;
+}
+
+BOOL FixedSupportDialog::GetPosition()
+{
+ return _position;
+}
+
+void HingedSupportDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_POSITION, _position);
+}
+
+void HingedSupportDialog::SetPosition(double value)
+{
+ _position = value;
+}
+
+double HingedSupportDialog::GetPosition()
+{
+ return _position;
+}
+
+void RollerSupportDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_POSITION, _position);
+}
+
+void RollerSupportDialog::SetPosition(double value)
+{
+ _position = value;
+}
+
+double RollerSupportDialog::GetPosition()
+{
+ return _position;
+}
+
+void PointLoadDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_POSITION, _position);
+ DDX_Text(pDX, IDC_VALUE, _value);
+}
+
+void PointLoadDialog::SetPosition(double value)
+{
+ _position = value;
+}
+
+double PointLoadDialog::GetPosition()
+{
+ return _position;
+}
+
+void PointLoadDialog::SetValue(double value)
+{
+ _value = value;
+}
+
+double PointLoadDialog::GetValue()
+{
+ return _value;
+}
+
+void LinearDistributedLoadDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_POSITION, _position);
+ DDX_Text(pDX, IDC_VALUE, _value);
+ DDX_Text(pDX, IDC_LENGTH, _length);
+}
+
+void LinearDistributedLoadDialog::SetPosition(double value)
+{
+ _position = value;
+}
+
+double LinearDistributedLoadDialog::GetPosition()
+{
+ return _position;
+}
+
+void LinearDistributedLoadDialog::SetValue(double value)
+{
+ _value = value;
+}
+
+double LinearDistributedLoadDialog::GetValue()
+{
+ return _value;
+}
+
+void LinearDistributedLoadDialog::SetLength(double value)
+{
+ _length = value;
+}
+
+double LinearDistributedLoadDialog::GetLength()
+{
+ return _length;
+}
diff --git a/Source/Dialog.h b/Source/Dialog.h
new file mode 100644
index 0000000..a52adc2
--- /dev/null
+++ b/Source/Dialog.h
@@ -0,0 +1,157 @@
+#ifndef __Dialog__
+#define __Dialog__
+
+#include "stdafx.h"
+#include "Resource.h"
+
+class CreateBeamDialog : public CDialog
+{
+ double _length = 0.0;
+
+public:
+ CreateBeamDialog() : CDialog(CreateBeamDialog::IDD) {}
+ void SetLength(double length);
+ double GetLength();
+
+ enum { IDD = IDD_CREATE_BEAM };
+
+protected:
+ void DoDataExchange(CDataExchange* pDX);
+};
+
+class PropertiesDialog : public CDialog
+{
+private:
+ double _modulusOfElasticity = 0.0;
+ double _momentOfInertia = 0.0;
+ double _axialArea = 0.0;
+
+public:
+ PropertiesDialog() : CDialog(PropertiesDialog::IDD) {}
+ void SetModulusOfElasticity(double value);
+ double GetModulusOfElasticity();
+ void SetMomentOfInertia(double value);
+ double GetMomentOfInertia();
+ void SetAxialArea(double value);
+ double GetAxialArea();
+
+ enum { IDD = IDD_PROPERTIES };
+
+protected:
+ void DoDataExchange(CDataExchange* pDX);
+};
+
+class FixedSupportDialog : public CDialog
+{
+ BOOL _position = FALSE;
+
+public:
+ FixedSupportDialog() : CDialog(FixedSupportDialog::IDD) {}
+ void SetPosition(BOOL value);
+ BOOL GetPosition();
+ void OnPositionStart();
+ void OnPositionEnd();
+
+ enum { IDD = IDD_FIXED_SUPPORT };
+
+protected:
+ virtual BOOL OnInitDialog();
+
+ DECLARE_MESSAGE_MAP()
+};
+
+class HingedSupportDialog : public CDialog
+{
+ double _position;
+
+public:
+ HingedSupportDialog() : CDialog(HingedSupportDialog::IDD)
+ {
+ _position = 0.0;
+ }
+ void SetPosition(double value);
+ double GetPosition();
+
+ enum { IDD = IDD_HINGED_SUPPORT };
+
+protected:
+ void DoDataExchange(CDataExchange* pDX);
+};
+
+class RollerSupportDialog : public CDialog
+{
+ double _position;
+
+public:
+ RollerSupportDialog() : CDialog(RollerSupportDialog::IDD)
+ {
+ _position = 0.0;
+ }
+ void SetPosition(double value);
+ double GetPosition();
+
+ enum { IDD = IDD_ROLLER_SUPPORT };
+
+protected:
+ void DoDataExchange(CDataExchange* pDX);
+};
+
+class PointLoadDialog : public CDialog
+{
+ double _position;
+ double _value;
+
+public:
+ PointLoadDialog() : CDialog(PointLoadDialog::IDD)
+ {
+ _position = 0.0;
+ _value = 0.0;
+ }
+ void SetPosition(double value);
+ double GetPosition();
+ void SetValue(double value);
+ double GetValue();
+
+ enum { IDD = IDD_POINT_LOAD };
+
+protected:
+ void DoDataExchange(CDataExchange * DX);
+};
+
+class LinearDistributedLoadDialog : public CDialog
+{
+ double _position;
+ double _value;
+ double _length;
+
+public:
+ LinearDistributedLoadDialog() : CDialog(LinearDistributedLoadDialog::IDD)
+ {
+ _position = 0.0;
+ _value = 0.0;
+ _length = 0.0;
+ }
+ void SetPosition(double value);
+ double GetPosition();
+ void SetValue(double value);
+ double GetValue();
+ void SetLength(double value);
+ double GetLength();
+
+ enum { IDD = IDD_LINEAR_DISTRIBUTED_LOAD };
+
+protected:
+ void DoDataExchange(CDataExchange* pDX);
+};
+
+class AboutDialog : public CDialog
+{
+public:
+ AboutDialog() : CDialog(AboutDialog::IDD)
+ {
+ }
+
+ enum { IDD = IDD_ABOUT };
+};
+
+#endif
diff --git a/Source/Document.cpp b/Source/Document.cpp
new file mode 100644
index 0000000..442ca9f
--- /dev/null
+++ b/Source/Document.cpp
@@ -0,0 +1,442 @@
+#include
+#include
+#include "stdafx.h"
+#include "Application.h"
+#include "Dialog.h"
+#include "Object.h"
+#include "Document.h"
+
+IMPLEMENT_DYNCREATE(Document, CDocument)
+
+BEGIN_MESSAGE_MAP(Document, CDocument)
+ ON_COMMAND(IDM_PROPERTIES, OnProperties)
+END_MESSAGE_MAP()
+
+Document::Document()
+{
+ EnableAutomation();
+ AfxOleLockApp();
+
+ // default values
+ _beamLength = ((Application*)AfxGetApp())->_beamLength;
+ _modulusOfElasticity = 210000 * 1000;
+ _momentOfInertia = 0.0000836;
+ _axialArea = 0.00538;
+
+ // no object is selected
+ _selected = NULL;
+}
+
+Document::~Document()
+{
+ CoFreeUnusedLibraries();
+ AfxOleUnlockApp();
+}
+
+BOOL Document::OnNewDocument()
+{
+ if (!CDocument::OnNewDocument())
+ {
+ return FALSE;
+ }
+
+ ((Application*)AfxGetApp())->_beamLength = 10;
+
+ if (((Application*)AfxGetApp())->_beamCreate)
+ {
+ ((Application*)AfxGetApp())->_beamCreate = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ ((Application*)AfxGetApp())->_beamCreate = TRUE;
+ return FALSE;
+ }
+}
+
+void Document::Serialize(CArchive& archive)
+{
+ if (archive.IsLoading())
+ {
+ archive >> _beamLength;
+ archive >> _modulusOfElasticity >> _momentOfInertia;
+ _objectList.Serialize(archive);
+ }
+ else
+ {
+ archive << _beamLength;
+ archive << _modulusOfElasticity << _momentOfInertia;
+ _objectList.Serialize(archive);
+ }
+}
+
+BOOL Document::InsertObject(ObjectCast* item)
+{
+ if (item == NULL)
+ return FALSE;
+
+ if (CLASSOF(item, "HingedSupport") || CLASSOF(item, "FixedSupport") || CLASSOF(item, "RollerSupport"))
+ {
+ ObjectCast* object;
+ POSITION position = _objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (ObjectCast*)_objectList.GetNext(position);
+ if (object != NULL)
+ {
+ if (CLASSOF(item, "HingedSupport") || CLASSOF(item, "FixedSupport") || CLASSOF(item, "RollerSupport"))
+ {
+ if (fabs(((SupportCast *)object)->GetPosition() - ((SupportCast *)item)->GetPosition()) < EPSILON)
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ if (_objectList.IsEmpty())
+ {
+ _objectList.AddHead(item);
+ }
+ else
+ {
+ _objectList.AddTail(item);
+ }
+
+ return TRUE;
+}
+
+void Document::DeleteObject(ObjectCast* item)
+{
+ POSITION position = _objectList.GetHeadPosition();
+ position = _objectList.Find(item);
+ if (position != NULL)
+ {
+ _objectList.RemoveAt(position);
+ }
+}
+
+int Document::SortLoadLevels(CDC* pDC, double scaleX)
+{
+ int maximumLevel = 1;
+ LoadCast* currentObject = NULL;
+
+ // set the level of all object to zero
+ ObjectCast* object = NULL;
+ POSITION position = _objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (ObjectCast*)_objectList.GetNext(position);
+ if ((object != NULL) && (CLASSOF(object, "PointLoad") || CLASSOF(object, "LinearDistributedLoad")))
+ {
+ ((LoadCast*)object)->SetLevel(0);
+ }
+ }
+
+ // sort all load objects
+ do
+ {
+ currentObject = NULL;
+ double currentStart = 0;
+ double currentLength = 0;
+
+ // scan for the biggest load object at level 0
+ ObjectCast* object;
+ POSITION position = _objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (ObjectCast*)_objectList.GetNext(position);
+ if ((object != NULL) && (CLASSOF(object, "PointLoad") || CLASSOF(object, "LinearDistributedLoad")))
+ {
+ double start;
+ double length;
+ ((LoadCast*)object)->GetExtent(pDC, start, length, scaleX);
+ if ((((LoadCast*)object)->GetLevel() == 0) && (length > currentLength))
+ {
+ currentObject = (LoadCast*)object;
+ currentStart = start;
+ currentLength = length;
+ }
+ }
+ }
+
+ // exit if no object found
+ if (currentObject == NULL)
+ {
+ return maximumLevel;
+ }
+
+ // increase the level of the object until it fits
+ int currentLevel = 0;
+ BOOL match = FALSE;
+ do
+ {
+ match = FALSE;
+ currentLevel++;
+ currentObject->SetLevel(currentLevel);
+ ObjectCast* object;
+ POSITION position = _objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (ObjectCast*)_objectList.GetNext(position);
+ if ((object != NULL) && (object != currentObject) && (CLASSOF(object, "PointLoad") || CLASSOF(object, "LinearDistributedLoad")))
+ {
+ int level;
+ double start;
+ double length;
+ level = ((LoadCast*)object)->GetLevel();
+ ((LoadCast*)object)->GetExtent(pDC, start, length, scaleX);
+ if (level == currentLevel)
+ {
+ if (((currentStart >= start) &&
+ (currentStart <= (start + length))) ||
+ (((currentStart + currentLength) >= start) &&
+ ((currentStart + currentLength) <= (start + length))))
+ {
+ match = TRUE;
+ }
+ }
+ }
+ }
+ } while (match);
+
+ // update maximum level
+ if (maximumLevel < currentLevel) maximumLevel = currentLevel;
+ } while (currentObject != NULL);
+
+ return maximumLevel;
+}
+
+BOOL Document::Analyse()
+{
+ Beam* analysis = new Beam();
+
+ // create beam
+ analysis->SetLength(_beamLength);
+ analysis->SetEI(_modulusOfElasticity, _momentOfInertia);
+
+ // transfer objects
+ ObjectCast* object;
+ POSITION position = _objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (ObjectCast*)_objectList.GetNext(position);
+ if (object != NULL)
+ {
+ if (CLASSOF(object, "FixedSupport"))
+ analysis->CreateFixedSupport(((SupportCast *)object)->GetPosition());
+ if (CLASSOF(object, "HingedSupport"))
+ analysis->CreateHingedSupport(((SupportCast *)object)->GetPosition());
+ if (CLASSOF(object, "RollerSupport"))
+ analysis->CreateRollerSupport(((SupportCast *)object)->GetPosition());
+ if (CLASSOF(object, "PointLoad"))
+ analysis->CreatePointLoad(((LoadCast*)object)->GetPosition(), ((LoadCast*)object)->GetValue());
+ if (CLASSOF(object, "LinearDistributedLoad"))
+ analysis->CreateLinearDistributedLoad(((LoadCast*)object)->GetPosition(), ((LoadCast*)object)->GetValue(), ((LoadCast*)object)->GetLength());
+ }
+ }
+
+ // start analysis
+ analysis->Analyse();
+
+ // delete old results
+ _shearForceList.RemoveAll();
+ _bendingMomentList.RemoveAll();
+ _displacementList.RemoveAll();
+
+ // retrieve results
+ Section* shearForce;
+ Section* bendingMoment;
+ Section* displacement;
+ HRESULT result = 0;
+ do
+ {
+ shearForce = new Section;
+ bendingMoment = new Section;
+ displacement = new Section;
+ result = analysis->GetNextSection(shearForce, bendingMoment, displacement);
+ _shearForceList.AddHead((CObject *)shearForce);
+ _bendingMomentList.AddHead((CObject *)bendingMoment);
+ _displacementList.AddHead((CObject *)displacement);
+ } while (result == S_OK);
+
+ delete analysis;
+
+ return TRUE;
+}
+
+void Document::OnProperties()
+{
+ PropertiesDialog dialog;
+
+ dialog.SetModulusOfElasticity(_modulusOfElasticity / 1000);
+ dialog.SetMomentOfInertia(_momentOfInertia * (100 * 100 * 100 * 100));
+ dialog.SetAxialArea(_axialArea * (100 * 100));
+
+ if (dialog.DoModal() == IDOK)
+ {
+ _modulusOfElasticity = dialog.GetModulusOfElasticity() * 1000;
+ _momentOfInertia = dialog.GetMomentOfInertia() / (100 * 100 * 100 * 100);
+ _axialArea = dialog.GetAxialArea() / (100 * 100);
+ }
+
+ UpdateAllViews(NULL);
+}
+
+BOOL Document::CreateBeam(double length, double modulusOfElasticity, double momentOfInertia, double axialArea)
+{
+ _beamLength = length;
+ _modulusOfElasticity = modulusOfElasticity;
+ _momentOfInertia = momentOfInertia;
+ _axialArea = axialArea;
+ return TRUE;
+}
+
+BOOL Document::CreateFixedSupport(double position)
+{
+ SupportCast * SupportObject = NULL;
+ if ((position != 0) && (position != _beamLength)) return FALSE;
+ SupportObject = new FixedSupport;
+ if (SupportObject == NULL) return FALSE;
+ SupportObject->SetPosition(position);
+ if (!InsertObject(SupportObject))
+ {
+ delete SupportObject;
+ return FALSE;
+ }
+ _selected = SupportObject;
+ return TRUE;
+}
+
+BOOL Document::CreateHingedSupport(double position)
+{
+ SupportCast * SupportObject = NULL;
+ if ((position < 0) || (position > _beamLength)) return FALSE;
+ SupportObject = new HingedSupport;
+ if (SupportObject == NULL) return FALSE;
+ SupportObject->SetPosition(position);
+ if (!InsertObject(SupportObject))
+ {
+ delete SupportObject;
+ return FALSE;
+ }
+ _selected = SupportObject;
+ return TRUE;
+}
+
+BOOL Document::CreateRollerSupport(double position)
+{
+ SupportCast * SupportObject = NULL;
+ if ((position < 0) || (position > _beamLength)) return FALSE;
+ SupportObject = new RollerSupport;
+ if (SupportObject == NULL) return FALSE;
+ SupportObject->SetPosition(position);
+ if (!InsertObject(SupportObject))
+ {
+ delete SupportObject;
+ return FALSE;
+ }
+ _selected = SupportObject;
+ return TRUE;
+}
+
+BOOL Document::CreatePointLoad(double position, double value)
+{
+ LoadCast* loadObject = NULL;
+ if ((position < 0) || (position > _beamLength)) return FALSE;
+ loadObject = new PointLoad;
+ if (loadObject == NULL) return FALSE;
+ loadObject->SetValue(value);
+ loadObject->SetPosition(position);
+ if (!InsertObject(loadObject))
+ {
+ delete loadObject;
+ return FALSE;
+ }
+ _selected = loadObject;
+ return TRUE;
+}
+
+BOOL Document::CreateLinearDistributedLoad(double position, double value,
+ double length)
+{
+ LoadCast* loadObject = NULL;
+ if ((length < 0) || (position < 0) || ((position + length) > _beamLength))
+ {
+ return FALSE;
+ }
+ loadObject = new LinearDistributedLoad;
+ if (loadObject == NULL)
+ {
+ return FALSE;
+ }
+ loadObject->SetValue(value);
+ loadObject->SetPosition(position);
+ loadObject->SetLength(length);
+ if (!InsertObject(loadObject))
+ {
+ delete loadObject;
+ return FALSE;
+ }
+ _selected = loadObject;
+ return TRUE;
+}
+
+double Document::GetShearForce(double position)
+{
+ Section* object;
+ POSITION pointer = _shearForceList.GetHeadPosition();
+ while (pointer != NULL)
+ {
+ object = (Section*)_shearForceList.GetNext(pointer);
+ if (object != NULL)
+ {
+ if ((position >= object->Start) && (position <= (object->Start + object->Length)))
+ {
+ double x = position - object->Start;
+ return (object->A4 * x * x * x * x + object->A3 * x * x * x + object->A2 * x * x + object->A1 * x + object->A0);
+ }
+ }
+ }
+ return 0;
+}
+
+double Document::GetBendingMoment(double position)
+{
+ Section* object;
+ POSITION pointer = _bendingMomentList.GetHeadPosition();
+ while (pointer != NULL)
+ {
+ object = (Section*)_bendingMomentList.GetNext(pointer);
+ if (object != NULL)
+ {
+ if ((position >= object->Start) && (position <= (object->Start + object->Length)))
+ {
+ double x = position - object->Start;
+ return (object->A4 * x * x * x * x + object->A3 * x * x * x + object->A2 * x * x + object->A1 * x + object->A0);
+ }
+ }
+ }
+ return 0;
+}
+
+double Document::GetDisplacement(double position)
+{
+ Section* object;
+ POSITION pointer = _displacementList.GetHeadPosition();
+ while (pointer != NULL)
+ {
+ object = (Section*)_displacementList.GetNext(pointer);
+ if (object != NULL)
+ {
+ if ((position >= object->Start) &&
+ (position <= (object->Start + object->Length)))
+ {
+ double x = position - object->Start;
+ return (object->A4 * x * x * x * x + object->A3 * x * x * x + object->A2 * x * x + object->A1 * x + object->A0);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/Source/Document.h b/Source/Document.h
new file mode 100644
index 0000000..286e6bd
--- /dev/null
+++ b/Source/Document.h
@@ -0,0 +1,47 @@
+#ifndef __Document__
+#define __Document__
+
+class Document : public CDocument
+{
+private:
+ double _modulusOfElasticity;
+ double _momentOfInertia;
+ double _axialArea;
+
+public:
+ double _beamLength;
+ CObList _objectList;
+ CObList _shearForceList;
+ CObList _bendingMomentList;
+ CObList _displacementList;
+ CObject* _selected;
+
+public:
+ virtual void Serialize(CArchive& Archive);
+ virtual BOOL OnNewDocument();
+ BOOL InsertObject(ObjectCast* item);
+ void DeleteObject(ObjectCast* item);
+ int SortLoadLevels(CDC* pDC, double scaleX);
+ BOOL Analyse();
+
+ // automation interface
+ BOOL CreateBeam(double length, double modulusOfElasticity, double momentOfInertia, double axialArea);
+ BOOL CreateFixedSupport(double position);
+ BOOL CreateHingedSupport(double position);
+ BOOL CreateRollerSupport(double position);
+ BOOL CreatePointLoad(double position, double value);
+ BOOL CreateLinearDistributedLoad(double position, double value, double length);
+ double GetShearForce(double position);
+ double GetBendingMoment(double position);
+ double GetDisplacement(double position);
+
+protected:
+ Document();
+ ~Document();
+ afx_msg void OnProperties();
+
+ DECLARE_MESSAGE_MAP()
+ DECLARE_DYNCREATE(Document)
+};
+
+#endif
diff --git a/Source/Document.ico b/Source/Document.ico
new file mode 100644
index 0000000..35d685b
Binary files /dev/null and b/Source/Document.ico differ
diff --git a/Source/Object.cpp b/Source/Object.cpp
new file mode 100644
index 0000000..9cdf5da
--- /dev/null
+++ b/Source/Object.cpp
@@ -0,0 +1,308 @@
+#include "stdafx.h"
+#include "Object.h"
+#include
+
+IMPLEMENT_SERIAL(ObjectCast, CObject, 1);
+
+void ObjectCast::Serialize(CArchive& archive)
+{
+}
+
+void ObjectCast::Draw(CDC* pDC, int x, int y, double Scale)
+{
+}
+
+CRectTracker & ObjectCast::GetBoundRect()
+{
+ return _boundRect;
+}
+
+void ObjectCast::SetType(int type)
+{
+ _type = type;
+}
+
+int ObjectCast::GetType()
+{
+ return _type;
+}
+
+IMPLEMENT_SERIAL(SupportCast, ObjectCast, 2);
+
+void SupportCast::Serialize(CArchive& archive)
+{
+}
+
+void SupportCast::SetPosition(double value)
+{
+ _position = value;
+}
+
+double SupportCast::GetPosition()
+{
+ return _position;
+}
+
+IMPLEMENT_SERIAL(FixedSupport, SupportCast, 3);
+
+void FixedSupport::Serialize(CArchive& archive)
+{
+ if (archive.IsLoading())
+ archive >> _position;
+ else
+ archive << _position;
+}
+
+void FixedSupport::Draw(CDC* pDC, int x, int y, double Scale)
+{
+ x = x + ((int)(_position * Scale));
+
+ pDC->MoveTo(x, y - 8);
+ pDC->LineTo(x, y + 8);
+
+ if (fabs(_position) < EPSILON)
+ {
+ pDC->MoveTo(x - 4, y - 4);
+ pDC->LineTo(x, y - 8);
+ pDC->MoveTo(x - 4, y);
+ pDC->LineTo(x, y - 4);
+ pDC->MoveTo(x - 4, y + 4);
+ pDC->LineTo(x, y);
+ pDC->MoveTo(x - 4, y + 8);
+ pDC->LineTo(x, y + 4);
+
+ _boundRect = CRectTracker(CRect(x - 8, y - 13, x + 4, y + 13), CRectTracker::dottedLine);
+ }
+ else
+ {
+ pDC->MoveTo(x + 4, y - 4);
+ pDC->LineTo(x, y - 8);
+ pDC->MoveTo(x + 4, y);
+ pDC->LineTo(x, y - 4);
+ pDC->MoveTo(x + 4, y + 4);
+ pDC->LineTo(x, y);
+ pDC->MoveTo(x + 4, y + 8);
+ pDC->LineTo(x, y + 4);
+
+ _boundRect = CRectTracker(CRect(x - 4, y - 13, x + 8, y + 13), CRectTracker::dottedLine);
+ }
+}
+
+IMPLEMENT_SERIAL(HingedSupport, SupportCast, 3);
+
+void HingedSupport::Serialize(CArchive& archive)
+{
+ if (archive.IsLoading())
+ archive >> _position;
+ else
+ archive << _position;
+}
+
+void HingedSupport::Draw(CDC* pDC, int x, int y, double Scale)
+{
+ x = x + ((int)(_position * Scale));
+
+ pDC->MoveTo(x, y);
+ pDC->LineTo(x + 8, y + 8);
+ pDC->LineTo(x - 8, y + 8);
+ pDC->LineTo(x, y);
+
+ _boundRect = CRectTracker(CRect(x - 12, y - 4, x + 12, y + 12), CRectTracker::dottedLine);
+}
+
+IMPLEMENT_SERIAL(RollerSupport, SupportCast, 3);
+
+void RollerSupport::Serialize(CArchive& archive)
+{
+ if (archive.IsLoading())
+ archive >> _position;
+ else
+ archive << _position;
+}
+
+void RollerSupport::Draw(CDC* pDC, int x, int y, double Scale)
+{
+ x = x + ((int)(_position * Scale));
+
+ pDC->MoveTo(x, y);
+ pDC->LineTo(x + 8, y + 8);
+ pDC->LineTo(x - 8, y + 8);
+ pDC->LineTo(x, y);
+ pDC->MoveTo(x + 8, y + 10);
+ pDC->LineTo(x - 8, y + 10);
+
+ _boundRect = CRectTracker(CRect(x - 12, y - 4, x + 12, y + 14),
+ CRectTracker::dottedLine);
+}
+
+IMPLEMENT_SERIAL(LoadCast, ObjectCast, 2);
+
+void LoadCast::Serialize(CArchive& archive)
+{
+}
+
+void LoadCast::GetExtent(CDC* pDC, double & Start,
+ double & Length, double Scale)
+{
+}
+
+void LoadCast::SetPosition(double position)
+{
+ _position = position;
+}
+
+double LoadCast::GetPosition()
+{
+ return _position;
+}
+
+void LoadCast::SetValue(double value)
+{
+ _value = value;
+}
+
+double LoadCast::GetValue()
+{
+ return _value;
+}
+
+void LoadCast::SetLength(double length)
+{
+ _length = length;
+}
+
+double LoadCast::GetLength()
+{
+ return _length;
+}
+
+void LoadCast::SetLevel(int level)
+{
+ _level = level;
+}
+
+int LoadCast::GetLevel()
+{
+ return _level;
+}
+
+IMPLEMENT_SERIAL(PointLoad, LoadCast, 3);
+
+PointLoad::PointLoad()
+{
+ _level = 0;
+}
+
+void PointLoad::Serialize(CArchive& archive)
+{
+ if (archive.IsLoading())
+ archive >> _position >> _value;
+ else
+ archive << _position << _value;
+}
+
+void PointLoad::Draw(CDC* pDC, int x, int y, double Scale)
+{
+ char buffer[36];
+
+ x = x + ((int)(_position * Scale));
+ y = y - ((_level - 1) * 30);
+
+ pDC->MoveTo(x, y - 30);
+ pDC->LineTo(x, y - 1);
+ pDC->MoveTo(x - 4, y - 9);
+ pDC->LineTo(x, y - 3);
+ pDC->MoveTo(x + 4, y - 9);
+ pDC->LineTo(x, y - 3);
+
+ sprintf_s(buffer, "%.2f", _value);
+ pDC->SetTextAlign(TA_LEFT | TA_TOP);
+ pDC->TextOut(x + 3, y - 30, buffer);
+
+ CSize textSize(pDC->GetTextExtent(buffer, (int)strlen(buffer)));
+
+ _boundRect = CRectTracker(CRect(x - 9, y - 34, x + textSize.cx + 7, y + 4), CRectTracker::dottedLine);
+}
+
+void PointLoad::GetExtent(CDC* pDC, double& Start, double& Length, double Scale)
+{
+ Start = (int)(_position * Scale) - 9;
+ char buffer[36];
+ sprintf_s(buffer, "%.2f", _value);
+ CSize textSize(pDC->GetTextExtent(buffer, (int)strlen(buffer)));
+ Length = textSize.cx + 7;
+}
+
+IMPLEMENT_SERIAL(LinearDistributedLoad, LoadCast, 3);
+
+LinearDistributedLoad::LinearDistributedLoad()
+{
+ _level = 0;
+}
+
+void LinearDistributedLoad::Serialize(CArchive& archive)
+{
+ if (archive.IsLoading())
+ archive >> _position >> _length >> _value;
+ else
+ archive << _position << _length << _value;
+}
+
+void LinearDistributedLoad::Draw(CDC* pDC, int x, int y, double Scale)
+{
+ char buffer[36];
+
+ x = x + (int)(_position * Scale);
+ y = y - ((_level - 1) * 30);
+
+ int length = (int)(_length * Scale);
+
+ pDC->MoveTo(x, y - 30);
+ pDC->LineTo(x + length, y - 30);
+
+ pDC->MoveTo(x, y - 30);
+ pDC->LineTo(x, y - 1);
+ pDC->MoveTo(x - 4, y - 9);
+ pDC->LineTo(x, y - 3);
+ pDC->MoveTo(x + 4, y - 9);
+ pDC->LineTo(x, y - 3);
+
+ pDC->MoveTo(x + length, y - 30);
+ pDC->LineTo(x + length, y - 1);
+ pDC->MoveTo(x + length - 4, y - 9);
+ pDC->LineTo(x + length, y - 3);
+ pDC->MoveTo(x + length + 4, y - 9);
+ pDC->LineTo(x + length, y - 3);
+
+ double DX = (_length / (((double)length / 9) + 1));
+ double XC = 0;
+ XC += DX;
+
+ while ((XC * Scale) < (length - 1))
+ {
+ pDC->MoveTo(x + ((int)(XC * Scale)), y - 27);
+ pDC->LineTo(x + ((int)(XC * Scale)), y - 4);
+ XC += DX;
+ }
+
+ sprintf_s(buffer, "%.2f", _value);
+ pDC->SetTextAlign(TA_LEFT || TA_TOP);
+ pDC->TextOut(x + length + 2, y - 30, buffer);
+
+ CSize textSize(pDC->GetTextExtent(buffer, (int)strlen(buffer)));
+
+ _boundRect = CRectTracker(CRect(x - 9, y - 34,
+ x + length + textSize.cx + 7, y + 4),
+ CRectTracker::dottedLine);
+}
+
+void LinearDistributedLoad::GetExtent(CDC* pDC, double& Start,
+ double & Length, double Scale)
+{
+ Start = (int)(_position * Scale) - 9;
+ char buffer[36];
+ sprintf_s(buffer, "%.2f", _value);
+ CSize textSize(pDC->GetTextExtent(buffer, (int)strlen(buffer)));
+ Length = (int)(_length * Scale) + textSize.cx + 7;
+}
+
diff --git a/Source/Object.h b/Source/Object.h
new file mode 100644
index 0000000..a2595a5
--- /dev/null
+++ b/Source/Object.h
@@ -0,0 +1,107 @@
+#ifndef __Object__
+#define __Object__
+
+#include "stdafx.h"
+
+class ObjectCast : public CObject
+{
+protected:
+ int _type = 0;
+ CRectTracker _boundRect;
+
+public:
+ virtual void Serialize(CArchive& archive);
+ virtual void Draw(CDC* pDC, int x, int y, double Scale);
+ virtual CRectTracker& GetBoundRect();
+ void SetType(int type);
+ int GetType();
+
+ DECLARE_SERIAL(ObjectCast)
+};
+
+class SupportCast : public ObjectCast
+{
+protected:
+ double _position = 0.0;
+
+public:
+ virtual void Serialize(CArchive& archive);
+ void SetPosition(double value);
+ double GetPosition();
+
+ DECLARE_SERIAL(SupportCast)
+};
+
+class FixedSupport : public SupportCast
+{
+public:
+ virtual void Serialize(CArchive& archive);
+ virtual void Draw(CDC* pDC, int x, int y, double Scale);
+
+ DECLARE_SERIAL(FixedSupport)
+};
+
+class HingedSupport : public SupportCast
+{
+public:
+ virtual void Serialize(CArchive& archive);
+ virtual void Draw(CDC* pDC, int x, int y, double Scale);
+
+ DECLARE_SERIAL(HingedSupport)
+};
+
+class RollerSupport : public SupportCast
+{
+public:
+ virtual void Serialize(CArchive& archive);
+ virtual void Draw(CDC* pDC, int x, int y, double Scale);
+
+ DECLARE_SERIAL(RollerSupport)
+};
+
+class LoadCast : public ObjectCast
+{
+protected:
+ int _level;
+ double _position;
+ double _value;
+ double _length;
+
+public:
+ virtual void Serialize(CArchive& archive);
+ virtual void GetExtent(CDC* pDC, double& Start, double& Length, double Scale);
+ void SetPosition(double value);
+ double GetPosition();
+ void SetValue(double value);
+ double GetValue();
+ void SetLength(double value);
+ double GetLength();
+ void SetLevel(int value);
+ int GetLevel();
+
+ DECLARE_SERIAL(LoadCast)
+};
+
+class PointLoad : public LoadCast
+{
+public:
+ PointLoad();
+ virtual void Serialize(CArchive& archive);
+ virtual void Draw(CDC* pDC, int x, int y, double Scale);
+ virtual void GetExtent(CDC* pDC, double& Start, double& Length, double Scale);
+
+ DECLARE_SERIAL(PointLoad)
+};
+
+class LinearDistributedLoad : public LoadCast
+{
+public:
+ LinearDistributedLoad();
+ virtual void Serialize(CArchive& archive);
+ virtual void Draw(CDC* pDC, int x, int y, double Scale);
+ virtual void GetExtent(CDC* pDC, double& Start, double& Length, double Scale);
+
+ DECLARE_SERIAL(LinearDistributedLoad)
+};
+
+#endif
diff --git a/Source/Resource.h b/Source/Resource.h
new file mode 100644
index 0000000..a2d0396
--- /dev/null
+++ b/Source/Resource.h
@@ -0,0 +1,54 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Application.rc
+//
+#define IDR_MAIN_FRAME 2
+#define IDR_DOCUMENT 3
+#define IDB_SPLASH 101
+#define IDD_PROPERTIES 102
+#define ID_Menu 103
+#define IDD_ABOUT 230
+#define IDD_CREATE_BEAM 240
+#define IDD_HINGED_SUPPORT 260
+#define IDD_FIXED_SUPPORT 270
+#define IDD_POINT_LOAD 280
+#define IDD_LINEAR_DISTRIBUTED_LOAD 290
+#define IDD_ROLLER_SUPPORT 291
+#define IDC_BEAM_LENGTH 1000
+#define IDC_POSITION_LEFT 1001
+#define IDC_POSITION_RIGHT 1002
+#define IDC_POSITION 1003
+#define IDC_LENGTH 1005
+#define IDC_MODULUS_OF_ELASTICITY 1008
+#define IDC_MOMENT_OF_INERTIA 1009
+#define IDC_VALUE 1009
+#define IDC_AXIAL_AREA 1010
+#define IDM_ABOUT 40001
+#define IDM_VIEW_CONTINUOUS_BEAM 40002
+#define IDM_VIEW_SHEAR_FORCE 40003
+#define IDM_VIEW_BENDING_MOMENT 40004
+#define IDM_VIEW_DISPLACEMENT 40005
+#define IDM_VIEW_NUMERICAL_VALUES 40006
+#define IDM_PROPERTIES 40007
+#define IDM_DELETE 40008
+#define IDM_HINGED_SUPPORT 40009
+#define IDM_FIXED_SUPPORT 40010
+#define IDM_POINT_LOAD 40011
+#define IDM_LINEAR_DISTRIBUTED_LOAD 40012
+#define IDM_ROLLER_SUPPORT 40015
+#define ID_FILE_PREVIEW 40016
+#define IDM_HELP_INDEX 40019
+#define ID_40021 40021
+#define ID_PRINT 40021
+#define ID_40023 40023
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40025
+#define _APS_NEXT_CONTROL_VALUE 1011
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Source/ToolBar.bmp b/Source/ToolBar.bmp
new file mode 100644
index 0000000..ff86214
Binary files /dev/null and b/Source/ToolBar.bmp differ
diff --git a/Source/View.cpp b/Source/View.cpp
new file mode 100644
index 0000000..94f7b1a
--- /dev/null
+++ b/Source/View.cpp
@@ -0,0 +1,965 @@
+
+#include
+#include "stdafx.h"
+#include "Dialog.h"
+#include "Object.h"
+#include "Document.h"
+#include "View.h"
+
+IMPLEMENT_DYNCREATE(View, CScrollView)
+
+BEGIN_MESSAGE_MAP(View, CScrollView)
+ ON_WM_LBUTTONDOWN()
+ ON_WM_RBUTTONDOWN()
+ ON_WM_LBUTTONDBLCLK()
+ ON_WM_ERASEBKGND()
+ ON_COMMAND(IDM_DELETE, OnDelete)
+ ON_UPDATE_COMMAND_UI(IDM_DELETE, OnUpdateDelete)
+ ON_COMMAND(IDM_FIXED_SUPPORT, OnCreateFixedSupport)
+ ON_COMMAND(IDM_HINGED_SUPPORT, OnCreateHingedSupport)
+ ON_COMMAND(IDM_ROLLER_SUPPORT, OnCreateRollerSupport)
+ ON_COMMAND(IDM_POINT_LOAD, OnCreatePointLoad)
+ ON_COMMAND(IDM_LINEAR_DISTRIBUTED_LOAD, OnCreateLinearDistributedLoad)
+ ON_COMMAND(IDM_VIEW_CONTINUOUS_BEAM, OnViewContinuousBeam)
+ ON_UPDATE_COMMAND_UI(IDM_VIEW_CONTINUOUS_BEAM, OnUpdateViewContinuousBeam)
+ ON_COMMAND(IDM_VIEW_SHEAR_FORCE, OnViewShearForce)
+ ON_UPDATE_COMMAND_UI(IDM_VIEW_SHEAR_FORCE, OnUpdateViewShearForce)
+ ON_COMMAND(IDM_VIEW_BENDING_MOMENT, OnViewBendingMoment)
+ ON_UPDATE_COMMAND_UI(IDM_VIEW_BENDING_MOMENT, OnUpdateViewBendingMoment)
+ ON_COMMAND(IDM_VIEW_DISPLACEMENT, OnViewDisplacement)
+ ON_UPDATE_COMMAND_UI(IDM_VIEW_DISPLACEMENT, OnUpdateViewDisplacement)
+ ON_COMMAND(IDM_VIEW_NUMERICAL_VALUES, OnViewNumericalValues)
+ ON_UPDATE_COMMAND_UI(IDM_VIEW_NUMERICAL_VALUES, OnUpdateViewNumericalValues)
+ ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
+END_MESSAGE_MAP()
+
+View::View()
+{
+ // create popup menu
+ _popupMenu = new CMenu;
+ _popupMenu->CreatePopupMenu();
+ _popupMenu->AppendMenu(MF_STRING, IDM_FIXED_SUPPORT, "&Fixed Support\tAlt+X");
+ _popupMenu->AppendMenu(MF_STRING, IDM_HINGED_SUPPORT, "&Hinged Support\tAlt+N");
+ _popupMenu->AppendMenu(MF_STRING, IDM_ROLLER_SUPPORT, "&Roller Support\tAlt+R");
+ _popupMenu->AppendMenu(MF_SEPARATOR);
+ _popupMenu->AppendMenu(MF_STRING, IDM_POINT_LOAD, "&Point Load\tAlt+P");
+ _popupMenu->AppendMenu(MF_STRING, IDM_LINEAR_DISTRIBUTED_LOAD, "&Distributed Load\tAlt+L");
+ _popupMenu->AppendMenu(MF_SEPARATOR);
+ _popupMenu->AppendMenu(MF_STRING, IDM_DELETE, "&Delete\tDel");
+
+ // default view settings
+ _viewContinuousBeam = TRUE;
+ _viewShearForce = FALSE;
+ _viewBendingMoment = TRUE;
+ _viewDisplacement = FALSE;
+ _viewNumericalValues = FALSE;
+}
+
+View::~View()
+{
+ // delete popup menu
+ delete _popupMenu;
+}
+
+void View::OnInitialUpdate()
+{
+ CScrollView::OnInitialUpdate();
+ SetScrollSizes(MM_TEXT, CSize(100, 100));
+
+ _document = (Document*)m_pDocument;
+}
+
+void View::LPtoDP(CRect& rect)
+{
+ CClientDC dc(this);
+ OnPrepareDC(&dc, NULL);
+ dc.LPtoDP(&rect);
+ rect.NormalizeRect();
+}
+
+void View::OnDraw(CDC* pDrawDC)
+{
+ CDC* pDC = pDrawDC;
+
+ // clipbox in logical units
+ CRect rectLogical;
+ pDC->GetClipBox(rectLogical);
+
+ // clipbox in device units
+ CRect rectDevice = rectLogical;
+ LPtoDP(rectDevice);
+
+ CDC dc;
+ CBitmap bmp;
+ CBitmap* pbmpOld = NULL;
+
+ // use swap buffer
+ if (/*(!pDC->IsPrinting()) &&*/ (dc.CreateCompatibleDC(pDC)) &&
+ (bmp.CreateCompatibleBitmap(pDC, rectDevice.Width(), rectDevice.Height())))
+ {
+ OnPrepareDC(&dc, NULL);
+ pDC = &dc;
+ dc.OffsetViewportOrg(-rectDevice.left, -rectDevice.top);
+ pbmpOld = dc.SelectObject(&bmp);
+ dc.SetBrushOrg(rectDevice.left % 8, rectDevice.top % 8);
+ dc.IntersectClipRect(rectLogical);
+ }
+
+ // draw all the things
+ pDC->FillRect(rectLogical, new CBrush(::GetSysColor(COLOR_WINDOW)));
+ Draw(pDC, pDrawDC);
+
+ // BitBlt Bitmap into View
+ if (pDrawDC != pDC)
+ {
+ pDrawDC->SetViewportOrg(0, 0);
+ pDrawDC->SetWindowOrg(0, 0);
+ pDrawDC->SetMapMode(MM_TEXT);
+ dc.SetViewportOrg(0, 0);
+ dc.SetWindowOrg(0, 0);
+ dc.SetMapMode(MM_TEXT);
+ pDrawDC->BitBlt(rectDevice.left, rectDevice.top, rectDevice.Width(), rectDevice.Height(), &dc, 0, 0, SRCCOPY);
+ dc.SelectObject(pbmpOld);
+ }
+}
+
+BOOL View::OnEraseBkgnd(CDC* pDC)
+{
+ return TRUE;
+}
+
+void View::Draw(CDC* pDC, CDC* pDrawDC)
+{
+ // let the view background be transparent
+ pDC->SetBkMode(TRANSPARENT);
+
+ // cound number of views
+ int views = 0;
+ if (_viewShearForce)
+ {
+ views++;
+ }
+ if (_viewBendingMoment)
+ {
+ views++;
+ }
+ if (_viewDisplacement)
+ {
+ views++;
+ }
+
+ // if something to draw
+ if ((views != 0) || (_viewContinuousBeam))
+ {
+ // calculate virtual window width
+ CRect rect;
+ GetClientRect(&rect);
+ int width = rect.Width();
+ if (width < 400)
+ {
+ width = 400;
+ }
+
+ // calculate horizontal scale
+ double borderX = _document->_beamLength / 6;
+ double scaleX = width / (_document->_beamLength + 2 * borderX);
+ int beamX = (int)(borderX * scaleX);
+
+ // calculate height of the beam
+ int beamHeight;
+ if (_viewContinuousBeam)
+ {
+ beamHeight = 40 + (_document->SortLoadLevels(pDC, scaleX) * 30) + 32;
+ }
+ else
+ {
+ beamHeight = 0;
+ }
+
+ // calculate virtual window height
+ int height = rect.Height() - 24;
+ if (height < (beamHeight + (views * 80)))
+ {
+ height = beamHeight + (views * 80);
+ }
+
+ // height of one view
+ int viewHeight = 0;
+ if (views != 0)
+ {
+ viewHeight = (height - beamHeight) / views;
+ }
+
+ // select new black drawing pencil and font
+ CPen newPen(PS_SOLID, 1, RGB(0, 0, 0));
+ CPen* oldPen = pDC->SelectObject(&newPen);
+ CFont newFont;
+ newFont.CreateFont(-9, 0, 0, 0, 0, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, NULL);
+ CFont* oldFont = (CFont *)pDC->SelectObject(&newFont);
+ pDC->SetTextAlign(TA_LEFT | TA_TOP);
+
+ if (pDrawDC->IsPrinting())
+ {
+ pDC->TextOut(0, 0, "Beamax");
+ }
+
+ // draw the continuous beam
+ if (_viewContinuousBeam == TRUE)
+ {
+ int beamY = beamHeight - 32;
+
+ // draw the beam object/line
+ pDC->MoveTo(beamX, beamY);
+ pDC->LineTo(beamX + (int)(_document->_beamLength * scaleX), beamY);
+
+ // draw the support and load objects
+ ObjectCast* item;
+ POSITION position = _document->_objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ item = (ObjectCast*)_document->_objectList.GetNext(position);
+ if (item != NULL)
+ {
+ item->Draw(pDC, beamX, beamY, scaleX);
+ }
+ }
+
+ // enable bound box
+ item = (ObjectCast*)_document->_selected;
+ if (item != NULL)
+ {
+ item->GetBoundRect().Draw(pDC);
+ }
+ }
+
+ // get fixed degrees of freedom
+ int fixedDegreesOfFreedom = 0;
+ SupportCast * object;
+ POSITION position = _document->_objectList.GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (SupportCast *)_document->_objectList.GetNext(position);
+ if (object != NULL)
+ {
+ if (CLASSOF(object, "FixedSupport"))
+ {
+ fixedDegreesOfFreedom += 3;
+ }
+ if (CLASSOF(object, "HingedSupport"))
+ {
+ fixedDegreesOfFreedom += 2;
+ }
+ if (CLASSOF(object, "RollerSupport"))
+ {
+ fixedDegreesOfFreedom += 1;
+ }
+ }
+ }
+
+ // start analysis and draw result
+ if ((views > 0) && (fixedDegreesOfFreedom >= 3))
+ {
+ if (!_document->Analyse())
+ {
+ AfxMessageBox("Could not run analysis.");
+ }
+ else
+ {
+ DrawResults(pDC, beamX, beamHeight + (viewHeight / 2), scaleX, viewHeight, views);
+ }
+ }
+
+ // restore old drawing pen and font
+ pDC->SelectObject(oldPen);
+ pDC->SelectObject(oldFont);
+ }
+}
+
+void View::OnLButtonDown(UINT flags, CPoint point)
+{
+ POSITION position;
+ ObjectCast* object;
+
+ _document->_selected = NULL;
+
+ // scan object list
+ position = _document->_objectList.GetHeadPosition();
+ while ((position != NULL) && (_document->_selected == NULL))
+ {
+ object = (ObjectCast*)_document->_objectList.GetNext(position);
+ if (object->GetBoundRect().m_rect.PtInRect(point))
+ {
+ _document->_selected = object;
+ }
+ }
+
+ RedrawWindow();
+ CView::OnLButtonDown(flags, point);
+}
+
+void View::OnRButtonDown(UINT flags, CPoint point)
+{
+ // toggle delete options
+ _popupMenu->EnableMenuItem(IDM_DELETE, MF_BYCOMMAND | (_document->_selected != NULL ? MF_ENABLED : MF_GRAYED));
+
+ // track popup menu
+ CRect rect;
+ GetWindowRect(&rect);
+ CPoint position = rect.TopLeft() + CSize(point);
+ _popupMenu->TrackPopupMenu(TPM_LEFTALIGN, position.x, position.y, this, rect);
+
+ CView::OnRButtonDown(flags, point);
+}
+
+
+void View::OnLButtonDblClk(UINT flags, CPoint point)
+{
+ if (_document->_selected == NULL)
+ {
+ return;
+ }
+ if (CLASSOF(_document->_selected, "FixedSupport"))
+ {
+ OnEditFixedSupport();
+ }
+ if (CLASSOF(_document->_selected, "HingedSupport"))
+ {
+ OnEditHingedSupport();
+ }
+ if (CLASSOF(_document->_selected, "RollerSupport"))
+ {
+ OnEditRollerSupport();
+ }
+ if (CLASSOF(_document->_selected, "PointLoad"))
+ {
+ OnEditPointLoad();
+ }
+ if (CLASSOF(_document->_selected, "LinearDistributedLoad"))
+ {
+ OnEditLinearDistributedLoad();
+ }
+ CView::OnLButtonDblClk(flags, point);
+}
+
+void View::OnCreateFixedSupport()
+{
+ FixedSupportDialog dialog;
+
+ dialog.SetPosition(TRUE);
+ if (dialog.DoModal() == IDOK)
+ {
+ double position = 0;
+ if (!dialog.GetPosition())
+ {
+ position = _document->_beamLength;
+ }
+ if (!_document->CreateFixedSupport(position))
+ {
+ MessageBox("Could not create fixed support.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnEditFixedSupport()
+{
+ FixedSupportDialog dialog;
+
+ FixedSupport* item = (FixedSupport*)_document->_selected;
+ dialog.SetPosition(TRUE);
+ if (item->GetPosition() != 0)
+ {
+ dialog.SetPosition(FALSE);
+ }
+ if (dialog.DoModal() == IDOK)
+ {
+ item->SetPosition(0);
+ if (dialog.GetPosition() != TRUE)
+ {
+ item->SetPosition(_document->_beamLength);
+ }
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnCreateHingedSupport()
+{
+ HingedSupportDialog dialog;
+
+ dialog.SetPosition(0);
+ if (dialog.DoModal() == IDOK)
+ {
+ if (!_document->CreateHingedSupport(dialog.GetPosition()))
+ {
+ MessageBox("Could not create hinged support.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnEditHingedSupport()
+{
+ HingedSupportDialog dialog;
+
+ HingedSupport* item = (HingedSupport*)_document->_selected;
+ dialog.SetPosition(item->GetPosition());
+ if (dialog.DoModal() == IDOK)
+ {
+ double position = dialog.GetPosition();
+ if ((position < 0) || (position > _document->_beamLength))
+ {
+ MessageBox("Support position not in beam range.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ else
+ {
+ item->SetPosition(position);
+ _document->UpdateAllViews(NULL);
+ }
+ }
+}
+
+void View::OnCreateRollerSupport()
+{
+ RollerSupportDialog dialog;
+
+ dialog.SetPosition(0);
+ if (dialog.DoModal() == IDOK)
+ {
+ if (!_document->CreateRollerSupport(dialog.GetPosition()))
+ {
+ MessageBox("Could not create roller support.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnEditRollerSupport()
+{
+ RollerSupportDialog dialog;
+
+ RollerSupport* item = (RollerSupport*)_document->_selected;
+ dialog.SetPosition(item->GetPosition());
+ if (dialog.DoModal() == IDOK)
+ {
+ double position = dialog.GetPosition();
+ if ((position < 0) || (position > _document->_beamLength))
+ {
+ MessageBox("Support position not in beam range.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ else
+ {
+ item->SetPosition(position);
+ _document->UpdateAllViews(NULL);
+ }
+ }
+}
+
+void View::OnCreatePointLoad()
+{
+ PointLoadDialog dialog;
+
+ dialog.SetPosition(0);
+ dialog.SetValue(1);
+ if (dialog.DoModal() == IDOK)
+ {
+ if (!_document->CreatePointLoad(dialog.GetPosition(), dialog.GetValue()))
+ {
+ MessageBox("Could not create point load.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnEditPointLoad()
+{
+ PointLoadDialog dialog;
+
+ PointLoad* item = (PointLoad*)_document->_selected;
+ dialog.SetPosition(item->GetPosition());
+ dialog.SetValue(item->GetValue());
+ if (dialog.DoModal() == IDOK)
+ {
+ double position = dialog.GetPosition();
+ if ((position < 0) || (position > _document->_beamLength))
+ {
+ MessageBox("Point load not in beam range.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ else
+ {
+ item->SetPosition(position);
+ item->SetValue(dialog.GetValue());
+ _document->UpdateAllViews(NULL);
+ }
+ }
+}
+
+void View::OnCreateLinearDistributedLoad()
+{
+ LinearDistributedLoadDialog dialog;
+
+ dialog.SetPosition(0);
+ dialog.SetValue(1);
+ dialog.SetLength(0);
+ if (dialog.DoModal() == IDOK)
+ {
+ if (!_document->CreateLinearDistributedLoad(dialog.GetPosition(), dialog.GetValue(), dialog.GetLength()))
+ {
+ MessageBox("Could not create linear distributed load.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnEditLinearDistributedLoad()
+{
+ LinearDistributedLoadDialog dialog;
+
+ LinearDistributedLoad* item = (LinearDistributedLoad*)_document->_selected;
+ dialog.SetPosition(item->GetPosition());
+ dialog.SetValue(item->GetValue());
+ dialog.SetLength(item->GetLength());
+ if (dialog.DoModal() == IDOK)
+ {
+ double position = dialog.GetPosition();
+ double length = dialog.GetLength();
+ if ((length < 0) || (position < 0) || ((position + length) > _document->_beamLength))
+ {
+ MessageBox("Linear distributed load not in beam range.", "Error", MB_OK | MB_ICONSTOP);
+ }
+ else
+ {
+ item->SetPosition(position);
+ item->SetValue(dialog.GetValue());
+ item->SetLength(length);
+ _document->UpdateAllViews(NULL);
+ }
+ }
+}
+
+void View::OnDelete(void)
+{
+ if (_document->_selected != NULL)
+ {
+ _document->DeleteObject((ObjectCast*)_document->_selected);
+ _document->_selected = NULL;
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnUpdateDelete(CCmdUI* pCmdUI)
+{
+ if (_document->_selected != NULL)
+ {
+ pCmdUI->Enable(TRUE);
+ }
+ else
+ {
+ pCmdUI->Enable(FALSE);
+ }
+}
+
+void View::OnViewContinuousBeam()
+{
+ if (_viewContinuousBeam)
+ {
+ _viewContinuousBeam = FALSE;
+ }
+ else
+ {
+ _viewContinuousBeam = TRUE;
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnUpdateViewContinuousBeam(CCmdUI* pCmdUI)
+{
+ if (_viewContinuousBeam)
+ {
+ pCmdUI->SetCheck(1);
+ }
+ else
+ {
+ pCmdUI->SetCheck(0);
+ }
+}
+
+void View::OnViewShearForce()
+{
+ if (_viewShearForce)
+ {
+ _viewShearForce = FALSE;
+ }
+ else
+ {
+ _viewShearForce = TRUE;
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnUpdateViewShearForce(CCmdUI* pCmdUI)
+{
+ if (_viewShearForce)
+ {
+ pCmdUI->SetCheck(1);
+ }
+ else
+ {
+ pCmdUI->SetCheck(0);
+ }
+}
+
+void View::OnViewBendingMoment()
+{
+ if (_viewBendingMoment)
+ {
+ _viewBendingMoment = FALSE;
+ }
+ else
+ {
+ _viewBendingMoment = TRUE;
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnUpdateViewBendingMoment(CCmdUI* pCmdUI)
+{
+ if (_viewBendingMoment)
+ {
+ pCmdUI->SetCheck(1);
+ }
+ else
+ {
+ pCmdUI->SetCheck(0);
+ }
+}
+
+void View::OnViewDisplacement()
+{
+ if (_viewDisplacement)
+ {
+ _viewDisplacement = FALSE;
+ }
+ else
+ {
+ _viewDisplacement = TRUE;
+ }
+
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnUpdateViewDisplacement(CCmdUI* pCmdUI)
+{
+ if (_viewDisplacement)
+ {
+ pCmdUI->SetCheck(1);
+ }
+ else
+ {
+ pCmdUI->SetCheck(0);
+ }
+}
+
+void View::OnViewNumericalValues()
+{
+ if (_viewNumericalValues)
+ {
+ _viewNumericalValues = FALSE;
+ }
+ else
+ {
+ _viewNumericalValues = TRUE;
+ }
+ _document->UpdateAllViews(NULL);
+}
+
+void View::OnUpdateViewNumericalValues(CCmdUI* pCmdUI)
+{
+ if (_viewNumericalValues)
+ {
+ pCmdUI->SetCheck(1);
+ }
+ else
+ {
+ pCmdUI->SetCheck(0);
+ }
+}
+
+BOOL View::OnPreparePrinting(CPrintInfo* pPrintInfo)
+{
+ return DoPreparePrinting(pPrintInfo);
+}
+
+void View::OnBeginPrinting(CDC* pDC, CPrintInfo* pPrintInfo)
+{
+}
+
+void View::OnEndPrinting(CDC* pDC, CPrintInfo* pPrintInfo)
+{
+}
+
+void View::OnPrepareDC(CDC* pDC, CPrintInfo* pPrintInfo)
+{
+ CScrollView::OnPrepareDC(pDC, pPrintInfo);
+
+ if (pDC->IsPrinting())
+ {
+ pDC->SetMapMode(MM_ANISOTROPIC);
+ CRect r;
+ GetClientRect(&r);
+ CSize w = r.Size();
+ CSize v(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
+ v.cy = (int)((v.cx * w.cy) / w.cx);
+ pDC->SetWindowExt(w);
+ pDC->SetViewportExt(v);
+ }
+}
+
+double View::GetMaximum(Section* object)
+{
+ if ((object->A4 != 0) || (object->A3 != 0) || (object->A2 != 0))
+ {
+ // start at section / 2
+ double x = object->Length / 2;
+
+ // newton iteration
+ for (int i = 0; i < 32; i++)
+ {
+ x = x - ((4 * object->A4 * x * x * x + 3 * object->A3 * x * x +
+ 2 * object->A2 * x + object->A1) /
+ (12 * object->A4 * x * x + 6 * object->A3 * x +
+ 2 * object->A2));
+ }
+
+ if ((x > 0) && (x < object->Length))
+ {
+ return x;
+ }
+ }
+ return 0;
+}
+
+double View::SolvePolynom(double x, Section* object)
+{
+ if (object->A4 == 0)
+ {
+ if (object->A3 == 0)
+ {
+ if (object->A2 == 0)
+ {
+ if (object->A1 == 0)
+ {
+ return (object->A0);
+ }
+ return (object->A1 * x + object->A0);
+ }
+ return (object->A2 * x * x + object->A1 * x + object->A0);
+ }
+ return (object->A3 * x * x * x + object->A2 * x * x + object->A1 * x + object->A0);
+ }
+ return (object->A4 * x * x * x * x + object->A3 * x * x * x + object->A2 * x * x + object->A1 * x + object->A0);
+}
+
+BOOL View::IsRectEmpty(CDC* pDC, int x1, int y1, int x2, int y2)
+{
+ COLORREF Background = pDC->GetBkColor();
+ for (int x = (x1 - 1); x < (x2 + 1); x++)
+ {
+ for (int y = (y1 - 1); y < (y2 + 1); y++)
+ {
+ if (pDC->GetPixel(x, y) != Background)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+void View::DrawValue(CDC* pDC, int x, int y, BOOL mirror, double value)
+{
+ char buffer[32];
+ sprintf_s(buffer, "%.2f", value);
+ CSize textSize(pDC->GetTextExtent(buffer, (int)strlen(buffer)));
+ int x1 = x - (textSize.cx / 2);
+ int x2 = x + (textSize.cx / 2);
+ if (mirror) value *= (-1);
+ if (value < 0)
+ {
+ pDC->SetTextAlign(TA_CENTER | TA_BOTTOM);
+ int y1 = y - textSize.cy;
+ int y2 = y;
+ for (int i = 2; i <= 12; i = i + 6)
+ {
+ if (IsRectEmpty(pDC, x1, y1 - i, x2, y2 - i) == TRUE)
+ {
+ pDC->TextOut(x, y - i, buffer);
+ return;
+ }
+ }
+ }
+ else
+ {
+ pDC->SetTextAlign(TA_CENTER | TA_TOP);
+ int y1 = y;
+ int y2 = y + textSize.cy;
+ for (int i = 2; i <= 12; i = i + 6)
+ {
+ if (IsRectEmpty(pDC, x1, y1 + i, x2, y2 + i) == TRUE)
+ {
+ pDC->TextOut(x, y + i, buffer);
+ return;
+ }
+ }
+ }
+}
+
+void View::DrawView(CDC* pDC, int beamX, int beamY, double scaleX, int viewHeight, BOOL mirror, BOOL values, double unitScale, char* unitName, char* viewName, CObList* sectionList)
+{
+ POSITION position;
+ Section* object;
+
+ // draw the beam
+ pDC->MoveTo(beamX, beamY);
+ pDC->LineTo(beamX + (int)(_document->_beamLength * scaleX), beamY);
+
+ // print view name
+ CSize textSize(pDC->GetTextExtent(viewName, (int)strlen(viewName)));
+ pDC->MoveTo(beamX - textSize.cx - 20, beamY - (textSize.cy / 2) - 3);
+ pDC->LineTo(beamX - 12, beamY - (textSize.cy / 2) - 3);
+ pDC->LineTo(beamX - 12, beamY + (textSize.cy / 2) + 3);
+ pDC->LineTo(beamX - textSize.cx - 20, beamY + (textSize.cy / 2) + 3);
+ pDC->LineTo(beamX - textSize.cx - 20, beamY - (textSize.cy / 2) - 3);
+ pDC->TextOut(beamX - textSize.cx - 16, beamY - (textSize.cy / 2), viewName);
+
+ // print unit name
+ textSize = pDC->GetTextExtent(unitName, sizeof(unitName));
+ pDC->TextOut(beamX + (int)(_document->_beamLength * scaleX) + 12, beamY - (textSize.cy / 2), unitName);
+
+ // find maximum value for scaling
+ double maximum = 0;
+ position = sectionList->GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (Section*)sectionList->GetNext(position);
+ if (object != NULL)
+ {
+ double x = GetMaximum(object);
+ if (maximum < fabs(SolvePolynom(x, object)))
+ {
+ maximum = fabs(SolvePolynom(x, object));
+ }
+ if (maximum < fabs(SolvePolynom(0, object)))
+ {
+ maximum = fabs(SolvePolynom(0, object));
+ }
+ if (maximum < fabs(SolvePolynom(object->Length, object)))
+ {
+ maximum = fabs(SolvePolynom(object->Length, object));
+ }
+ }
+ }
+
+ // calculate scale for y axis
+ double scaleY = (viewHeight / maximum) * 0.36 * (mirror ? -1 : 1);
+
+ // draw the graph
+ position = sectionList->GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (Section*)sectionList->GetNext(position);
+ if (object != NULL)
+ {
+ pDC->MoveTo(beamX + (int)(object->Start * scaleX), beamY);
+
+ double dx = (1 / scaleX);
+
+ for (double x = 0; x < object->Length; x += dx)
+ {
+ pDC->LineTo(beamX + (int)((object->Start + x) * scaleX), beamY + (int)(SolvePolynom(x, object) * scaleY));
+ }
+
+ double y = SolvePolynom(object->Length, object);
+
+ pDC->LineTo(beamX + (int)((object->Start + object->Length) * scaleX), beamY + (int)(y * scaleY));
+ pDC->LineTo(beamX + (int)((object->Start + object->Length) * scaleX), beamY);
+ }
+ }
+
+ // draw numerical values
+ if (values)
+ {
+ // selecet text align
+ UINT oldTextAlign = pDC->SetTextAlign(TA_CENTER | TA_TOP);
+
+ // draw the values
+ position = sectionList->GetHeadPosition();
+ while (position != NULL)
+ {
+ object = (Section*)sectionList->GetNext(position);
+ if (object != NULL)
+ {
+ double x;
+ double y;
+
+ // draw left value
+ y = SolvePolynom(0, object);
+ if (fabs(y) > EPSILON)
+ {
+ DrawValue(pDC, beamX + (int)(object->Start * scaleX), beamY + (int)(y * scaleY), mirror, y * unitScale);
+ }
+
+ // draw maximum value
+ x = GetMaximum(object);
+ y = SolvePolynom(x, object);
+ if ((fabs(y) > EPSILON) && (!mirror))
+ {
+ DrawValue(pDC, beamX + (int)((object->Start + x) * scaleX), beamY + (int)(y * scaleY), mirror, y * unitScale);
+ }
+
+ // draw right value
+ y = SolvePolynom(object->Length, object);
+ if (fabs(y) > EPSILON)
+ {
+ DrawValue(pDC, beamX + (int)((object->Start + object->Length) * scaleX), beamY + (int)(y * scaleY), mirror, y * unitScale);
+ }
+ }
+ }
+
+ // restore text align
+ pDC->SetTextAlign(oldTextAlign);
+ }
+}
+
+void View::DrawResults(CDC* pDC, int beamX, int beamY, double scaleX, int viewHeight, int views)
+{
+ // draw shear force graph
+ if (_viewShearForce)
+ {
+ DrawView(pDC, beamX, beamY, scaleX, viewHeight, TRUE, _viewNumericalValues, 1, "[kN]", "FZ", &_document->_shearForceList);
+ beamY += viewHeight;
+ }
+
+ // draw bending moment graph
+ if (_viewBendingMoment)
+ {
+ DrawView(pDC, beamX, beamY, scaleX, viewHeight, FALSE, _viewNumericalValues, 1, "[kNm]", "MY", &_document->_bendingMomentList);
+ beamY += viewHeight;
+ }
+
+ // draw displacement graph
+ if (_viewDisplacement)
+ {
+ DrawView(pDC, beamX, beamY, scaleX, viewHeight, FALSE, _viewNumericalValues, 1000, "[mm]", "UZ", &_document->_displacementList);
+ beamY += viewHeight;
+ }
+}
diff --git a/Source/View.h b/Source/View.h
new file mode 100644
index 0000000..aac0247
--- /dev/null
+++ b/Source/View.h
@@ -0,0 +1,74 @@
+#ifndef __View__
+#define __View__
+
+class View : public CScrollView
+{
+private:
+ Document* _document;
+ CMenu* _popupMenu;
+ BOOL _viewContinuousBeam;
+ BOOL _viewShearForce;
+ BOOL _viewBendingMoment;
+ BOOL _viewDisplacement;
+ BOOL _viewNumericalValues;
+
+public:
+ View();
+ virtual ~View();
+
+ // message handler
+protected:
+ virtual void OnInitialUpdate();
+ virtual void OnDraw(CDC* pDC);
+ virtual BOOL OnEraseBkgnd(CDC* pDC);
+ afx_msg void OnLButtonDown(UINT flags, CPoint point);
+ afx_msg void OnRButtonDown(UINT flags, CPoint point);
+ afx_msg void OnLButtonDblClk(UINT flags, CPoint point);
+ afx_msg void OnCreateFixedSupport();
+ afx_msg void OnEditFixedSupport();
+ afx_msg void OnCreateHingedSupport();
+ afx_msg void OnEditHingedSupport();
+ afx_msg void OnCreateRollerSupport();
+ afx_msg void OnEditRollerSupport();
+ afx_msg void OnCreatePointLoad();
+ afx_msg void OnEditPointLoad();
+ afx_msg void OnCreateLinearDistributedLoad();
+ afx_msg void OnEditLinearDistributedLoad();
+ afx_msg void OnDelete();
+ afx_msg void OnUpdateDelete(CCmdUI* pCmdUI);
+ afx_msg void OnOneLevelUp();
+ afx_msg void OnUpdateOneLevelUp(CCmdUI* pCmdUI);
+ afx_msg void OnOneLevelDown();
+ afx_msg void OnUpdateOneLevelDown(CCmdUI* pCmdUI);
+ afx_msg void OnViewContinuousBeam();
+ afx_msg void OnUpdateViewContinuousBeam(CCmdUI* pCmdUI);
+ afx_msg void OnViewShearForce();
+ afx_msg void OnUpdateViewShearForce(CCmdUI* pCmdUI);
+ afx_msg void OnViewBendingMoment();
+ afx_msg void OnUpdateViewBendingMoment(CCmdUI* pCmdUI);
+ afx_msg void OnViewDisplacement();
+ afx_msg void OnUpdateViewDisplacement(CCmdUI* pCmdUI);
+ afx_msg void OnViewNumericalValues();
+ afx_msg void OnUpdateViewNumericalValues(CCmdUI* pCmdUI);
+
+ // printer handler
+ virtual BOOL OnPreparePrinting(CPrintInfo* pPrintInfo);
+ virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pPrintInfo);
+ virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pPrintInfo);
+ virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pPrintInfo);
+
+ // graph functions
+ inline double GetMaximum(Section* object);
+ inline double SolvePolynom(double x, Section* object);
+ inline BOOL IsRectEmpty(CDC* pDC, int x1, int y1, int x2, int y2);
+ void LPtoDP(CRect& rect);
+ void Draw(CDC* pDC, CDC* pDrawDC);
+ void DrawValue(CDC* pDC, int x, int y, BOOL mirror, double value);
+ void DrawView(CDC* pDC, int beamX, int beamY, double scaleX, int viewHeight, BOOL mirror, BOOL values, double unit, char* unitName, char* viewName, CObList* sectionList);
+ void DrawResults(CDC* pDC, int beamX, int beamY, double scaleX, int viewHeight, int views);
+
+ DECLARE_MESSAGE_MAP()
+ DECLARE_DYNCREATE(View)
+};
+
+#endif
diff --git a/Source/stdafx.cpp b/Source/stdafx.cpp
new file mode 100644
index 0000000..1577c4e
--- /dev/null
+++ b/Source/stdafx.cpp
@@ -0,0 +1 @@
+#include "stdafx.h"
\ No newline at end of file
diff --git a/Source/stdafx.h b/Source/stdafx.h
new file mode 100644
index 0000000..6e64937
--- /dev/null
+++ b/Source/stdafx.h
@@ -0,0 +1,12 @@
+#ifndef __Stdafx__
+#define __Stdafx__
+
+#include
+#include
+#include
+
+#define CLASSOF(_instance, _class) (strcmp(_instance->GetRuntimeClass()->m_lpszClassName, _class) == 0 ? TRUE : FALSE)
+
+#include "Analysis.h"
+
+#endif
\ No newline at end of file