坐标系转换和实施

Coordinate System Transformation and implementation

提问人:Chris Vorster 提问时间:10/5/2023 更新时间:10/5/2023 访问量:28

问:

我正在尝试从 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

有些偏转被正确绘制,而另一些则没有。我确定问题出在我的坐标系变换上,但我无法弄清楚我做错了什么。我花了无数个小时试图解决这个问题。请帮忙!

C# vb.net 3D 矢量图形

评论

0赞 jdweng 10/5/2023
看起来梁有多个部分,可能不是直的。您可能需要为每个线段创建一个新的直梁才能获得正确的结果。

答: 暂无答案