You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

沿公共边e旋转面f以展开至同一平面的顶点r'坐标求解

嘿,这个把共享边的面展开到同一平面的问题我之前也碰到过,核心就是把3D里的旋转拆解成坐标系变换+轴旋转,一步步来其实不难,我给你梳理下具体步骤:

绕共享边展开面的坐标计算方案

首先先明确几个关键的已知点:

  • 共享边e的两个端点记为AB(对应全局坐标分别为$(x_A,y_A,z_A)$和$(x_B,y_B,z_B)$)
  • 面f中不属于e的目标顶点是r(全局坐标$(x_r,y_r,z_r)$)
  • 面f'是我们要对齐的参考面,最终要让f和f'共面

步骤1:搭建局部坐标系

咱们先把共享边AB当作局部坐标系的X轴,然后在f'平面内构建垂直于AB的Y轴,最后通过叉乘得到Z轴(垂直于f'平面):

  1. 先算出AB方向的单位向量$\vec{u}$:
    vec_AB = B - A  // 向量减法,对应坐标分量相减
    u = vec_AB / ||vec_AB||  // 除以向量模长得到单位向量
    
  2. 找面f'里一个不在AB上的点C(比如f'的另一个顶点),算出向量$\vec{AC}$,再通过两次叉乘得到f'平面内垂直于AB的单位向量$\vec{v}$:
    vec_AC = C - A
    temp_vec = cross(vec_AB, vec_AC)  // 得到垂直于f'平面的向量
    v = cross(temp_vec, u)  // 确保v在f'平面内且和u垂直
    v = v / ||v||
    
  3. 最后叉乘u和v得到Z轴的单位向量$\vec{w}$:
    w = cross(u, v)
    
    这个局部坐标系的原点就是A点,X轴沿AB方向,Y轴在f'平面内,Z轴垂直于f'平面。

步骤2:把顶点r转到局部坐标系

把全局坐标下的r转换成局部坐标系下的坐标$(x', y', z')$,其实就是求r相对于A点在三个轴上的投影:

vec_Ar = r - A
x' = dot(vec_Ar, u)  // 点积得到X轴分量
y' = dot(vec_Ar, v)  // Y轴分量
z' = dot(vec_Ar, w)  // Z轴分量,这个值就是r相对于f'平面的"高度"

步骤3:计算需要旋转的角度θ

要让f和f'共面,旋转角度就是两个面的法向量之间的夹角。咱们这么算:

  1. 先算面f的法向量$\vec{n_f}$:用AB和Ar叉乘得到
    n_f = cross(vec_AB, vec_Ar)
    n_f = n_f / ||n_f||  // 单位化
    
  2. 再算面f'的法向量$\vec{n_{f'}}$:用AB和AC叉乘得到
    n_f' = cross(vec_AB, vec_AC)
    n_f' = n_f' / ||n_f'||
    
  3. 最后通过点积和叉乘算出夹角θ:
    cosθ = dot(n_f, n_f')  // 余弦值
    sinθ = dot(cross(n_f, n_f'), u)  // 正弦值,同时能确定旋转方向
    θ = atan2(sinθ, cosθ)  // 得到带方向的角度
    

步骤4:在局部坐标系里执行旋转

因为咱们是绕X轴(也就是AB边)旋转,对应的旋转矩阵是:

[1   0      0     ]
[0 cosθ -sinθ]
[0 sinθ  cosθ]

把r的局部坐标$(x', y', z')$乘以这个矩阵,得到旋转后的局部坐标$(x'', y'', z'')$:

x'' = x'  // X轴方向不变,因为绕X轴转
y'' = y' * cosθ - z' * sinθ
z'' = y' * sinθ + z' * cosθ

这里旋转后z''理论上应该接近0(因为要转到f'平面),可以用这个来验证计算是否正确。

步骤5:把坐标转回到全局坐标系

最后用咱们搭建的局部坐标系,把旋转后的局部坐标转成全局坐标r':

r' = A + x''*u + y''*v + z''*w

一些小提醒

  • 叉乘的顺序很重要,会影响法向量的方向,进而决定旋转角度的正负,要是结果不对可以试试调换叉乘的顺序
  • 如果是2D场景的话,问题会简单很多,直接算两个面的夹角,绕AB旋转就行,不用搞3D坐标系变换
  • 提前预计算所有单位向量,能减少重复计算模长的工作量,效率更高

内容的提问来源于stack exchange,提问作者T4g1

火山引擎 最新活动