use crate::stress_processor::{StressBondDesc, StressImpulse, StressNodeDesc};
use crate::types::BondStressResult;
pub fn compute_bond_stress(
bond: &StressBondDesc,
impulse: &StressImpulse,
nodes: &[StressNodeDesc],
bond_area: f32,
) -> BondStressResult {
if bond_area <= 0.0 {
return BondStressResult::default();
}
let node0 = bond.node0 as usize;
let node1 = bond.node1 as usize;
if node0 >= nodes.len() || node1 >= nodes.len() {
return BondStressResult::default();
}
let displacement = nodes[node1].com - nodes[node0].com;
let node_distance = displacement.magnitude().max(1.0e-6);
let bond_normal = displacement.normalize();
let linear = impulse.lin;
let angular = impulse.ang;
let normal_component_linear = linear.dot(bond_normal);
let shear_linear_sq =
(linear.magnitude_squared() - normal_component_linear * normal_component_linear).max(0.0);
let mut stress_normal = normal_component_linear / bond_area;
let mut stress_shear = shear_linear_sq.sqrt() / bond_area;
let normal_component_angular = angular.dot(bond_normal).abs();
let angular_mag_sq = angular.magnitude_squared();
let twist = normal_component_angular / bond_area;
let bend_sq = (angular_mag_sq - normal_component_angular * normal_component_angular).max(0.0);
let bend = bend_sq.sqrt() / bond_area;
let twist_contribution = twist * 2.0 / node_distance;
stress_shear += twist_contribution;
let bend_contribution = bend * 2.0 / node_distance;
let sign = if stress_normal >= 0.0 { 1.0 } else { -1.0 };
stress_normal += bend_contribution * sign;
BondStressResult {
compression: if stress_normal < 0.0 {
-stress_normal
} else {
0.0
},
tension: if stress_normal > 0.0 {
stress_normal
} else {
0.0
},
shear: stress_shear,
}
}