如何从透视投影的3D平面获取点的归一化坐标?
计算点投影到矩形平面的归一化坐标
核心思路
通过构建矩形平面的局部坐标系,将点C投影到平面后转换到该局部坐标系,即可得到符合要求的归一化(u, v)坐标:
- 以P2为局部坐标系原点,P2→P1为u轴方向,P2→P3为v轴方向
- 计算点C到矩形平面的投影点C_proj
- 将C_proj相对于P2的向量,分别在u轴和v轴上投影并归一化,得到最终坐标
数学推导
定义基础向量
- u轴方向向量:
u_axis = P1 - P2 - v轴方向向量:
v_axis = P3 - P2 - 平面法向量:
n = u_axis × v_axis(叉乘运算)
- u轴方向向量:
计算投影点C_proj
利用点到平面的投影公式:t = (n · (C - P2)) / (n · n) C_proj = C - t * n其中
t是点C到平面的垂直距离与法向量模长的比值。计算归一化坐标(u, v)
计算投影点相对于P2的向量:vec = C_proj - P2- u值:
u = (vec · u_axis) / (u_axis · u_axis)(点积除以u轴向量的模长平方实现归一化) - v值:
v = (vec · v_axis) / (v_axis · v_axis)
- u值:
Python实现
纯Python实现(无第三方依赖)
def compute_normalized_coords(P1, P2, P3, C): # 向量运算辅助函数 def subtract(a, b): return (a[0]-b[0], a[1]-b[1], a[2]-b[2]) def dot(a, b): return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] def cross(a, b): return ( a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0] ) def multiply_scalar(vec, scalar): return (vec[0]*scalar, vec[1]*scalar, vec[2]*scalar) # 计算基础向量 u_axis = subtract(P1, P2) v_axis = subtract(P3, P2) n = cross(u_axis, v_axis) # 计算投影点C_proj C_minus_P2 = subtract(C, P2) t = dot(n, C_minus_P2) / dot(n, n) t_n = multiply_scalar(n, t) C_proj = subtract(C, t_n) # 计算归一化坐标 vec = subtract(C_proj, P2) u = dot(vec, u_axis) / dot(u_axis, u_axis) v = dot(vec, v_axis) / dot(v_axis, v_axis) return (u, v)
numpy简化实现
import numpy as np def compute_normalized_coords_np(P1, P2, P3, C): # 转换为numpy数组 P1 = np.array(P1) P2 = np.array(P2) P3 = np.array(P3) C = np.array(C) # 计算基础向量 u_axis = P1 - P2 v_axis = P3 - P2 n = np.cross(u_axis, v_axis) # 计算投影点C_proj C_minus_P2 = C - P2 t = np.dot(n, C_minus_P2) / np.dot(n, n) C_proj = C - t * n # 计算归一化坐标 vec = C_proj - P2 u = np.dot(vec, u_axis) / np.dot(u_axis, u_axis) v = np.dot(vec, v_axis) / np.dot(v_axis, v_axis) return (u, v)
验证示例
- 输入P2时,返回
(0.0, 0.0) - 输入P1时,返回
(1.0, 0.0) - 输入P3时,返回
(0.0, 1.0) - 输入P4(即
P2 + (P1-P2) + (P3-P2))时,返回(1.0, 1.0)
内容的提问来源于stack exchange,提问作者Rui Batista
相关产品推荐
相关产品推荐

