提问人:Chris Vorster 提问时间:10/5/2023 更新时间:10/5/2023 访问量:28
坐标系转换和实施
Coordinate System Transformation and implementation
问:
我正在尝试从 OOFEM(分析引擎)生成的输出文件中读取分析结果,然后使用 C# 和 VB.Net 的组合将从文件中读取的偏转应用到我的模型上。我正在使用 devDept.Eyeshot 进行可视化。
我在尝试将 OOFEM beam3d 元素输出转换为应用程序中的全局坐标系时遇到了问题。关于此事的 OOFEM 文档:
用于 3D 线性分析的梁单元,基于 Timchshenko 假设。支持任意自由度的内部冷凝,并在本地系统中执行。在输出时,局部端位移和局部端力以局部坐标系打印。要求根据惯性的主要中心轴选择局部系统。局部元素坐标系由以下规则确定: l.让第一个元素节点具有以下坐标(习,Yi,Zi),第二个元素节点(Xj,Yj,Zj), 2. 局部 X 轴的方向向量为 a1 = (Xj – 习, Yj – Yi, Zj – Zi), 3.局部Y轴方向矢量位于局部X轴方向矢量(a1)和给定点的平面内 (带有坐标(Xk、Yk、Zk)的 k 节点) - 所谓的参考节点, 4.然后通过向量(Xk – 习,Yk – Yi,Zk – Zi)确定局部Z轴方向向量(a1)的向量乘积, 5.然后确定局部Y轴由局部X轴方向矢量确定为局部Z轴方向矢量的矢量乘积。
我的代码由一个用于 CrossSection 对象的 C# 类组成,该类尝试使用 Cross Section 属性确定 KNode 和梁的 X 方向。横截面始终定义为 XY 平面上的 2D 区域。特此摘录有关计算部分的摘录:
AreaProperties areaProperties = new AreaProperties();
List<Point3D> lstp3d = new List<Point3D>();
foreach (Point2D pt in coords){
lstp3d.Add(new Point3D(pt.X, pt.Y, 0));
}
areaProperties.Add(lstp3d);
Centroid = new Point3D(Math.Round(areaProperties.Centroid.X, 5), Math.Round(areaProperties.Centroid.Y, 5), Math.Round(areaProperties.Centroid.Z, 5));
KNode = new Point3D(Centroid.X + width / 2, Centroid.Y, Centroid.Z);
然后在我自己的 Beam3D 课程中,我有:
public void SetLocalVectors(Node nde1, Node nde2)
{
Vector3D localX = new Vector3D(nde1.ToPoint3D(), nde2.ToPoint3D());
localX.Normalize();
// Use the KNode property to get the direction to the k-node
Vector3D toKNode = new Vector3D(nde1.ToPoint3D(), CrossSection.KNode);
// Compute the Local Z-Axis
Vector3D localZ = Vector3D.Cross(toKNode, localX);
localZ.Normalize();
// Compute the Local Y-Axis
Vector3D localY = Vector3D.Cross(localZ, localX);
localY.Normalize();
LocalXDirection = localX;
LocalYDirection = localY;
LocalZDirection = localZ;
}
我尝试设置光束的局部坐标系,以便以后可以正确解释结果,并应用于全局 CS。
我正在阅读 OOFEM 结果如下:
public void ReadBeamOutput(string filePath, OOFEMProject project)
{
if (File.Exists(filePath))
{
using (StreamReader reader = new StreamReader(filePath))
{
// Skip the header line
reader.ReadLine();
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("endStep"))
{
break;
}
string[] parts = line.Split(';');
double time = double.Parse(parts[0], CultureInfo.InvariantCulture);
int beamId = int.Parse(parts[1]);
double distanceFromI = Math.Round(double.Parse(parts[2], CultureInfo.InvariantCulture), 5);
Beam3D beam = FindBeamById(beamId);
if (beam != null)
{
// Create a transformation matrix using the local axes
Matrix3D transformationMatrix = new Matrix3D(
beam.LocalXDirection.X, beam.LocalXDirection.Y, beam.LocalXDirection.Z, 0,
beam.LocalYDirection.X, beam.LocalYDirection.Y, beam.LocalYDirection.Z, 0,
beam.LocalZDirection.X, beam.LocalZDirection.Y, beam.LocalZDirection.Z, 0,
0, 0, 0, 1
);
// Convert local results to global coordinates
System.Windows.Media.Media3D.Vector3D localDeflection = new System.Windows.Media.Media3D.Vector3D(
Math.Round(double.Parse(parts[9], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[10], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[11], CultureInfo.InvariantCulture), 10)
);
System.Windows.Media.Media3D.Vector3D globalDeflection = System.Windows.Media.Media3D.Vector3D.Multiply(localDeflection, transformationMatrix);
System.Windows.Media.Media3D.Vector3D localRotation = new System.Windows.Media.Media3D.Vector3D(
Math.Round(double.Parse(parts[12], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[13], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[14], CultureInfo.InvariantCulture), 10)
);
System.Windows.Media.Media3D.Vector3D globalRotation = System.Windows.Media.Media3D.Vector3D.Multiply(localRotation, transformationMatrix);
BEMs bem = new BEMs(time, distanceFromI,
Math.Round(double.Parse(parts[3], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[4], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[5], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[6], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[7], CultureInfo.InvariantCulture), 10),
Math.Round(double.Parse(parts[8], CultureInfo.InvariantCulture), 10),
globalDeflection.X, globalDeflection.Y, globalDeflection.Z,
globalRotation.X, globalRotation.Y, globalRotation.Z
);
beam.BEMs.Add(bem);
}
}
}
}
}
然后,在我的 VB.Net 桌面应用程序中,我尝试按如下方式绘制梁拉伸:
Function ExtrudeElements(ByVal bm As oofem_projlib.Beam3D) As Mesh
Dim startPoint = projoofem.FindNodeById(bm.Node1).ToPoint3D()
Dim endPoint = projoofem.FindNodeById(bm.Node2).ToPoint3D()
' Use the stored local X-axis direction vector
Dim beamXDirection As Vector3D = bm.LocalXDirection
beamXDirection.Normalize()
' Get the profile points
Dim profilePoints = bm.CrossSection.ToPoint3D(0)
' Create the LinearPath and Region using the profile points
Dim profileLp As New LinearPath(profilePoints)
Dim profileRegion As New Region(profileLp)
' Determine the Rotation to Align the Profile's Z-axis with the Beam's Direction
Dim rotationAxis As Vector3D = CrossProduct(Vector3D.AxisZ, beamXDirection)
Dim angleInRadians As Double = Math.Acos(DotProduct(Vector3D.AxisZ, beamXDirection))
' Create the Rotation Transformation
Dim rotationTrans As New Transformation()
rotationTrans.Rotation(angleInRadians, rotationAxis)
profileRegion.TransformBy(rotationTrans)
' Translate the profile to the start point of the beam
Dim translation As New Transformation()
translation.Translation(startPoint.X, startPoint.Y, startPoint.Z)
profileRegion.TransformBy(translation)
' Use the stored local X-axis for the Extrusion Direction
Dim extrusionDirection As Vector3D = beamXDirection
extrusionDirection.Normalize()
' Determine the Extrusion Magnitude
Dim extrusionMagnitude As Double = startPoint.DistanceTo(endPoint)
' Extrude the Profile
Dim extrudedMesh = profileRegion.ExtrudeAsMesh(extrusionMagnitude * extrusionDirection, 0.1, Mesh.natureType.MulticolorSmooth)
Return extrudedMesh
End Function
这在大多数情况下是有效的,但由于某种原因,某些光束围绕局部 X 轴旋转了 90 度。
然后,当我尝试绘制偏转的形状时(每个梁有 5 组节点 - 起点 + 3 个内部 + 终点),事情就有点不对劲了。此代码片段为:
For Each ele In projoofem.Elements
If ele.ElementType = oofem_projlib.ElementType.Beam3D Then
Dim bm As oofem_projlib.Beam3D = ele
Dim bmP1 As Point3D = projoofem.FindNodeById(bm.Node1).ToPoint3D()
Dim bmP2 As Point3D = projoofem.FindNodeById(bm.Node2).ToPoint3D()
Dim lstbmPoints As New List(Of Point3D)
For i = 0 To projoofem.nrBeamSegments
Dim tpt = GetIntermediatePoint(bmP1, bmP2, bm.BEMs(i).DistanceFromI)
' Use the global deflection values directly
Dim xDefl = tpt.X + bm.BEMs(i).D_x * xfrm.tbAmplify.Value
Dim yDefl = tpt.Y + bm.BEMs(i).D_y * xfrm.tbAmplify.Value
Dim zDefl = tpt.Z + bm.BEMs(i).D_z * xfrm.tbAmplify.Value
''Incorporate rotations(considering small angle approximation)
'xDefl += bm.BEMs(i).R_z * yDefl - bm.BEMs(i).R_y * zDefl
'yDefl += bm.BEMs(i).R_x * zDefl - bm.BEMs(i).R_z * xDefl
'zDefl += bm.BEMs(i).R_y * xDefl - bm.BEMs(i).R_x * yDefl
lstbmPoints.Add(New Point3D(xDefl, yDefl, zDefl))
Next
End If
Next
有些偏转被正确绘制,而另一些则没有。我确定问题出在我的坐标系变换上,但我无法弄清楚我做错了什么。我花了无数个小时试图解决这个问题。请帮忙!
答: 暂无答案
上一个:RDLC 比例图像对齐
评论