RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1564847
Accepted
artem_tmm
artem_tmm
Asked:2024-02-05 18:11:07 +0000 UTC2024-02-05 18:11:07 +0000 UTC 2024-02-05 18:11:07 +0000 UTC

在空间中旋转线段

  • 772

输入是空间中的一些随机线段,其两端的坐标为 p1(x1,y1,z1) 和 p2(x2,y2,z2)。

任务如下 - 有必要对其坐标进行此类转换,使其严格垂直,同时保持其长度。图片中的演示(绿色 - 原始,蓝色 - 旋转)。

在此输入图像描述

  1. 这个想法是取原始线段上的任意点(用 A1 表示),并添加第二个点 (A2),该点比点 A1 高出原始线段的长度。但这是行不通的,因为我们应用于该段以旋转它的变换将应用于其他 3D 对象。

  2. 还有一个想法是计算线段与所有轴(x、y、z)之间的角度,然后将线段的所有坐标依次乘以沿所有轴的旋转矩阵。但执行此操作后的新段并没有达到预期(看起来不直)。

这里我将坐标依次乘以这3个矩阵在此输入图像描述

预先知道角度 alpha、beta、gamma 为 45 度,可以检查角度是否取正确,图中(绿色部分),例如坐标为 p1(0,0,0) p2(1 ,1,1) 被取

尝试实现获取旋转矩阵的算法:

import numpy as np

# нормализовать вектор (привести к единичной длине)
def normalize_vector(vector):
    norm_v = np.linalg.norm(vector)
    if norm_v != 0:
        return vector / norm_v
    else:
        return vector

# Исходные данные задачи (2 конца отрезка)
x = np.array([0,0,0])
y = np.array([1,1,1])

#нормализуем вектора
x = normalize_vector(x)
y = normalize_vector(y)

# необходимые вектора для решения задачи
s = np.array([y[0] - x[0],y[1] - x[1],y[2] - x[2]])
t = np.array([0,1,0])
a = np.cross(s,t)

#нормализуем вектора
s = normalize_vector(s)
t = normalize_vector(t)
a = normalize_vector(a)

# матрицы
S = np.array([s, a, np.cross(s,a)])
T = np.array([t, a, np.cross(t,a)])

#транспонированная S
S_t = np.transpose(S)

# получаем решение задачи
solution = np.dot(S_t, T)

# тестируем, пробуем получить повернутый отрезок
x = np.array([[0,0,0]])
y = np.array([[1,1,1]])
x = np.dot(x, solution)
y = np.dot(y, solution)
x = np.round(x, decimals=2)
y = np.round(y, decimals=2)

print(x, y)
геометрия
  • 2 2 个回答
  • 91 Views

2 个回答

  • Voted
  1. MBo
    2024-02-05T18:46:37Z2024-02-05T18:46:37Z

    将平移矩阵应用到(-A1.x, -A1.y, -A1.z)
    原点处的 Now A1

    我们应用围绕 OZ 轴一定角度的旋转矩阵。f=atan2(A1.y-A2.y,A1.x-A2.x)
    现在向量位于 OXZ 平面中

    应用绕 OY 轴一定角度的旋转矩阵。t=acos((A1.z-A2.z)/Len(A)) 现在向量共线 OZ

    如有需要,请转回(A1.x, A1.y, A1.z)

    (检查角度标志,我可能犯了一个错误)

    • 1
  2. Best Answer
    Stanislav Volodarskiy
    2024-02-05T18:51:59Z2024-02-05T18:51:59Z

    所有向量进一步减少到单位长度。这很重要。

    我们引入向量s = (x 2 - x 1 , y 2 - y 1 , z 2 - z 1 )。

    向量t = (0, 1, 0)。矢量a = s × t - 矢量积(这将是旋转轴)。

    我们将根据向量组装两个矩阵: S = (s, a, s × a)和T = (t, a, t × a)。“让我们收集”意味着第一个向量成为矩阵的第一列,第二个向量成为第二列,第三个向量成为第三列。

    您需要的旋转矩阵是S -1 ·T。

    PS代数是在向量为行向量的假设下编写的,即向量乘以矩阵计算为v·M。如果向量是列向量,则矩阵的“组合”从列变为行,最后的乘积的形式为:T·S -1。

    PPS如果归一化前向量a的长度接近于零,则向量s已经几乎是垂直的。你不必标准化,你可以立即返回单位矩阵。

    PPPS解决此类问题的一般方法:为初始位置和最终位置提出两个正交基。从底创建两个矩阵。反转第一个并乘以第二个 - 您将得到基数之间的转换矩阵,这就是您所需要的。

    PPPPS问题可以通过多种方式解决,这种解决方案是周转最短的。

    PPPPS演示:

    import numpy as np
    
    
    def normalized(v):
        return v / np.linalg.norm(v)
    
    
    def get_rotation(x, y):
        s = normalized(y - x)
        t = np.array([0, 1, 0])
    
        a = np.cross(s, t)
        an = np.linalg.norm(a)
        if an == 0:
            return np.identity(3)
        a /= an
    
        sm = np.array([s, a, np.cross(s, a)])
        tm = np.array([t, a, np.cross(t, a)])
        return np.dot(np.transpose(sm), tm)
    
    
    def test(x, y):
        print()
        print('x', x)
        print('y', y)
    
        r = get_rotation(x, y)
        
        # чистый поворот, но он смещает x
        # xm = np.dot(x, r)
        # ym = np.dot(y, r)
    
        # поворот вокруг x, x остаётся на месте
        xm = x
        ym = x + np.dot(y - x, r)
    
        print('xm', xm)
        print('ym', ym)
        print('ym - xm', ym - xm)
        print('norm(y - x)', np.linalg.norm(y - x))
    
    
    test(np.array([0, 0, 0]), np.array([1, 1, 1]))
    for _ in range(5):
        test(np.random.random(3), np.random.random(3))
    
    $ python motion.py
    
    x [0 0 0]
    y [1 1 1]
    xm [0 0 0]
    ym [8.32667268e-17 1.73205081e+00 1.11022302e-16]
    ym - xm [8.32667268e-17 1.73205081e+00 1.11022302e-16]
    norm(y - x) 1.7320508075688772
    
    x [0.09054937 0.25113354 0.84059327]
    y [0.66784923 0.45813704 0.97364723]
    xm [0.09054937 0.25113354 0.84059327]
    ym [0.09054937 0.87869146 0.84059327]
    ym - xm [-1.38777878e-17  6.27557916e-01  0.00000000e+00]
    norm(y - x) 0.627557915509163
    
    x [0.45851044 0.61577351 0.9463866 ]
    y [0.79713568 0.81397556 0.91020798]
    xm [0.45851044 0.61577351 0.9463866 ]
    ym [0.45851044 1.00980396 0.9463866 ]
    ym - xm [0.         0.39403046 0.        ]
    norm(y - x) 0.3940304551397485
    
    x [0.19882745 0.59956245 0.47065679]
    y [0.94670724 0.47282411 0.67784346]
    xm [0.19882745 0.59956245 0.47065679]
    ym [0.19882745 1.38589132 0.47065679]
    ym - xm [0.         0.78632888 0.        ]
    norm(y - x) 0.7863288771527435
    
    x [0.70422901 0.08023806 0.26255832]
    y [0.63219791 0.35879577 0.96748029]
    xm [0.70422901 0.08023806 0.26255832]
    ym [0.70422901 0.84161698 0.26255832]
    ym - xm [0.         0.76137892 0.        ]
    norm(y - x) 0.7613789207408871
    
    x [0.73489304 0.54577026 0.95083131]
    y [0.82219623 0.42600696 0.34361226]
    xm [0.73489304 0.54577026 0.95083131]
    ym [0.73489304 1.17081432 0.95083131]
    ym - xm [0.         0.62504406 0.        ]
    norm(y - x) 0.6250440595015537
    
    • 1

相关问题

  • 一个点是否属于圆的某个部分 - 根据公式的问题

  • 检查是否可以通过 3 个向量绘制直线

  • 球体和三角形的交点

  • 平面到球体的几何变换?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5