feat(cpp-object-oriented-modular-refactoring): step 8 - element-geometry-vector3

This commit is contained in:
KOKO\Mimi
2026-08-16 07:27:51 +09:00
parent cbad5c3592
commit a9ff75b3fa
9 changed files with 320 additions and 233 deletions
+18 -39
View File
@@ -9,6 +9,8 @@
#include <utility>
#include <vector>
#include "fesa/math/vector3.h"
namespace fesa {
namespace {
@@ -17,26 +19,6 @@ constexpr std::size_t kGeneralizedComponentCount = 4U;
constexpr double kGeometryTolerance = 1.0e-12;
constexpr double kStiffnessInvariantTolerance = 1.0e-12;
using Vector3 = std::array<double, 3>;
double Norm(const Vector3& value) {
return std::hypot(value[0], value[1], value[2]);
}
double Dot(const Vector3& lhs, const Vector3& rhs) {
return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2];
}
Vector3 Cross(const Vector3& lhs, const Vector3& rhs) {
return {lhs[1] * rhs[2] - lhs[2] * rhs[1], lhs[2] * rhs[0] - lhs[0] * rhs[2],
lhs[0] * rhs[1] - lhs[1] * rhs[0]};
}
bool IsFinite(const Vector3& value) {
return std::isfinite(value[0]) && std::isfinite(value[1]) &&
std::isfinite(value[2]);
}
std::string ElementIdentity(const Node& first_node, const Node& second_node) {
return first_node.source_id.instance_name + ":" +
first_node.source_id.source_label_text + "-" +
@@ -233,13 +215,13 @@ Result<EulerBeam3D> EulerBeam3D::Create(const Node& first_node,
const GeneralBeamSection& section,
const LinearElasticMaterial& material) {
const std::string identity = ElementIdentity(first_node, second_node);
const Vector3& first = first_node.coordinates;
const Vector3& second = second_node.coordinates;
const Vector3 delta = {second[0] - first[0], second[1] - first[1],
second[2] - first[2]};
const double length = Norm(delta);
const double coordinate_scale = (std::max)({1.0, Norm(first), Norm(second)});
if (!IsFinite(first) || !IsFinite(second) || !IsFinite(delta) ||
const Vector3 first{first_node.coordinates};
const Vector3 second{second_node.coordinates};
const Vector3 delta = second - first;
const double length = delta.Norm();
const double coordinate_scale =
(std::max)({1.0, first.Norm(), second.Norm()});
if (!first.IsFinite() || !second.IsFinite() || !delta.IsFinite() ||
!std::isfinite(length) || !std::isfinite(coordinate_scale) ||
!(length > kGeometryTolerance * coordinate_scale)) {
return ModelFailure(
@@ -247,15 +229,13 @@ Result<EulerBeam3D> EulerBeam3D::Create(const Node& first_node,
"Beam length must exceed the scale-aware geometry threshold.");
}
const Vector3 ex = {delta[0] / length, delta[1] / length, delta[2] / length};
const Vector3& guide = section.first_axis;
const double guide_norm = Norm(guide);
const double guide_projection = Dot(guide, ex);
const Vector3 ey_trial = {guide[0] - guide_projection * ex[0],
guide[1] - guide_projection * ex[1],
guide[2] - guide_projection * ex[2]};
const double ey_trial_norm = Norm(ey_trial);
if (!IsFinite(guide) || !std::isfinite(guide_norm) || !IsFinite(ey_trial) ||
const Vector3 ex = delta / length;
const Vector3 guide{section.first_axis};
const double guide_norm = guide.Norm();
const double guide_projection = guide.Dot(ex);
const Vector3 ey_trial = guide - guide_projection * ex;
const double ey_trial_norm = ey_trial.Norm();
if (!guide.IsFinite() || !std::isfinite(guide_norm) || !ey_trial.IsFinite() ||
!std::isfinite(ey_trial_norm) ||
!(ey_trial_norm > kGeometryTolerance * (std::max)(1.0, guide_norm))) {
return ModelFailure(
@@ -323,9 +303,8 @@ Result<EulerBeam3D> EulerBeam3D::Create(const Node& first_node,
"Derived beam stiffness coefficients must be finite and positive.");
}
const Vector3 ey = {ey_trial[0] / ey_trial_norm, ey_trial[1] / ey_trial_norm,
ey_trial[2] / ey_trial_norm};
const Vector3 ez = Cross(ex, ey);
const Vector3 ey = ey_trial / ey_trial_norm;
const Vector3 ez = ex.Cross(ey);
// Rows map global vectors to the approved right-handed local (ex,ey,ez)
// basis.
const std::array<double, 9> rotation = {ex[0], ex[1], ex[2], ey[0], ey[1],