Commit b27b7fae authored by Janis Born's avatar 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!
Please register or to comment