| import numpy as np |
| from numpy.matlib import repmat |
| """ |
| compute_normal.py: Compute the normals of a closed shape. |
| Pablo Gainza - LPDI STI EPFL 2019 |
| This file is part of MaSIF, based on previous matlab code by Gabriel Peyre, converted to Python by Pablo Gainza |
| """ |
|
|
| |
| from default_config.global_vars import epsilon as eps |
|
|
|
|
| def compute_normal(vertex, face): |
|
|
| """ |
| compute_normal - compute the normal of a triangulation |
| vertex: 3xn matrix of vertices |
| face: 3xm matrix of face indices. |
| |
| normal,normalf = compute_normal(vertex,face) |
| |
| normal(i,:) is the normal at vertex i. |
| normalf(j,:) is the normal at face j. |
| |
| Copyright (c) 2004 Gabriel Peyr |
| Converted to Python by Pablo Gainza LPDI EPFL 2017 |
| """ |
|
|
| vertex = vertex.T |
| face = face.T |
| nface = np.size(face, 1) |
| nvert = np.size(vertex, 1) |
| normal = np.zeros((3, nvert)) |
| |
| normalf = crossp( |
| vertex[:, face[1, :]] - vertex[:, face[0, :]], |
| vertex[:, face[2, :]] - vertex[:, face[0, :]], |
| ) |
| sum_squares = np.sum(normalf ** 2, 0) |
| d = np.sqrt(sum_squares) |
| d[d < eps] = 1 |
| normalf = normalf / repmat(d, 3, 1) |
| |
| normal = np.zeros((3, nvert)) |
| for i in np.arange(0, nface): |
| f = face[:, i] |
| for j in np.arange(3): |
| normal[:, f[j]] = normal[:, f[j]] + normalf[:, i] |
|
|
| |
| d = np.sqrt(np.sum(normal ** 2, 0)) |
| d[d < eps] = 1 |
| normal = normal / repmat(d, 3, 1) |
| |
| vertex_means = np.mean(vertex, 0) |
| v = vertex - repmat(vertex_means, 3, 1) |
| s = np.sum(np.multiply(v, normal), 1) |
| if np.sum(s > 0) < np.sum(s < 0): |
| |
| normal = -normal |
| normalf = -normalf |
| return normal.T |
|
|
|
|
| def crossp(x, y): |
|
|
| |
| z = np.zeros((x.shape)) |
| z[0, :] = np.multiply(x[1, :], y[2, :]) - np.multiply(x[2, :], y[1, :]) |
| z[1, :] = np.multiply(x[2, :], y[0, :]) - np.multiply(x[0, :], y[2, :]) |
| z[2, :] = np.multiply(x[0, :], y[1, :]) - np.multiply(x[1, :], y[0, :]) |
| return z |
|
|