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. + +Screenshot \ 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