在我的电子表格中,云在这种格式的某个坐标系中有一堆点:
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°转换:
总结原点(0,0,0)将位于中点(PT1-PT2)。新的X轴将是向量中点(PT1-PT2)到中点(PT3-PT4)。 Y轴将包含在平面中并垂直于X.Z将垂直于X和Y.
目前我能够找到平面的方程,以及X,Y,Z轴。
我的问题是如何基于这些参数构建转换矩阵并使用excel公式实现它。
谢谢。
答案 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次旋转的组合。 例如
总旋转为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)
看一下这段代码,它允许在按行排列的一系列点上进行旋转。
首先是三个函数,它们采用一组值并对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 - 输入作为数组函数输入
因此,对于ZYX
的欧拉旋转,需要输入以下内容
=RotPointsX(
RotPointsY(
RotPointsZ(
AsArray(<range>),
angle_z),
angle_y),
angle_x)
反向旋转是负角度的XYZ
旋转
=RotPointsZ(
RotPointsY(
RotPointsX(
AsArray(<range>),
-angle_x),
-angle_y),
-angle_z)
我已通过恢复原始点验证了这一点