I have a bunch of points in 3d space (x,y and z) and want to find their perpendicular projection on a surface in python. My surface is created by four points using the following function:
PRECISION = 1e-8 # Arbitrary zero for real-world purposes
def plane_from_points(points):
centroid = np.mean(points, axis=0)
_, eigenvalues, eigenvectors = np.linalg.svd(points - centroid)
if eigenvalues[1] < PRECISION:
raise ValueError("Points are aligned, can't define a plane")
normal = eigenvectors[2]
d = -np.dot(centroid, normal)
plane = np.append(normal, d)
thickness = eigenvalues[2]
return plane, thickness
These are my input points stored as list for creating the surface:
surface_maker=[np.array([[44., 5., 25.],
[44., 25., 25.],
[59., 5., 75.],
[59., 25., 75.]])]
I want to ind the perpedicular projection of the following points in the created surface:
projection_point=[np.array([[49.9, 5., 65.],
[48., 17., 69.],
[47., 25., 71.9],
[60., 5., 39.],
[55., 15., 42.1],
[57., 25., 40.1]])]
I tried the following code to do so, but it is giving me the horizontal projection while i want to find the perpendilar projection:
pls=[]
for i in surface_maker:
i=i.tolist()
pl, thickness= plane_from_points(i)
pls.append(pl)
point_on_surf=[]
n_iter=1
for i in range (n_iter):
a, b, c, d = pls[i][0], pls[i][1], pls[i][2], pls[i][3]
def fun(row):
row[0] = -(d + b * row[1] + c * row[2]) / a # calculates new x
return row[0], row[1], row[2] # new x and old y and z
to_be_projected=[copy.copy(projection_point[i])]
new_points = np.asarray(list(map(fun, [x for point in to_be_projected for x in point])))
point_on_surf.append(new_points)
In fig I visualized what I want. I just used different colurs for points to make the figure more readable. For the upper thre point I showed arrows to visualize the projection. My code is giving me the points which are at the end of red arrows but I want to find the projection point that are perpendicular to the surface. In fact, my code is only calculating a new x for the projection_point
. In the fig green arrows show the direction I want. I want to do so for all the points existing in projection_point
.
In advance, I do appreciate any help.