【问题标题】:Changing 3D coordinate system using Excel使用 Excel 更改 3D 坐标系
【发布时间】:2015-10-22 00:13:07
【问题描述】:

我的电子表格中有一个点云,位于某个坐标系中,云的格式如下: Name X Y Z PT1 X1 Y1 Z1 PT2 X2 Y2 Z2 PT3 X3 Y3 Z3 PT4 X4 Y4 Z4 ... PTi Xi Yi Zi ... 我想使用列表中的前四个点来构造一个新的坐标系,并将我的所有点转置到新的坐标系中。

必须将新坐标系定义为平面-线-点(或 3-2-1° 变换:

  1. 平面是 (PT1, PT2, PT3, PT4) 的最佳拟合平面。我知道如何使用 excel LINEST 公式构造平面方程
  2. 线/向量Midpoint(PT1-PT2)到Midpoint(PT3-PT4)线/向量很容易在excel中构造
  3. 点是中点(PT1-PT2)。

总结原点 (0,0,0) 将位于中点 (PT1-PT2)。新的 X 轴将是中点 (PT1-PT2) 到中点 (PT3-PT4) 的向量。 Y 轴将包含在平面内并垂直于 X。Z 将垂直于 X 和 Y。

目前我能够找到平面和 X、Y、Z 轴的方程。

我的问题是如何根据这些参数构造变换矩阵,并使用excel公式实现。

谢谢。

【问题讨论】:

    标签: excel 3d coordinate-systems coordinate-transformation


    【解决方案1】:

    我尝试将任务分为 5 个部分来回答。我将把 x,y,z 称为以 O 为中心的旧轴,将 X,Y,Z 称为以 P 为中心的新轴。

    第一次尝试将部分结果保存在空单元格中。我无法为您提供一个单一的公式,可以一步回答您的问题。

    a) 通用转换是旋转翻译。你在 P 点找到了你的新原点(你有坐标)。假设您的“旧原点”是 O = (0,0,0),我可以简单地说从旧原点到新原点的转换是 d = |P-O| = |P|两个系统中向量 P 的欧几里得范数,在 excel 中很容易计算(我不知道是否有函数,我会使用毕达哥拉斯定理)。有人尝试构建用户定义的宏here

    b) 现在您有了平移向量 (t1,t2,t3),您可以为旧轴设置新原点,而无需旋转它们。注意符号,不过是一个简单的翻译公式(见例子: 如果 x = x' + t1 则 x' = x - t1) 想想在你的情况下哪个是 x' 哪个是 x,试着用一个简单的点 (1,0,0) 看看你的选择是否合适。 翻译你所有的点(即:PT1_t,PT2_t...) 现在您在 xyz 和 XYZ 之间有了一个中间参考系统。我们称之为“pqr”

    c) 现在您的参考系统 pqr 和 XYZ 仅在旋转角度上有所不同。在构建旋转矩阵之前,您必须决定哪个轴首先旋转。 最好使用归一化向量(将每个向量划分为其范数) 假设 pqr 系统和 XYZ 的旋转是(最多)3 次围绕固定轴旋转的组合。 例如

    1. 您将围绕 Z 旋转 pqr 以将 versor p 置于 XZ 平面中。您将获得一个“新”pqr' 系统。这是通过 3x3 旋转矩阵 RX 完成的(我们还不知道)
    2. 您将使用 RY 围绕 Y 旋转 pqr' 以将 pqr' 与 X 对齐。你现在有 pqr''
    3. 您将使用围绕 X 的旋转和矩阵 RX 将 q 轴与 Y 对齐,将 r 轴与 Z 对齐。 pqr''' 与 XYZ 完全对齐

    总旋转为 R = RX * RY * RZ,一个矩阵乘积。如何找到旋转? (按照我的旋转顺序不是强制性的!您可以构建自己的顺序,但最著名的是 XYZ、ZYX 和 ZXZ)。

    d) 每个矩阵都需要一个角度。第一个角度是 p 与其在 XZ 平面中的投影之间的角度。第二个角度是 p' (= RZ * p) 和 X 之间的角度,第三个角度是 q'' ( = RY * q' = RY * RX * q) 和 Y 之间的角度。它必须相等(有错误)到 r'' 和 Z 之间的角度。 可以这样构建矩阵(如果 A 是通用角度)

    RX = [1   0      0
          0 cos(A) -sin(A)
          0 sin(A) cos(A)]
    

    检查 RY 和 RZ at this link 但请注意:正如我们之前所说,A 是一个方向的旋转角度,因此您可能需要 -A 进行旋转。一般来说(但要验证)A是从旧轴到新轴的角度,正A是逆时针方向。

    要计算角度 A,请使用简单的公式 exposed here。 Excel 具有您需要的所有测角公式(余弦、反余弦...)。

    e) 一旦你找到了三个矩阵 RX RY RZ 与旧 pqr 轴的旋转一起使用,你的新 XYZ 系统中的每个点 PTi' 都是从 PTi' = R * PTi_t 获得的。 您可以使用 MMULT excel 函数简单地构建矩阵产品 explained here

    抱歉,篇幅较长,但作为一个简单的学生,这是我所知道的唯一系统。 希望对你有帮助。

    【讨论】:

      【解决方案2】:

      通过Ctrl+Shift+Enter在下面的J6到L16中需要的命令将坐标重置为原始值

      =RotpointsZ(RotpointsY(RotpointsX(AsArray($F$6:$H$16),$K$1),$K$2),$K$3)

      如何编辑 VBA 代码以读取每个旋转行的不同 xyz 旋转,而不是像此处显示的那样绑定到一个旋转?

      26/04/18 Mr.Excel 上的 WORF 刚刚回答了我的问题,即为每个要旋转的点读取不同的 xyz 旋转。他的输入是将以下代码添加到现有代码中:

      Function Rot3D(ByVal rng1 As Range, ByVal rng2 As Range, ByVal rng3 As 
      Range, ByVal rng4 As Range)
      Rot3D = RotPointsX(RotPointsY(RotPointsZ(AsArray(rng1), rng2.Value), 
      rng3.Value), rng4.Value)
      End Function
      

      复制以下公式:

      =rot3d(b2:d2,h2,g2,f2)
      

      使用 ctrl+shift+enter 进入单元格 J2、K2、L2,然后向下复制。 B、C、D 列中 xyz 坐标的旋转将按照 F、G、H 列中的角度进行旋转,并在 J、K、L 列中输出

      我已使用剪切和粘贴将旋转角度放置在 F、G、H 列中。这当然会改变此处显示的原始工作表的布局。

      【讨论】:

        【解决方案3】:

        看看这段代码,它允许在按行排列的一系列点上进行旋转。

        首先是三个函数,它们接受一组值并应用关于 X、Y 或 Z 的相应旋转。

        Public Function RotPointsX(ByRef pts() As Variant, angle_rad As Double) As Variant()
            Dim n As Integer
            n = UBound(pts, 1)
            If UBound(pts, 2) <> 3 Then
                'Need Three Points
                Exit Function
            End If
            Dim tX As Double, tY As Double, tZ As Double
            Dim X As Double, Y As Double, Z As Double
        
            For i = 1 To n
                tX = pts(i, 1): tY = pts(i, 2): tZ = pts(i, 3)
                X = tX
                Y = tY * Cos(angle_rad) - tZ * Sin(angle_rad)
                Z = tY * Sin(angle_rad) + tZ * Cos(angle_rad)
                pts(i, 1) = X: pts(i, 2) = Y: pts(i, 3) = Z
            Next i
        
            RotPointsX = pts
        End Function
        Public Function RotPointsY(ByRef pts() As Variant, angle_rad As Double) As Variant()
            Dim n As Integer
            n = UBound(pts, 1)
            If UBound(pts, 2) <> 3 Then
                'Need Three Points
                Exit Function
            End If
            Dim tX As Double, tY As Double, tZ As Double
            Dim X As Double, Y As Double, Z As Double
        
            For i = 1 To n
                tX = pts(i, 1): tY = pts(i, 2): tZ = pts(i, 3)
                X = tZ * Sin(angle_rad) + tX * Cos(angle_rad)
                Y = tY
                Z = tZ * Cos(angle_rad) - tX * Sin(angle_rad)
                pts(i, 1) = X: pts(i, 2) = Y: pts(i, 3) = Z
            Next i
        
            RotPointsY = pts
        End Function
        Public Function RotPointsZ(ByRef pts() As Variant, angle_rad As Double) As Variant()
            Dim n As Integer
            n = UBound(pts, 1)
            If UBound(pts, 2) <> 3 Then
                'Need Three Points
                Exit Function
            End If
            Dim tX As Double, tY As Double, tZ As Double
            Dim X As Double, Y As Double, Z As Double
        
            For i = 1 To n
                tX = pts(i, 1): tY = pts(i, 2): tZ = pts(i, 3)
                X = tX * Cos(angle_rad) - tY * Sin(angle_rad)
                Y = tX * Sin(angle_rad) + tY * Cos(angle_rad)
                Z = tZ
                pts(i, 1) = X: pts(i, 2) = Y: pts(i, 3) = Z
            Next i
        
            RotPointsZ = pts
        End Function
        

        接下来我需要一个函数将范围转换为数组,以及使用此函数执行此操作的最简单方法:

        Public Function AsArray(ByVal r_pts As Range) As Variant()
            AsArray = r_pts.Value2
        End Function
        

        最后在我的工作表中,我将旋转作为嵌套函数并使用 Ctrl-Shift-Enter 作为数组函数输入

        所以对于ZYX 的欧拉旋转,需要以下输入

        =RotPointsX(
             RotPointsY(
                 RotPointsZ(
                     AsArray(<range>),
                 angle_z),
             angle_y), 
         angle_x)
        

        反向旋转是XYZ的负角旋转

        =RotPointsZ(
             RotPointsY(
                 RotPointsX(
                     AsArray(<range>),
                 -angle_x),
             -angle_y), 
         -angle_z)
        

        我已经通过还原原始点验证了这一点

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-29
          • 1970-01-01
          • 1970-01-01
          • 2011-03-10
          • 2011-05-10
          相关资源
          最近更新 更多