三点构面
空间三点任意两点构成两条向量(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)