You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过欧氏变换对齐超平面并转换数据点坐标系

3D超平面对齐与数据坐标转换实现

核心思路

欧氏变换仅包含旋转和平移操作,能保持点间距离与角度不变,恰好满足将第二个平面对齐到第一个平面坐标系的需求。实现分为两步:

  1. 旋转:让两个平面的法向量方向完全一致
  2. 平移:让两个平面的位置重合

具体步骤与代码实现

1. 提取并归一化平面法向量

平面方程 ax+by+cz+d=0 的法向量为 (a,b,c),先对两个法向量做归一化处理:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 给定的两个平面参数
plane1 = np.array([-5.297742252442251, 21.751836101364013, -2.470896764133499, -0.5601826186620921])
plane2 = np.array([45.42557999642176, -16.9433283673388, 2.5117971500097287, -8.528560240570203])

# 提取法向量并归一化
n1 = plane1[:3] / np.linalg.norm(plane1[:3])
n2 = plane2[:3] / np.linalg.norm(plane2[:3])

2. 计算旋转矩阵

通过Rodrigues旋转公式计算将法向量n2旋转到n1的旋转矩阵:

def rodrigues_rotation(n_from, n_to):
    # 计算旋转轴(叉乘)
    axis = np.cross(n_from, n_to)
    axis_norm = np.linalg.norm(axis)
    if axis_norm < 1e-8:
        # 法向量方向相同或相反
        if np.dot(n_from, n_to) > 0:
            return np.eye(3)
        else:
            # 构造180度旋转矩阵
            if abs(n_from[0]) > abs(n_from[1]):
                ortho = np.array([-n_from[2], 0, n_from[0]])
            else:
                ortho = np.array([0, -n_from[2], n_from[1]])
            ortho = ortho / np.linalg.norm(ortho)
            return np.eye(3) - 2 * np.outer(ortho, ortho)
    axis = axis / axis_norm
    # 计算旋转角度(点乘)
    angle = np.arccos(np.clip(np.dot(n_from, n_to), -1, 1))
    # 构造Rodrigues矩阵
    K = np.array([[0, -axis[2], axis[1]],
                  [axis[2], 0, -axis[0]],
                  [-axis[1], axis[0], 0]])
    R = np.eye(3) + np.sin(angle)*K + (1 - np.cos(angle))*np.dot(K, K)
    return R

# 生成旋转矩阵
R = rodrigues_rotation(n2, n1)

3. 计算平移向量

以原点到平面的垂足为对应点,计算平移量让第二个平面的垂足移到第一个平面的垂足:

# 计算原点到平面的垂足
def plane_foot_point(plane):
    a, b, c, d = plane
    denom = a**2 + b**2 + c**2
    return np.array([-a*d, -b*d, -c*d]) / denom

p1 = plane_foot_point(plane1)
p2 = plane_foot_point(plane2)

# 平移向量:将旋转后的p2移到p1
t = p1 - np.dot(R, p2)

4. 转换data2的所有数据点

对data2的每个点 x 应用变换:x' = R @ x + t

# 假设data2是N×3的numpy数组,示例用模拟数据
np.random.seed(42)
data2 = np.random.randn(100, 3)
# 应用欧氏变换
data2_transformed = np.dot(data2, R.T) + t

5. 绘制对齐后的3D图

绘制原始平面1、对齐后的平面2,以及data1、转换后的data2:

# 生成平面网格点
xx, yy = np.meshgrid(np.linspace(-5,5,20), np.linspace(-5,5,20))

# 平面1的z坐标
z1 = (-plane1[0]*xx - plane1[1]*yy - plane1[3]) / plane1[2]
# 对齐后平面2的z坐标(基于法向量n1和垂足p1推导)
z2_aligned = (-n1[0]*xx - n1[1]*yy - (-np.dot(n1, p1))) / n1[2]

# 创建3D图
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')

# 绘制平面
ax.plot_surface(xx, yy, z1, alpha=0.3, label='Plane 1')
ax.plot_surface(xx, yy, z2_aligned, alpha=0.3, label='Aligned Plane 2', color='orange')

# 绘制数据点(示例用模拟data1)
data1 = np.random.randn(100,3)
ax.scatter(data1[:,0], data1[:,1], data1[:,2], color='blue', label='Data 1')
ax.scatter(data2_transformed[:,0], data2_transformed[:,1], data2_transformed[:,2], color='red', label='Transformed Data 2')

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.legend()
plt.show()

关键注意事项

  • 归一化法向量是计算旋转矩阵的前提,避免因法向量长度差异导致旋转错误
  • 欧氏变换必须先旋转,再平移,顺序不可颠倒
  • 平面平移后需重新推导方程,确保绘制的对齐平面与转换后的数据点匹配

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 18:01:29