点到平面的垂直向量

博客介绍了如何通过三个空间点确定一个平面的方程,并计算原点到该平面上的点的投影。通过具体的数学公式和Python代码展示了计算过程,包括点面投影的坐标公式以及垂直向量的获取。最后,利用matplotlib绘制了相关图形进行验证。
摘要由CSDN通过智能技术生成

三点构面

空间三点任意两点构成两条向量(x2-x1, y2-y1, z2-z1)和(x3-x1, y3-y1, z3-z1)存在三点构成平面的法向量n与这两向量垂直。

由三点: p1(x1, y1, z1) p2(x2, y2, z2) p3(x3, y3, z3)

求平面方程: Ax + By + Cz + D = 0

解向量n并带入点:

A = (Y2*Z3 - Y2*Z1 - Y1*Z3 - Y3*Z2 + Y1*Z2 + Y3*Z1)

B = (X3*Z2 - X1*Z2 - X3*Z1 - X2*Z3 + X2*Z1 + X1*Z3) 

C = (X2*Y3 - X2*Y1 - X1*Y3 - X3*Y2 + X3*Y1 + X1*Y2)

D = X1*Y3*Z2 + X2*Y1*Z3 + X3*Y2*Z1 - X1*Y2*Z3 - X3*Y1*Z2 - X2*Y3*Z1

# 平面点
x1, y1, z1 = [1, 0, 0]
x2, y2, z2 = [0, 1, 0]
x3, y3, z3 = [0, 0, 1]

# 平面方程
A = y2*z3 - y2*z1 - y1*z3 - y3*z2 + y1*z2 + y3*z1
B = x3*z2 - x1*z2 - x3*z1 - x2*z3 + x2*z1 + x1*z3
C = x2*y3 - x2*y1 - x1*y3 - x3*y2 + x3*y1 + x1*y2
D = x1*y3*z2 + x2*y1*z3 + x3*y2*z1 - x1*y2*z3 - x3*y1*z2 - x2*y3*z1

 

 

点面投影

由点 P(x, y, z)

平面方程: Ax + By + Cz + D = 0

求投影点:P_pro(x_pro, y_pro, z_pro)

解得:

x_pro = ((B**2 + C**2)*x - A*(B*y + C*z +D))/(A**2 + B**2 +C**2)

y_pro = ((A**2 + C**2)*y - B*(A*x + C*z +D))/(A**2 + B**2 +C**2)

z_pro = ((A**2 + B**2)*z - C*(A*x + B*y +D))/(A**2 + B**2 +C**2)

# 原点
x, y, z = [1, 1, 1]

# 投影点
xp = ((B ** 2 + C ** 2) * x - A * (B * y + C * z + D)) / (A ** 2 + B ** 2 + C ** 2)
yp = ((A ** 2 + C ** 2) * y - B * (A * x + C * z + D)) / (A ** 2 + B ** 2 + C ** 2)
zp = ((A ** 2 + B ** 2) * z - C * (A * x + B * y + D)) / (A ** 2 + B ** 2 + C ** 2)

 

两点向量

垂直向量n_ver = 投影点P_pro - 原点P = (x_pro, y_pro, z_pro)- (x, y, z)

# 垂直向量
n_ver = [xp - x, yp - y, zp - z]

 

完整代码

import matplotlib.pyplot as plt
import numpy as np

# 原点
x, y, z = [1, 1, 1]
# 平面点
x1, y1, z1 = [1, 0, 0]
x2, y2, z2 = [0, 1, 0]
x3, y3, z3 = [0, 0, 1]

# 平面方程
A = y2*z3 - y2*z1 - y1*z3 - y3*z2 + y1*z2 + y3*z1
B = x3*z2 - x1*z2 - x3*z1 - x2*z3 + x2*z1 + x1*z3
C = x2*y3 - x2*y1 - x1*y3 - x3*y2 + x3*y1 + x1*y2
D = x1*y3*z2 + x2*y1*z3 + x3*y2*z1 - x1*y2*z3 - x3*y1*z2 - x2*y3*z1

A, B, C, D = -A, -B, -C, -D
print('%fx + %fy + %fz + %f = 0'%(A,B,C,D))


# 投影点
xp = ((B ** 2 + C ** 2) * x - A * (B * y + C * z + D)) / (A ** 2 + B ** 2 + C ** 2)
yp = ((A ** 2 + C ** 2) * y - B * (A * x + C * z + D)) / (A ** 2 + B ** 2 + C ** 2)
zp = ((A ** 2 + B ** 2) * z - C * (A * x + B * y + D)) / (A ** 2 + B ** 2 + C ** 2)

# 垂直向量
n_ver = [xp - x, yp - y, zp - z]
print(n_ver)

fig1 = plt.figure()
ax1 = fig1.add_subplot(111, projection='3d')
ax1.set_xlabel("x")
ax1.set_ylabel("y")
ax1.set_zlabel("z")
ax1.scatter(x, y, z, c='y', marker='.')
ax1.scatter(x1,y1,z1, c='r', marker='*')
ax1.scatter(x2,y2,z2, c='r', marker='*')
ax1.scatter(x3,y3,z3, c='r', marker='*')
ax1.scatter(xp,yp,zp, c='b', marker='*')

x_p = np.linspace(0,1, 100)
y_p = np.linspace(0,1, 100)
x_p, y_p = np.meshgrid(x_p, y_p)
z_p =(A * x_p + B * y_p + D)/(-C)
ax1.plot_wireframe(x_p, y_p, z_p, rstride=10, cstride=10)
plt.show()

 图中描述的点:红三点确定平面,黄点原点,蓝点投影点。

看起来投影点好像不是垂直的,但是在坐标上描出蓝点坐标为(0.33,0.33,0.33)是符合垂直投影结果的,其中垂直向量应该为p蓝 - p黄 =(-0.66,-0.66,-0.66)

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
计算点到平面垂直距离可以通过以下步骤实现: 1. 根据给定平面上的三个,计算出平面的法向量,可以使用向量积的方法:将平面上的两个向量进行叉乘。 2. 将平面上的任意一连接成一个向量,计算该向量在法向量方向上的投影。 3. 将该向量减去上一步计算的投影向量,得到点到平面垂直向量。 4. 计算垂直向量的长度,即为点到平面垂直距离。 具体的实现代码如下: function computeDistance(point, plane){ //计算平面的法向量 var v1 = subtractVectors(plane[1], plane[0]); var v2 = subtractVectors(plane[2], plane[0]); var normal = crossProduct(v1, v2); //将平面上的任意一连接成一个向量 var vector = subtractVectors(point, plane[0]); //计算投影向量 var projection = projectVector(vector, normal); //计算垂直向量 var perpendicular = subtractVectors(vector, projection); //计算垂直向量长度 var distance = vectorLength(perpendicular); return distance; } //向量减法 function subtractVectors(v1, v2){ return [v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2]]; } //向量叉乘 function crossProduct(v1, v2){ return [v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1]-v1[1]*v2[0]]; } //向量乘 function dotProduct(v1, v2){ return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } //向量长度 function vectorLength(v){ return Math.sqrt(dotProduct(v, v)); } //向量投影 function projectVector(v, axis){ var length = dotProduct(v, axis) / dotProduct(axis, axis); return [axis[0]*length, axis[1]*length, axis[2]*length]; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

K.K. Salamander

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值