sort points

Jan 7th, 2022 (edited)
948
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. def sort_points(pts):
2.     centroid = np.sum(pts, axis=0) / pts.shape[0]
3.     vector_from_centroid = pts - centroid
4.     vector_angle = np.arctan2(
5.         vector_from_centroid[:, 1], vector_from_centroid[:, 0])
6.     # Find the indices that give a sorted vector_angle array
7.     sort_order = np.argsort(vector_angle)
8.
9.     # Apply sort_order to original pts array.
10.     return pts[sort_order, :]
11.
12. # selected_verts are the points that the user selects...
13.
14. view_mat = bpy.context.region_data.view_matrix
15. # Project points onto 2D plane
16. corners = np.array(
17.     [view_mat @ p for p in selected_verts])
18. plane_normal = np.cross(
19.     corners[1, :] - corners[0, :], corners[2, :] - corners[0, :])
20. plane_normal = plane_normal / np.linalg.norm(plane_normal)
21.
22. new_origin = corners[0, :]
23. new_x = corners[1, :] - corners[0, :]
24. new_x = new_x / np.linalg.norm(new_x)
25.
26. new_y = np.cross(plane_normal, new_x)
27.
28. # Maps the indices of the original 3d points to the projected 2d points
29. corners2dmap = {}
30. for index, corner in enumerate(corners):
31.     proj_x = Vector.dot(
32.         Vector(corner) - Vector(new_origin), Vector(new_x))
33.     proj_y = Vector.dot(
34.         Vector(corner) - Vector(new_origin), Vector(new_y))
35.     # Cannot use Blender's Vector type as a key for a dict so must convert to tuple for the mapping
36.     corners2dmap[tuple((proj_x, proj_y))] = index
37.
38. # Sort the 2d points in a winding order
39. sorted_corners2d = sort_points(np.array(list(corners2dmap.keys())))
40. sorted_corners = []
41. # Obtain the sorted list of 3d points with the view_matrix transformation reversed
42. for corner in sorted_corners2d:
43.     sorted_corners.append(view_mat.inverted() @
44.                             Vector(corners[corners2dmap[tuple(corner)]]))