Commit b27b7fae by Janis Born

### improve performance of calculate_face_normals and calculate_point_normals functions

parent a0f2da98
 ... ... @@ -3,7 +3,6 @@ import numpy as np def calculate_normal_edges(vertices, face_indices, normals, length): resolved_normals = None if isinstance(normals, FaceAttribute): ... ... @@ -32,42 +31,33 @@ def calculate_normal_edges(vertices, face_indices, normals, length): return edge_vertices, edge_indices def calculate_face_normals(vertices, face_indices): values = [] for face in face_indices: # Assuming face is planar v1 = np.array(vertices[face[0]]) v2 = np.array(vertices[face[1]]) v3 = np.array(vertices[face[2]]) v12 = np.subtract(v2, v1) v13 = np.subtract(v3, v1) norm = np.cross(v12, v13) norm = norm / np.linalg.norm(norm) values.append(norm) def calculate_face_normals(vertices, face_indices): v = np.asarray(vertices) f = np.asarray(face_indices) v0 = v[f][:, 0, :] v1 = v[f][:, 1, :] v2 = v[f][:, 2, :] n = np.cross(v1 - v0, v2 - v0) n /= np.linalg.norm(n, axis=1)[:, np.newaxis] return FaceAttribute(n) return FaceAttribute(values) def calculate_point_normals(vertices, face_indices): normals = np.zeros_like(vertices) counts = np.zeros(vertices.shape[0]) for face in face_indices: # Assuming face is planar v1 = np.array(vertices[face[0]]) v2 = np.array(vertices[face[1]]) v3 = np.array(vertices[face[2]]) v12 = np.subtract(v2, v1) v13 = np.subtract(v3, v1) norm = np.cross(v12, v13) filtered_face = face[np.where(face != -1)] normals[filtered_face] += norm counts[filtered_face] += 1 normals /= counts.reshape(-1, 1) normals /= np.linalg.norm(normals, axis=1).reshape(-1, 1) return PointAttribute(normals) \ No newline at end of file v = np.asarray(vertices) f = np.asarray(face_indices) fn = calculate_face_normals(v, f).values vi = np.ravel(f) fi = np.repeat(np.arange(f.shape[0]), 3, axis=0) vn = np.zeros_like(v) np.add.at(vn, vi, fn[fi]) # faster, but requires SciPy: # fv_matrix_rows = np.ravel(f) # fv_matrix_cols = np.repeat(np.arange(f.shape[0]), 3, axis=0) # fv_matrix = sp.sparse.coo_matrix((np.ones_like(fv_matrix_rows), (fv_matrix_rows, fv_matrix_cols))) # vn = fv_matrix @ fn vn /= np.linalg.norm(vn, axis=1)[:, np.newaxis] return PointAttribute(vn)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!