我正在尝试将不规则曲面拟合到具有各自法线的三个点。该表面必须垂直于每条法线。 我能得到的最接近的是通过以下:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import Rbf
from scipy.optimize import minimize
# Data
#positions
A = np.array([1054.74352286, -1439.33862908, -1.50677694])
W = np.array([895.76063743, 61.69720144, -7.4430564])
B = np.array([869.90944818, 6.61926443, 5.88590894])
positions = np.vstack([A, W, B])
# normals
N_A = np.array([0.86465823, -0.02097322, 0.50192258])
N_W = np.array([0.82339849, -0.43041935, -0.3698028])
N_B = np.array([0.8991198, -0.14663834, -0.41240851])
normals = np.vstack([N_A, N_W, N_B])
def objective_function(points, positions, normals, w=1000):
points = points.reshape(-1, 3)
rbf = Rbf(*points.T, function='multiquadric')
def rbf_gradient(pos_2d, delta=1e-6):
x, y = pos_2d
grad_x = (rbf(x + delta, y) - rbf(x - delta, y)) / (2 * delta)
grad_y = (rbf(x, y + delta) - rbf(x, y - delta)) / (2 * delta)
return grad_x, grad_y
error = 0
for pos, normal in zip(positions, normals):
pos_2d = np.array([pos[0], pos[1]])
interpolated_grads = rbf_gradient(pos_2d)
interpolated_normal = np.array([interpolated_grads[0], interpolated_grads[1], -1])
interpolated_normal /= np.linalg.norm(interpolated_normal)
error += w * (1 - np.dot(interpolated_normal, normal)) ** 2
return error
result = minimize(objective_function, positions, args=(positions, normals, 10000), method='L-BFGS-B')
# Compute the surface using RBF interpolation
points = result.x.reshape(-1, 3)
rbf = Rbf(*points.T, function='multiquadric')
# Create a grid and evaluate the surface
X, Y = np.meshgrid(np.linspace(800, 1100, 100), np.linspace(-1500, 100, 100))
Z = rbf(X, Y)
# Plot the surface and normals
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, alpha=0.5, color='b', label='Interpolated Surface')
for pos, normal in zip(positions, normals):
ax.scatter(*pos, color='r', marker='o', s=50)
ax.quiver(pos[0], pos[1], pos[2], *normal, color='r', length=50, normalize=True)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Interpolated Surface and Normals')
` plt.show()
结果看起来像这样。问题是垂直度不好。我想要一个可以垂直于每个法线的表面。
我的问题是这种方法是否正确,还有其他建议适合的方法或如何增加垂直度吗?