Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,244 @@
import numpy as np
from scipy import sparse
# -----------------------------------------------------------------------------
# Functions from assignment_1_1
# -----------------------------------------------------------------------------
from geometry import compute_mesh_centroid
from geometry import compute_faces_centroid
from geometry import compute_faces_area
# -----------------------------------------------------------------------------
# Provided functions
# -----------------------------------------------------------------------------
def vertex_cells_sum(values, cells):
"""
Sums values at vertices from each incident n-cell.
Input:
- values : np.array (#cells,) or (#cells, n)
The cell values to be summed at vertices.
If shape (#cells,): The value is per-cell,
If shape (#cells, n): The value refers to the corresponding cell vertex.
- cells : np.array (#cells, n)
The array of cells.
Output:
- v_sum : np.array (#vertices,)
A vector with the sum at each i-th vertex in i-th position.
Note:
If n = 2 the cell is an edge, if n = 3 the cell is a triangle,
if n = 4 the cell can be a tetrahedron or a quadrilateral, depending on
the data structure.
"""
i = cells.flatten('F')
j = np.arange(len(cells))
j = np.tile(j, cells.shape[1])
v = values.flatten('F')
if len(v) == len(cells):
v = v[j]
v_sum = sparse.coo_matrix((v, (i, j)), (np.max(cells) + 1, len(cells)))
return np.array(v_sum.sum(axis=1)).flatten()
def compute_edges_length(V, E):
"""
Computes the edge length of each mesh edge.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- E : np.array (#edges, 2)
The array of mesh edges.
generated from the function E = igl.edges(F)
returns an array (#edges, 2) where i-th row contains the indices of the two vertices of i-th edge.
Output:
- l : np.array (#edges,)
The edge lengths.
"""
l = np.linalg.norm(V[E[:, 0]] - V[E[:, 1]], axis=1)
return l
# -----------------------------------------------------------------------------
# 2.5.1 Target energies
# -----------------------------------------------------------------------------
def compute_equilibrium_energy(V, F, x_csl):
"""
Computes the equilibrium energy E_eq = 1/2*(x_cm - x_csl)^2.
Input:
-- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
Output:
- E_eq : float
the equilibrium energy of the mesh with respect to the target centroid
x_csl.
"""
x_cm = compute_mesh_centroid(V,F)[0]
E_eq = 0.5 * (x_cm - x_csl)**2
return E_eq
def compute_shape_energy(V, E, L):
"""
Computes the energy E_sh = 1/2 sum_e (l_e - L_e)^2 in the current
configuration V, where l_e is the length of mesh edges, and L_e the
corresponding length in the undeformed configuration.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- E : np.array (#edges, 2)
The array of mesh edges.
- L : np.array (#edges,)
The rest lengths of mesh edges.
Output:
- E_sh : float
The energy E_sh in the current configuration V.
"""
l = compute_edges_length(V,E)
Lf = np.array(L)
e_vec = np.arange(len(E))
ldiff = (l[e_vec]-Lf[e_vec])**2
E_sh = 0.5 * np.sum(ldiff)
return E_sh
# -----------------------------------------------------------------------------
# 2.5.2 Faces area gradient
# -----------------------------------------------------------------------------
def compute_faces_area_gradient(V, F):
"""
Computes the gradient of faces area.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
Output:
- dA_x : np.array (#F, 3)
The gradient of faces areas A_i with respect to the x coordinate of each
face vertex x_1, x_2, and x_3, with (i,0) = dA_i/dx_1, (i,1) = dA_i/dx_2,
and (i,2) = dA_i/dx_3.
- dA_y : np.array (#F, 3)
The gradient of faces areas A_i with respect to the y coordinate of each
face vertex y_1, y_2, and y_3, with (i,0) = dA_i/dy_1, (i,1) = dA_i/dy_2,
and (i,2) = dA_i/dy_3.
"""
grad = lambda a,b: (V[a]-V[b])
gradABC = lambda fi: [grad(fi[2],fi[1]),grad(fi[0],fi[2]),grad(fi[1],fi[0])]
dA = np.apply_along_axis(gradABC,1,F)/2
dA_x = -dA[:,:,1]
dA_y = dA[:,:,0]
return dA_x, dA_y
# -----------------------------------------------------------------------------
# 2.5.3 Equilibrium energy gradient
# -----------------------------------------------------------------------------
def compute_equilibrium_energy_gradient(V, F, x_csl):
"""
Computes the gradient of the energy E_eq = 1/2*(x_cm - x_csl)^2 with respect
to the x and y coordinates of each vertex, where x_cm is the x coordinate
of the area centroid and x_csl x coordinate of the center of the support
line.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
Output:
- grad_E_eq : np.array (#V, 2)
The gradient of the energy E_eq with respect to vertices v_i,
with (i, 0) = dE_eq/dx_i and (i, 1) = dE_eq/dy_i
"""
cm = compute_mesh_centroid(V,F)
x_cm = cm[0]
x_f = compute_faces_centroid(V,F)
A_f = compute_faces_area(V,F)
A_f_V_nonp = compute_faces_area_gradient(V, F)
A_f_V = np.stack(A_f_V_nonp,axis=-1)
A_omega = np.sum(A_f)
xfact = (x_cm - x_csl)/A_omega
xfV = lambda v: np.apply_along_axis(lambda x: np.array([1/3,0.0]) if np.any(x[:]==v) else np.zeros((2)),1,F)
AfV = lambda v: (np.where(F[:,0][:,None]==v,A_f_V[:,0,:2],
np.where(F[:,1][:,None]==v,A_f_V[:,1,:2],
np.where(F[:,2][:,None]==v,A_f_V[:,2,:2],np.zeros((F.shape[0],2))) )) )
cf = lambda v : AfV(v)*(x_f[:,0] - x_cm)[:, None] + (A_f[:, None]*xfV(v))
#v_vec = np.arange(len(V))
#veq = np.sum(cf(v_vec),axis=0)*xfact
veq = np.array([np.sum(cf(v),axis=0) for v in range(0,len(V))])*xfact
return veq
# -----------------------------------------------------------------------------
# 2.5.4 Shape energy gradient
# -----------------------------------------------------------------------------
def compute_shape_energy_gradient(V, E, L):
"""
Computes the gradient of the energy E_sh = 1/2 sum_e (l_e - L_e)^2 with
respect to the x and y coordinates of each vertex, where l_e is the length
of mesh edges, and L_e the corresponding length in the undeformed
configuration.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- E : np.array (#edges, 2)
The array of mesh edges.
- L : np.array (#edges,)
The rest lengths of mesh edges.
Output:
- grad_E_sh : np.array (#V, 2)
The gradient of the energy E_sh with respect to vertices v_i,
with (i, 0) = dE_sh/dx_i, (i, 1) = dE_sh/dy_i
"""
vdif = lambda ee0, ee1: (V[ee0]-V[ee1])[:,:2]
len_e_d = vdif(E[:,0],E[:,1])
len_e = np.linalg.norm(len_e_d, axis=1)
len_e_t = lambda v: (np.where(E[:,0][:,None]==v,len_e_d[:],
np.where(E[:,1][:,None]==v,-len_e_d[:],np.zeros(E.shape))))
veq = np.sum(np.array([len_e_t(v) for v in range(0,len(V))]),axis=1) - np.sum(L/len_e,axis=0)
return veq

View File

@@ -0,0 +1,100 @@
import numpy as np
def compute_faces_area(V, F):
"""
Computes the area of the faces of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- area : np.array (|F|,)
The area of the faces. The i-th position contains the area of the i-th
face.
"""
# HW.1.3.3
return np.linalg.norm(np.cross(V[F[:,1]] - V[F[:,0]],V[F[:,2]] - V[F[:,0]], axis=1), axis=1)/2.0
def compute_mesh_area(V, F):
"""
Computes the area of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- area : float
The area of the mesh.
"""
# HW.1.3.3
return np.sum(compute_faces_area(V,F))
def compute_faces_centroid(V, F):
"""
Computes the area centroid of each face of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- cf : np.array (|F|, 3)
The area centroid of the faces.
"""
# HW.1.3.4
return (V[F[:,0]]+ V[F[:,1]] + V[F[:,2]])/3.0
def compute_mesh_centroid(V, F):
"""
Computes the area centroid of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- centroid : np.array (3,)
The area centroid of the mesh.
"""
# HW.1.3.4
face_centroid = compute_faces_centroid(V,F)
face_area = compute_faces_area(V,F)
return 1.0/np.sum(face_area) * np.sum(np.einsum('i,ij->ij', face_area, face_centroid), axis=0)
def compute_center_support_line(V):
"""
Computes the x coordinate of the center of the support line
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
Output:
- x_csl : float
the x coordinate of the center of the support line
"""
# HW.1.3.5
support_v = np.fromiter((v[0] for v in V if v[1]<10**-5), dtype=V.dtype)
x_csl = np.amin(support_v)+(np.amax(support_v)-np.amin(support_v))/2
return x_csl

View File

@@ -0,0 +1,138 @@
from energies import compute_edges_length
from energies import compute_equilibrium_energy_gradient, compute_equilibrium_energy
from energies import compute_shape_energy_gradient, compute_shape_energy
from geometry import compute_mesh_centroid
import numpy as np
import time
import igl
def compute_optimization_objective(V, F, E, x_csl, L0, w):
"""
Compute the objective function of make-it-stand problem.
E = E_equilibrium + w * E_shape
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- E : np.array (#edges, 2)
The array of mesh edges.
- x_csl : float
The x coordinate of the center of the support line.
- L0 : np.array (#edges,)
The rest lengths of mesh edges.
- w : float
The weight for shape preservation energy.
Output:
- obj : float
The value of the objective function.
"""
E_eq = compute_equilibrium_energy(V, F, x_csl)
E_sh = compute_shape_energy(V, E, L0)
obj = E_eq + w*E_sh
return obj
def compute_optimization_objective_gradient(V, F, E, x_csl, L0, w):
"""
Compute the gradient of the objective function of make-it-stand problem.
D_E = D_E_equilibrium + w * D_E_shape
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- E : np.array (#edges, 2)
The array of mesh edges.
- x_csl : float
The x coordinate of the center of the support line.
- l0 : np.array (#edges,)
The rest lengths of mesh edges.
- w : float
The weight for shape preservation energy.
Output:
- grad_obj : np.array (#V, 2)
The gradient of objective function.
"""
grad_E_eq = compute_equilibrium_energy_gradient(V, F, x_csl)
grad_E_sh = compute_shape_energy_gradient(V, E, L0)
grad_obj = grad_E_eq + w * grad_E_sh
return grad_obj
def fixed_step_gradient_descent(V, F, x_csl, w, theta, iters):
"""
Find equilibrium shape by using fixed step gradient descent method
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
- w : float
The weight for shape preservation energy.
- theta : float
The optimization step.
- iters : int
The number of iteration for gradient descent.
Output:
- V1 : np.array (#V, 3)
The optimized mesh's vertices
- F : np.array (#F, 3)
The array of triangle faces.
- energy: np.array(iters, 1)
The objective function energy curve with respect to the number of iterations.
- running_time: float
The tot running time of the optimization
"""
V1 = V.copy()
# this function of libigl returns an array (#edges, 2) where i-th row
# contains the indices of the two vertices of i-th edge.
E = igl.edges(F)
fix = np.where(V1[:, 1] < 1e-3)[0]
L0 = compute_edges_length(V1, E)
t0 = time.time()
energy = []
for i in range(iters):
grad = compute_optimization_objective_gradient(V1, F, E, x_csl, L0, w)
obj = compute_optimization_objective(V1, F, E, x_csl, L0, w)
energy.append(obj)
grad[fix] = 0
### start of your code.
x_cm = compute_mesh_centroid(V, F)[0]
if abs(x_csl - x_cm)<=10**-3:
break
if (np.linalg.norm(grad)<=10**-3):
break
# grad_f = grad[:,3
grad_f = np.zeros((np.shape(grad)[0],3))
grad_f[:,:-1] = grad
V1 = V1 -(theta * grad_f)
### end of your code.
running_time = time.time() - t0
return [V1, F, energy, running_time]

View File

@@ -0,0 +1,87 @@
# import pytest
import time
import pytest
import json
import sys
import igl
import numpy as np
sys.path.append('../')
sys.path.append('../src')
from src.energies import *
eps = 1E-6
with open('test_data2.json', 'r') as infile:
homework_datas = json.load(infile)
# @pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[0])
def test_shape_energy_correctness(data):
V = np.array(data[0], dtype=float)
E = np.array(data[1], dtype=int)
l0 = np.array(data[2], dtype=float)
shape_energy_ground_truth = np.array(data[3])
shape_energy_student = compute_shape_energy(V, E, l0)
assert np.linalg.norm(shape_energy_ground_truth - shape_energy_student) < eps
# @pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[1])
def test_equilibrium_engery_correctness(data):
V = np.array(data[0], dtype=float)
F = np.array(data[1], dtype=int)
x_csl = data[2]
equilibrium_engery_ground_truth = np.array(data[3])
equilibrium_engery_student = compute_equilibrium_energy(V, F, x_csl)
assert np.linalg.norm(equilibrium_engery_ground_truth - equilibrium_engery_student) < eps
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[2])
def test_faces_area_gradient_correctness(data):
V = np.array(data[0], dtype=float)
F = np.array(data[1], dtype=int)
faces_area_gradient_ground_truth_x = np.array(data[2])
faces_area_gradient_ground_truth_y = np.array(data[3])
[faces_area_gradient_student_x, faces_area_gradient_student_y] = compute_faces_area_gradient(V, F)
assert np.linalg.norm(faces_area_gradient_ground_truth_x - faces_area_gradient_student_x) < eps \
and np.linalg.norm(faces_area_gradient_ground_truth_y - faces_area_gradient_student_y) < eps
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[3])
def test_equilibrium_energy_gradient_correctness(data):
V = np.array(data[0], dtype=float)
F = np.array(data[1], dtype=int)
x_csl = data[2]
equilibrium_energy_gradient = np.array(data[3])
equilibrium_energy_student = compute_equilibrium_energy_gradient(V, F, x_csl)
assert np.linalg.norm(equilibrium_energy_gradient - equilibrium_energy_student) < eps
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[4])
def test_shape_energy_gradient_correctness(data):
V = np.array(data[0], dtype=float)
E = np.array(data[1], dtype=int)
l0 = np.array(data[2], dtype=float)
shape_energy_gradient_ground_truth = np.array(data[3])
shape_energy_gradient_student = compute_shape_energy_gradient(V, E, l0)
assert np.linalg.norm(shape_energy_gradient_ground_truth - shape_energy_gradient_student) < eps
n = 100000
F_big = np.arange(3 * n).reshape((n, 3))
V_big = np.random.random((3 * n, 3))
l0_big = np.zeros(3 * n)
E_big = igl.edges(F_big)
@pytest.mark.timeout(1)
def test_shape_energy_timing():
compute_shape_energy(V_big, E_big, l0_big)
@pytest.mark.timeout(1)
def test_faces_area_gradient_timing():
compute_faces_area_gradient(V_big, F_big)
@pytest.mark.timeout(1)
def test_equilibrium_energy_gradient_timing():
compute_equilibrium_energy_gradient(V_big, F_big, 0)
@pytest.mark.timeout(1)
def test_shape_energy_gradient_timing():
compute_shape_energy_gradient(V_big, E_big, l0_big)

View File

@@ -0,0 +1 @@
[[[[[0, 0, 0], [1, 0, 0], [0, 1, 0]], [[0, 1], [0, 2], [1, 2]], [0.0, 0.0, 0.0], 2.0], [[[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]], [[0, 1], [0, 2], [1, 2], [1, 3], [2, 3]], [0.0, 0.0, 0.0, 0.0, 0.0], 3.0]], [[[[0, 0, 0], [1, 0, 0], [0, 1, 0]], [[0, 1, 2]], 0, 0.05555555555555555], [[[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]], [[0, 1, 2], [1, 3, 2]], 0, 0.125]], [[[[0, 0, 0], [1, 0, 0], [0, 1, 0]], [[0, 1, 2]], [[-0.5, 0.5, -0.0]], [[-0.5, -0.0, 0.5]]], [[[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]], [[0, 1, 2], [1, 3, 2]], [[-0.5, 0.5, -0.0], [-0.0, 0.5, -0.5]], [[-0.5, -0.0, 0.5], [-0.5, 0.5, -0.0]]]], [[[[0, 0, 0], [1, 0, 0], [0, 1, 0]], [[0, 1, 2]], 0, [[0.1111111111111111, 0.0], [0.1111111111111111, 0.0], [0.1111111111111111, 0.0]]], [[[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]], [[0, 1, 2], [1, 3, 2]], 0, [[0.125, 0.04166666666666667], [0.12499999999999999, -0.04166666666666666], [0.125, -0.04166666666666667], [0.12499999999999999, 0.04166666666666666]]]], [[[[0, 0, 0], [1, 0, 0], [0, 1, 0]], [[0, 1], [0, 2], [1, 2]], [0.0, 0.0, 0.0], [[-1.0, -1.0], [2.0, -1.0], [-1.0, 2.0]]], [[[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]], [[0, 1], [0, 2], [1, 2], [1, 3], [2, 3]], [0.0, 0.0, 0.0, 0.0, 0.0], [[-1.0, -1.0], [2.0, -2.0], [-2.0, 2.0], [1.0, 1.0]]]]]