使用Excel

时间:2015-10-22 00:13:08

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

在我的电子表格中,云在这种格式的某个坐标系中有一堆点: 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. 线/矢量中点(PT1-PT2)到中点(PT3-PT4)线/矢量很容易在excel中构建
  3. 点是中点(PT1-PT2)。
  4. 总结原点(0,0,0)将位于中点(PT1-PT2)。新的X轴将是向量中点(PT1-PT2)到中点(PT3-PT4)。 Y轴将包含在平面中并垂直于X.Z将垂直于X和Y.

    目前我能够找到平面的方程,以及X,Y,Z轴。

    我的问题是如何基于这些参数构建转换矩阵并使用excel公式实现它。

    谢谢。

3 个答案:

答案 0 :(得分: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 e XYZ之间有一个中间参考系统。我们称之为" pqr"

c)现在您的参考系统pqr和XYZ仅在旋转角度上有所不同。在构建旋转矩阵之前,您必须先决定旋转哪个轴。 最好使用标准化向量(将每个向量除以其范数) 让我们说来自pqr系统和XYZ的旋转是围绕固定轴(最多)3次旋转的组合。 例如

  1. 您将围绕Z旋转pqr以将p或p放在XZ平面中。你将获得一个新的" PQR'系统。这是通过3x3旋转矩阵RX完成的(我们还不知道)
  2. 你将旋转pqr'在Y附近对齐p'使用RY来对应X.你现在有了pqr''
  3. 您将使用围绕X和矩阵RX的旋转将q轴与Y对齐,将r轴与Z对齐。 PQR'''与XYZ完全对齐
  4. 总旋转为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轴的旋转,每个点PTi'在您的新XYZ系统中,从PTi' = R * PTi_t。 您可以使用MMULT excel函数简单地构建矩阵产品 explained here

    对不起,这是我认识的唯一一个简单的学生系统。 我希望它可以帮助你。

答案 1 :(得分:1)

下面J6到L16所需的命令通过 Ctrl + Shift + 输入将coords重置为原始值

= RotpointsZ(RotpointsY(RotpointsX(AsArray($ F $ 6:$ H $ 16),$ķ$ 1),$ $ķ2),$ $ķ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)

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

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

答案 2 :(得分:0)

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

scr

首先是三个函数,它们采用一组值并对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 - 输入作为数组函数输入

scr

因此,对于ZYX的欧拉旋转,需要输入以下内容

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

反向旋转是负角度的XYZ旋转

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

我已通过恢复原始点验证了这一点

scr