From 55cc30ee305d1f2cf0434c42ef597e599dd7acab Mon Sep 17 00:00:00 2001 From: Lutz Roeder Date: Mon, 14 Sep 1998 12:00:00 +0100 Subject: [PATCH] first commit --- .github/screenshot.png | Bin 0 -> 44372 bytes .gitignore | 12 + LICENSE | 19 + README.md | 5 + Samples/Example.bcb | Bin 0 -> 179 bytes Source/Analysis.cpp | 1101 ++++++++++++++++++++++++++++++++++++++++ Source/Analysis.h | 212 ++++++++ Source/Application.cpp | 156 ++++++ Source/Application.h | 36 ++ Source/Application.ico | Bin 0 -> 766 bytes Source/Application.rc | 348 +++++++++++++ Source/Beamax.sln | 31 ++ Source/Beamax.vcxproj | 223 ++++++++ Source/Dialog.cpp | 189 +++++++ Source/Dialog.h | 157 ++++++ Source/Document.cpp | 442 ++++++++++++++++ Source/Document.h | 47 ++ Source/Document.ico | Bin 0 -> 766 bytes Source/Object.cpp | 308 +++++++++++ Source/Object.h | 107 ++++ Source/Resource.h | 54 ++ Source/ToolBar.bmp | Bin 0 -> 1978 bytes Source/View.cpp | 965 +++++++++++++++++++++++++++++++++++ Source/View.h | 74 +++ Source/stdafx.cpp | 1 + Source/stdafx.h | 12 + 26 files changed, 4499 insertions(+) create mode 100644 .github/screenshot.png create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Samples/Example.bcb create mode 100644 Source/Analysis.cpp create mode 100644 Source/Analysis.h create mode 100644 Source/Application.cpp create mode 100644 Source/Application.h create mode 100644 Source/Application.ico create mode 100644 Source/Application.rc create mode 100644 Source/Beamax.sln create mode 100644 Source/Beamax.vcxproj create mode 100644 Source/Dialog.cpp create mode 100644 Source/Dialog.h create mode 100644 Source/Document.cpp create mode 100644 Source/Document.h create mode 100644 Source/Document.ico create mode 100644 Source/Object.cpp create mode 100644 Source/Object.h create mode 100644 Source/Resource.h create mode 100644 Source/ToolBar.bmp create mode 100644 Source/View.cpp create mode 100644 Source/View.h create mode 100644 Source/stdafx.cpp create mode 100644 Source/stdafx.h diff --git a/.github/screenshot.png b/.github/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..eaa76d8ebbadc33b7be4ea822976fba4777f6134 GIT binary patch literal 44372 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 Zw=dgr@*?`#?P>70#oTgZ_IlTo{|DC7Ycv1= literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..dd5be6ebaebafeaca68bf188f60576ee7ecf1f8a GIT binary patch literal 179 zcmZQz009*T5V?_KrK1#gh=A`aQF~T~|Nog8co^I=D^gQ}OA89}i%LLhKma7e%ixij zmyRZ--~f^mW$?+&OHC|t$t*4@%1kOPNlo#|PfUU66>vbM8NgaN83OV%^GXoPAPxd5 PbzpCRXkc)F&>!pp +#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 0000000000000000000000000000000000000000..35d685b1a807d0e4e08e22d7dd6422e487467a81 GIT binary patch literal 766 zcmb7?F?Pcs42DJ1_uP$6S?jU4XpfW)wrDfQ@=-kY26UsJAdYcfo3^rlq#waAfi2>A z#_?IqJ|0Al_*XE3ci`laQAEjoZ%UGkYIBT)GS4&K5~aRUiba6Orfm4D4GHTO`+(^- z;lsJ)*mITpJf*N({|~*GlBf7pKZoE$r&kIbJ6-#kJg3boO}a+ahY)qx4l}SbKHYH1 zZ4ad<#a wyhOh_+QsGp9Dw@~i@37Kq0BNAZNC!b-7V@bW_gockY6aX@FA8L@MeX}7bO(IKL7v# literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..35d685b1a807d0e4e08e22d7dd6422e487467a81 GIT binary patch literal 766 zcmb7?F?Pcs42DJ1_uP$6S?jU4XpfW)wrDfQ@=-kY26UsJAdYcfo3^rlq#waAfi2>A z#_?IqJ|0Al_*XE3ci`laQAEjoZ%UGkYIBT)GS4&K5~aRUiba6Orfm4D4GHTO`+(^- z;lsJ)*mITpJf*N({|~*GlBf7pKZoE$r&kIbJ6-#kJg3boO}a+ahY)qx4l}SbKHYH1 zZ4ad<#a wyhOh_+QsGp9Dw@~i@37Kq0BNAZNC!b-7V@bW_gockY6aX@FA8L@MeX}7bO(IKL7v# literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ff86214b9e055017ad030a64170ddb4f2866b1b7 GIT binary patch literal 1978 zcmb`HJ#HH@5QQm3G6SS=kWM#9X+Recf^7r1+1{1vslryJO1tzeRA(C ziloE=!d?Ck=gpfL^2^unIeGa;`*HUE1xo6E@a|VEDZ9!+tM8 z4oa3}6)u>)JoDE;STUg2U6&{99(=HIfyB>v4?*00p743Y2F=O3A&_dl2Zc$?14u)? zhAJiN)(P4LY|GBOe_Vi#ReYQ}_4%-u)3>(rGGQB*3Y-HD+>@W;LZ%*s|mZr#XrM!?Z0Cy+KwHG2sXrpz1c*(`<{4T=RFL=9-|+0{@mxG z62Rtwx^SI0-V}NKO}>HcMY*=X>4AL_?;F_o+}S8bF=+j{&uhE|D>218c;obq=egw( zoBi{6Yj(-I)VGDLpgZ+$R4nE(&yfpkqV4epH?ZT55fSoy$~C|LQo@aS(8()r%ProX zCFrX6TS}zC?|0<+pYQj5WyA{<*ccZ&rKxQ;U$?$qK1V9;U1Jv5a;i8g^Ma?pZy~Lv v`mWW8l7lw#ZbE +#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