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 """ Taken from: compute_normal.py - MaSIF Pablo Gainza - LPDI STI EPFL 2019 """ 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)) # unit normals to the faces 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) # unit normal to the vertex 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] # normalize d = np.sqrt(np.sum(normal ** 2, 0)) d[d < eps] = 1 normal = normal / repmat(d, 3, 1) # enforce that the normal are outward 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): # flip normal = -normal normalf = -normalf return normal.T def crossp(x, y): # x and y are (m,3) dimensional 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