Cleaned up python tutorials and added dependency checks to all tutorials
Former-commit-id: 246017f041
This commit is contained in:
@@ -4,7 +4,7 @@ from iglhelpers import *
|
||||
|
||||
# Create a numpy dense array
|
||||
# 2 types are supported by the wrappers: float64 and int64
|
||||
dense_matrix = np.array( [ (1,2,3), (4,5,6) , (7,8,9) ], dtype='float64')
|
||||
dense_matrix = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype='float64')
|
||||
|
||||
# libigl wrappers uses Eigen as a matrix type, you can easily convert between numpy and Eigen using
|
||||
# the helper function p2e. This operation duplicates the data.
|
||||
@@ -18,7 +18,7 @@ dense_matrix_eigen_2 = dense_matrix_eigen * dense_matrix_eigen
|
||||
print("Eigen Matrix: \n", dense_matrix_eigen_2, "\n", sep='')
|
||||
|
||||
# and access single elements
|
||||
print("Eigen Matrix(0,0): ", dense_matrix_eigen_2[0,0], "\n")
|
||||
print("Eigen Matrix(0,0): ", dense_matrix_eigen_2[0, 0], "\n")
|
||||
|
||||
# To convert it back to a numpy array, use the helper function e2p
|
||||
dense_matrix_2 = e2p(dense_matrix_eigen_2)
|
||||
@@ -39,10 +39,3 @@ print("Sparse matrix Eigen: ", sparse_matrix_eigen, sep='')
|
||||
# And converted back with e2p
|
||||
sparse_matrix_2 = e2p(sparse_matrix_eigen)
|
||||
print("Sparse matrix Numpy: ", sparse_matrix_2.todense(), sep='')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
from __future__ import print_function
|
||||
import sys, os
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
igl.readOFF("../../tutorial/shared/cube.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "cube.off", V, F)
|
||||
|
||||
# Print the vertices and faces matrices
|
||||
print("Vertices: \n", V, sep='')
|
||||
|
||||
@@ -9,6 +9,7 @@ from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
## This is a test application for the TCPViewer
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
import os
|
||||
import time
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
import tcpviewer
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH
|
||||
|
||||
|
||||
## This is a test application for the TCPViewer
|
||||
|
||||
# Launch the tcp viewer
|
||||
os.system("python ../tcpviewer.py&")
|
||||
@@ -13,13 +17,10 @@ os.system("python ../tcpviewer.py&")
|
||||
# Wait for it to set up the socket
|
||||
time.sleep(1)
|
||||
|
||||
import pyigl as igl
|
||||
import tcpviewer
|
||||
|
||||
# Read a mesh
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
igl.readOFF('../../tutorial/shared/beetle.off', V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "beetle.off", V, F)
|
||||
|
||||
# Send it to the viewer
|
||||
viewer = tcpviewer.TCPViewer()
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V1 = igl.eigen.MatrixXd()
|
||||
F1 = igl.eigen.MatrixXi()
|
||||
|
||||
@@ -15,22 +21,22 @@ def key_pressed(viewer, key, modifier):
|
||||
|
||||
if key == ord('1'):
|
||||
# # Clear should be called before drawing the mesh
|
||||
viewer.data.clear();
|
||||
viewer.data.clear()
|
||||
# # Draw_mesh creates or updates the vertices and faces of the displayed mesh.
|
||||
# # If a mesh is already displayed, draw_mesh returns an error if the given V and
|
||||
# # F have size different than the current ones
|
||||
viewer.data.set_mesh(V1, F1);
|
||||
viewer.core.align_camera_center(V1,F1);
|
||||
viewer.data.set_mesh(V1, F1)
|
||||
viewer.core.align_camera_center(V1,F1)
|
||||
elif key == ord('2'):
|
||||
viewer.data.clear();
|
||||
viewer.data.set_mesh(V2, F2);
|
||||
viewer.core.align_camera_center(V2,F2);
|
||||
viewer.data.clear()
|
||||
viewer.data.set_mesh(V2, F2)
|
||||
viewer.core.align_camera_center(V2,F2)
|
||||
return False
|
||||
|
||||
|
||||
# Load two meshes
|
||||
igl.readOFF("../../tutorial/shared/bumpy.off", V1, F1);
|
||||
igl.readOFF("../../tutorial/shared/fertility.off", V2, F2);
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V1, F1)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "fertility.off", V2, F2)
|
||||
|
||||
print("1 Switch to bump mesh")
|
||||
print("2 Switch to fertility mesh")
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
C = igl.eigen.MatrixXd()
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/screwdriver.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "screwdriver.off", V, F)
|
||||
|
||||
# Plot the mesh
|
||||
viewer = igl.viewer.Viewer()
|
||||
viewer.data.set_mesh(V, F)
|
||||
|
||||
# Use the z coordinate as a scalar field over the surface
|
||||
Z = V.col(2);
|
||||
Z = V.col(2)
|
||||
|
||||
# Compute per-vertex colors
|
||||
igl.jet(Z,True,C)
|
||||
igl.jet(Z, True, C)
|
||||
|
||||
# Add per-vertex colors
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
@@ -1,49 +1,54 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/bunny.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "bunny.off", V, F)
|
||||
|
||||
# Find the bounding box
|
||||
m = V.colwiseMinCoeff()
|
||||
M = V.colwiseMaxCoeff()
|
||||
|
||||
|
||||
# Corners of the bounding box
|
||||
V_box = igl.eigen.MatrixXd(
|
||||
[
|
||||
[m[0,0], m[0,1], m[0,2]],
|
||||
[M[0,0], m[0,1], m[0,2]],
|
||||
[M[0,0], M[0,1], m[0,2]],
|
||||
[m[0,0], M[0,1], m[0,2]],
|
||||
[m[0,0], m[0,1], M[0,2]],
|
||||
[M[0,0], m[0,1], M[0,2]],
|
||||
[M[0,0], M[0,1], M[0,2]],
|
||||
[m[0,0], M[0,1], M[0,2]]
|
||||
]
|
||||
[
|
||||
[m[0, 0], m[0, 1], m[0, 2]],
|
||||
[M[0, 0], m[0, 1], m[0, 2]],
|
||||
[M[0, 0], M[0, 1], m[0, 2]],
|
||||
[m[0, 0], M[0, 1], m[0, 2]],
|
||||
[m[0, 0], m[0, 1], M[0, 2]],
|
||||
[M[0, 0], m[0, 1], M[0, 2]],
|
||||
[M[0, 0], M[0, 1], M[0, 2]],
|
||||
[m[0, 0], M[0, 1], M[0, 2]]
|
||||
]
|
||||
)
|
||||
|
||||
E_box = igl.eigen.MatrixXi(
|
||||
[
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
[2, 3],
|
||||
[3, 0],
|
||||
[4, 5],
|
||||
[5, 6],
|
||||
[6, 7],
|
||||
[7, 4],
|
||||
[0, 4],
|
||||
[1, 5],
|
||||
[2, 6],
|
||||
[7 ,3]
|
||||
]
|
||||
[
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
[2, 3],
|
||||
[3, 0],
|
||||
[4, 5],
|
||||
[5, 6],
|
||||
[6, 7],
|
||||
[7, 4],
|
||||
[0, 4],
|
||||
[1, 5],
|
||||
[2, 6],
|
||||
[7, 3]
|
||||
]
|
||||
)
|
||||
|
||||
# Plot the mesh
|
||||
@@ -51,21 +56,21 @@ viewer = igl.viewer.Viewer()
|
||||
viewer.data.set_mesh(V, F)
|
||||
|
||||
# Plot the corners of the bounding box as points
|
||||
viewer.data.add_points(V_box,igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_points(V_box, igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
|
||||
# Plot the edges of the bounding box
|
||||
for i in range(0,E_box.rows()):
|
||||
for i in range(0, E_box.rows()):
|
||||
viewer.data.add_edges(
|
||||
V_box.row(E_box[i,0]),
|
||||
V_box.row(E_box[i,1]),
|
||||
igl.eigen.MatrixXd([[1,0,0]]))
|
||||
V_box.row(E_box[i, 0]),
|
||||
V_box.row(E_box[i, 1]),
|
||||
igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
|
||||
# Plot labels with the coordinates of bounding box vertices
|
||||
l1 = 'x: ' + str(m[0,0]) + ' y: ' + str(m[0,1]) + ' z: ' + str(m[0,2])
|
||||
viewer.data.add_label(m.transpose(),l1)
|
||||
l1 = 'x: ' + str(m[0, 0]) + ' y: ' + str(m[0, 1]) + ' z: ' + str(m[0, 2])
|
||||
viewer.data.add_label(m.transpose(), l1)
|
||||
|
||||
l2 = 'x: ' + str(M[0,0]) + ' y: ' + str(M[0,1]) + ' z: ' + str(M[0,2])
|
||||
viewer.data.add_label(M.transpose(),l2)
|
||||
l2 = 'x: ' + str(M[0, 0]) + ' y: ' + str(M[0, 1]) + ' z: ' + str(M[0, 2])
|
||||
viewer.data.add_label(M.transpose(), l2)
|
||||
|
||||
# Launch the viewer
|
||||
viewer.launch()
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
@@ -11,33 +17,35 @@ N_vertices = igl.eigen.MatrixXd()
|
||||
N_faces = igl.eigen.MatrixXd()
|
||||
N_corners = igl.eigen.MatrixXd()
|
||||
|
||||
|
||||
# This function is called every time a keyboard button is pressed
|
||||
def key_pressed(viewer, key, modifier):
|
||||
if key == ord('1'):
|
||||
viewer.data.set_normals(N_faces)
|
||||
return True
|
||||
viewer.data.set_normals(N_faces)
|
||||
return True
|
||||
elif key == ord('2'):
|
||||
viewer.data.set_normals(N_vertices)
|
||||
return True
|
||||
viewer.data.set_normals(N_vertices)
|
||||
return True
|
||||
elif key == ord('3'):
|
||||
viewer.data.set_normals(N_corners)
|
||||
return True
|
||||
viewer.data.set_normals(N_corners)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/fandisk.off", V, F);
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "fandisk.off", V, F)
|
||||
|
||||
# Compute per-face normals
|
||||
N_faces = igl.eigen.MatrixXd()
|
||||
igl.per_face_normals(V,F,N_faces)
|
||||
igl.per_face_normals(V, F, N_faces)
|
||||
|
||||
# Compute per-vertex normals
|
||||
N_vertices = igl.eigen.MatrixXd()
|
||||
igl.per_vertex_normals(V,F,igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA,N_vertices)
|
||||
igl.per_vertex_normals(V, F, igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA, N_vertices)
|
||||
|
||||
# Compute per-corner normals, |dihedral angle| > 20 degrees --> crease
|
||||
N_corners = igl.eigen.MatrixXd()
|
||||
igl.per_corner_normals(V,F,20,N_corners)
|
||||
igl.per_corner_normals(V, F, 20, N_corners)
|
||||
|
||||
# Plot the mesh
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
# Load mesh
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
igl.readOFF("../../tutorial/shared/bumpy.off",V,F);
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F)
|
||||
|
||||
# Compute Gaussian curvature
|
||||
K = igl.eigen.MatrixXd();
|
||||
igl.gaussian_curvature(V,F,K);
|
||||
K = igl.eigen.MatrixXd()
|
||||
igl.gaussian_curvature(V, F, K)
|
||||
|
||||
# Compute pseudocolor
|
||||
C = igl.eigen.MatrixXd();
|
||||
igl.jet(K,True,C);
|
||||
C = igl.eigen.MatrixXd()
|
||||
igl.jet(K, True, C)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
V = igl.eigen.MatrixXd();
|
||||
F = igl.eigen.MatrixXi();
|
||||
igl.read_triangle_mesh("../../tutorial/shared/fertility.off", V, F);
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "fertility.off", V, F)
|
||||
|
||||
# Alternative discrete mean curvature
|
||||
HN = igl.eigen.MatrixXd()
|
||||
@@ -14,14 +20,13 @@ L = igl.eigen.SparseMatrixd()
|
||||
M = igl.eigen.SparseMatrixd()
|
||||
Minv = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.cotmatrix(V, F, L)
|
||||
igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M)
|
||||
|
||||
igl.cotmatrix(V,F,L)
|
||||
igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M)
|
||||
|
||||
igl.invert_diag(M,Minv)
|
||||
igl.invert_diag(M, Minv)
|
||||
|
||||
# Laplace-Beltrami of position
|
||||
HN = -Minv*(L*V)
|
||||
HN = -Minv * (L * V)
|
||||
|
||||
# Extract magnitude as mean curvature
|
||||
H = HN.rowwiseNorm()
|
||||
@@ -33,33 +38,33 @@ PD2 = igl.eigen.MatrixXd()
|
||||
PV1 = igl.eigen.MatrixXd()
|
||||
PV2 = igl.eigen.MatrixXd()
|
||||
|
||||
igl.principal_curvature(V,F,PD1,PD2,PV1,PV2)
|
||||
igl.principal_curvature(V, F, PD1, PD2, PV1, PV2)
|
||||
|
||||
# Mean curvature
|
||||
H = 0.5*(PV1+PV2)
|
||||
H = 0.5 * (PV1 + PV2)
|
||||
|
||||
viewer = igl.viewer.Viewer()
|
||||
viewer.data.set_mesh(V, F)
|
||||
|
||||
# Compute pseudocolor
|
||||
C = igl.eigen.MatrixXd()
|
||||
igl.parula(H,True,C)
|
||||
igl.parula(H, True, C)
|
||||
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
# Average edge length for sizing
|
||||
avg = igl.avg_edge_length(V,F)
|
||||
avg = igl.avg_edge_length(V, F)
|
||||
|
||||
# Draw a blue segment parallel to the minimal curvature direction
|
||||
red = igl.eigen.MatrixXd([[0.8,0.2,0.2]])
|
||||
blue = igl.eigen.MatrixXd([[0.2,0.2,0.8]])
|
||||
red = igl.eigen.MatrixXd([[0.8, 0.2, 0.2]])
|
||||
blue = igl.eigen.MatrixXd([[0.2, 0.2, 0.8]])
|
||||
|
||||
viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue)
|
||||
viewer.data.add_edges(V + PD1 * avg, V - PD1 * avg, blue)
|
||||
|
||||
# Draw a red segment parallel to the maximal curvature direction
|
||||
viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red)
|
||||
viewer.data.add_edges(V + PD2 * avg, V - PD2 * avg, red)
|
||||
|
||||
# Hide wireframe
|
||||
viewer.core.show_lines = False
|
||||
|
||||
viewer.launch();
|
||||
viewer.launch()
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/cheburashka.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F)
|
||||
|
||||
# Read scalar function values from a file, U: #V by 1
|
||||
U = igl.eigen.MatrixXd()
|
||||
igl.readDMAT("../../tutorial/shared/cheburashka-scalar.dmat",U)
|
||||
igl.readDMAT(TUTORIAL_SHARED_PATH + "cheburashka-scalar.dmat", U)
|
||||
U = U.col(0)
|
||||
|
||||
# Compute gradient operator: #F*3 by #V
|
||||
G = igl.eigen.SparseMatrixd()
|
||||
igl.grad(V,F,G)
|
||||
igl.grad(V, F, G)
|
||||
|
||||
# Compute gradient of U
|
||||
GU = (G*U).MapMatrix(F.rows(),3)
|
||||
GU = (G * U).MapMatrix(F.rows(), 3)
|
||||
|
||||
# Compute gradient magnitude
|
||||
GU_mag = GU.rowwiseNorm()
|
||||
@@ -31,22 +37,22 @@ viewer.data.set_mesh(V, F)
|
||||
# Compute pseudocolor for original function
|
||||
C = igl.eigen.MatrixXd()
|
||||
|
||||
igl.jet(U,True,C)
|
||||
igl.jet(U, True, C)
|
||||
|
||||
# Or for gradient magnitude
|
||||
# igl.jet(GU_mag,True,C)
|
||||
|
||||
viewer.data.set_colors(C);
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
# Average edge length divided by average gradient (for scaling)
|
||||
max_size = igl.avg_edge_length(V,F) / GU_mag.mean()
|
||||
max_size = igl.avg_edge_length(V, F) / GU_mag.mean()
|
||||
|
||||
# Draw a black segment in direction of gradient at face barycenters
|
||||
BC = igl.eigen.MatrixXd()
|
||||
igl.barycenter(V,F,BC)
|
||||
igl.barycenter(V, F, BC)
|
||||
|
||||
black = igl.eigen.MatrixXd([[0.0,0.0,0.0]])
|
||||
viewer.data.add_edges(BC,BC+max_size*GU, black)
|
||||
black = igl.eigen.MatrixXd([[0.0, 0.0, 0.0]])
|
||||
viewer.data.add_edges(BC, BC + max_size * GU, black)
|
||||
|
||||
# Hide wireframe
|
||||
viewer.core.show_lines = False
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
from __future__ import print_function
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
import pyigl as igl
|
||||
import math
|
||||
|
||||
global V
|
||||
global U
|
||||
global F
|
||||
global L
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
U = igl.eigen.MatrixXd()
|
||||
@@ -20,70 +19,70 @@ L = igl.eigen.SparseMatrixd()
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/cow.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "cow.off", V, F)
|
||||
|
||||
# Compute Laplace-Beltrami operator: #V by #V
|
||||
igl.cotmatrix(V,F,L)
|
||||
igl.cotmatrix(V, F, L)
|
||||
|
||||
# Alternative construction of same Laplacian
|
||||
G = igl.eigen.SparseMatrixd()
|
||||
K = igl.eigen.SparseMatrixd()
|
||||
|
||||
# Gradient/Divergence
|
||||
igl.grad(V,F,G);
|
||||
igl.grad(V, F, G)
|
||||
|
||||
# Diagonal per-triangle "mass matrix"
|
||||
dblA = igl.eigen.MatrixXd()
|
||||
igl.doublearea(V,F,dblA)
|
||||
igl.doublearea(V, F, dblA)
|
||||
|
||||
# Place areas along diagonal #dim times
|
||||
|
||||
T = (dblA.replicate(3,1)*0.5).asDiagonal() * 1
|
||||
T = (dblA.replicate(3, 1) * 0.5).asDiagonal() * 1
|
||||
|
||||
# Laplacian K built as discrete divergence of gradient or equivalently
|
||||
# discrete Dirichelet energy Hessian
|
||||
|
||||
temp = -G.transpose()
|
||||
K = -G.transpose() * T * G
|
||||
print("|K-L|: ",(K-L).norm())
|
||||
print("|K-L|: ", (K - L).norm())
|
||||
|
||||
|
||||
def key_pressed(viewer, key, modifier):
|
||||
global V
|
||||
global U
|
||||
global F
|
||||
global L
|
||||
global V, U, F, L
|
||||
|
||||
if key == ord('r') or key == ord('R'):
|
||||
U = V;
|
||||
U = V
|
||||
print("RESET")
|
||||
|
||||
elif key == ord(' '):
|
||||
|
||||
# Recompute just mass matrix on each step
|
||||
M = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.massmatrix(U,F,igl.MASSMATRIX_TYPE_BARYCENTRIC,M);
|
||||
igl.massmatrix(U, F, igl.MASSMATRIX_TYPE_BARYCENTRIC, M)
|
||||
|
||||
# Solve (M-delta*L) U = M*U
|
||||
S = (M - 0.001*L)
|
||||
S = (M - 0.001 * L)
|
||||
|
||||
solver = igl.eigen.SimplicialLLTsparse(S)
|
||||
|
||||
U = solver.solve(M*U)
|
||||
U = solver.solve(M * U)
|
||||
|
||||
# Compute centroid and subtract (also important for numerics)
|
||||
dblA = igl.eigen.MatrixXd()
|
||||
igl.doublearea(U,F,dblA)
|
||||
igl.doublearea(U, F, dblA)
|
||||
|
||||
print(dblA.sum())
|
||||
|
||||
area = 0.5*dblA.sum()
|
||||
area = 0.5 * dblA.sum()
|
||||
BC = igl.eigen.MatrixXd()
|
||||
igl.barycenter(U,F,BC)
|
||||
centroid = igl.eigen.MatrixXd([[0.0,0.0,0.0]])
|
||||
igl.barycenter(U, F, BC)
|
||||
centroid = igl.eigen.MatrixXd([[0.0, 0.0, 0.0]])
|
||||
|
||||
for i in range(0,BC.rows()):
|
||||
centroid += 0.5*dblA[i,0]/area*BC.row(i)
|
||||
for i in range(0, BC.rows()):
|
||||
centroid += 0.5 * dblA[i, 0] / area * BC.row(i)
|
||||
|
||||
U -= centroid.replicate(U.rows(),1)
|
||||
U -= centroid.replicate(U.rows(), 1)
|
||||
|
||||
# Normalize to unit surface area (important for numerics)
|
||||
U = U / math.sqrt(area)
|
||||
@@ -93,13 +92,14 @@ def key_pressed(viewer, key, modifier):
|
||||
# Send new positions, update normals, recenter
|
||||
viewer.data.set_vertices(U)
|
||||
viewer.data.compute_normals()
|
||||
viewer.core.align_camera_center(U,F)
|
||||
viewer.core.align_camera_center(U, F)
|
||||
return True
|
||||
|
||||
|
||||
# Use original normals as pseudo-colors
|
||||
N = igl.eigen.MatrixXd()
|
||||
igl.per_vertex_normals(V,F,N)
|
||||
C = N.rowwiseNormalized()*0.5+0.5;
|
||||
igl.per_vertex_normals(V, F, N)
|
||||
C = N.rowwiseNormalized() * 0.5 + 0.5
|
||||
|
||||
# Initialize smoothing with base mesh
|
||||
U = V
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
from __future__ import print_function
|
||||
import sys, os
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
igl.readOFF("../../tutorial/shared/decimated-knight.off",V,F)
|
||||
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", V, F)
|
||||
|
||||
# 100 random indicies into rows of F
|
||||
I = igl.eigen.MatrixXi()
|
||||
igl.floor((0.5*(igl.eigen.MatrixXd.Random(100,1)+1.)*F.rows()),I);
|
||||
igl.floor((0.5 * (igl.eigen.MatrixXd.Random(100, 1) + 1.) * F.rows()), I)
|
||||
|
||||
# 50 random indicies into rows of I
|
||||
J = igl.eigen.MatrixXi()
|
||||
igl.floor((0.5*(igl.eigen.MatrixXd.Random(50,1)+1.)*I.rows()),J)
|
||||
igl.floor((0.5 * (igl.eigen.MatrixXd.Random(50, 1) + 1.) * I.rows()), J)
|
||||
|
||||
# K = I(J);
|
||||
K = igl.eigen.MatrixXi()
|
||||
igl.slice(I,J,K)
|
||||
igl.slice(I, J, K)
|
||||
|
||||
# default green for all faces
|
||||
#C = p2e(np.array([[0.4,0.8,0.3]])).replicate(F.rows(),1)
|
||||
C = igl.eigen.MatrixXd([[0.4,0.8,0.3]]).replicate(F.rows(),1)
|
||||
# C = p2e(np.array([[0.4,0.8,0.3]])).replicate(F.rows(),1)
|
||||
C = igl.eigen.MatrixXd([[0.4, 0.8, 0.3]]).replicate(F.rows(), 1)
|
||||
|
||||
# Red for each in K
|
||||
R = igl.eigen.MatrixXd([[1.0,0.3,0.3]]).replicate(K.rows(),1)
|
||||
R = igl.eigen.MatrixXd([[1.0, 0.3, 0.3]]).replicate(K.rows(), 1)
|
||||
# C(K,:) = R
|
||||
igl.slice_into(R,K,1,C)
|
||||
igl.slice_into(R, K, 1, C)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
igl.readOFF("../../tutorial/shared/decimated-knight.off",V,F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", V, F)
|
||||
|
||||
# Sort barycenters lexicographically
|
||||
BC = igl.eigen.MatrixXd()
|
||||
sorted_BC = igl.eigen.MatrixXd()
|
||||
|
||||
igl.barycenter(V,F,BC);
|
||||
igl.barycenter(V, F, BC)
|
||||
|
||||
I = igl.eigen.MatrixXi()
|
||||
J = igl.eigen.MatrixXi()
|
||||
|
||||
# sorted_BC = BC(I,:)
|
||||
igl.sortrows(BC,True,sorted_BC,I)
|
||||
igl.sortrows(BC, True, sorted_BC, I)
|
||||
|
||||
# Get sorted "place" from sorted indices
|
||||
J.resize(I.rows(),1)
|
||||
J.resize(I.rows(), 1)
|
||||
# J(I) = 1:numel(I)
|
||||
|
||||
igl.slice_into(igl.coloni(0,I.size()-1),I,J)
|
||||
igl.slice_into(igl.coloni(0, I.size() - 1), I, J)
|
||||
|
||||
# Pseudo-color based on sorted place
|
||||
C = igl.eigen.MatrixXd()
|
||||
igl.jet(J.castdouble(),True,C)
|
||||
igl.jet(J.castdouble(), True, C)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,73 +1,78 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
igl.readOFF("../../tutorial/shared/camelhead.off",V,F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F)
|
||||
|
||||
# Find boundary edges
|
||||
E = igl.eigen.MatrixXi()
|
||||
igl.boundary_facets(F,E);
|
||||
igl.boundary_facets(F, E)
|
||||
|
||||
# Find boundary vertices
|
||||
b = igl.eigen.MatrixXi()
|
||||
b = igl.eigen.MatrixXi()
|
||||
IA = igl.eigen.MatrixXi()
|
||||
IC = igl.eigen.MatrixXi()
|
||||
|
||||
igl.unique(E,b,IA,IC);
|
||||
igl.unique(E, b, IA, IC)
|
||||
|
||||
# List of all vertex indices
|
||||
vall = igl.eigen.MatrixXi()
|
||||
vin = igl.eigen.MatrixXi()
|
||||
vall = igl.eigen.MatrixXi()
|
||||
vin = igl.eigen.MatrixXi()
|
||||
|
||||
igl.coloni(0,V.rows()-1,vall)
|
||||
igl.coloni(0, V.rows() - 1, vall)
|
||||
|
||||
# List of interior indices
|
||||
igl.setdiff(vall,b,vin,IA)
|
||||
igl.setdiff(vall, b, vin, IA)
|
||||
|
||||
# Construct and slice up Laplacian
|
||||
L = igl.eigen.SparseMatrixd()
|
||||
L_in_in = igl.eigen.SparseMatrixd()
|
||||
L_in_b = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.cotmatrix(V,F,L)
|
||||
igl.slice(L,vin,vin,L_in_in)
|
||||
igl.slice(L,vin,b,L_in_b)
|
||||
igl.cotmatrix(V, F, L)
|
||||
igl.slice(L, vin, vin, L_in_in)
|
||||
igl.slice(L, vin, b, L_in_b)
|
||||
|
||||
# Dirichlet boundary conditions from z-coordinate
|
||||
bc = igl.eigen.MatrixXd()
|
||||
Z = V.col(2)
|
||||
igl.slice(Z,b,bc)
|
||||
igl.slice(Z, b, bc)
|
||||
|
||||
# Solve PDE
|
||||
solver = igl.eigen.SimplicialLLTsparse(-L_in_in)
|
||||
Z_in = solver.solve(L_in_b*bc)
|
||||
Z_in = solver.solve(L_in_b * bc)
|
||||
|
||||
# slice into solution
|
||||
igl.slice_into(Z_in,vin,Z)
|
||||
igl.slice_into(Z_in, vin, Z)
|
||||
|
||||
# Alternative, short hand
|
||||
mqwf = igl.min_quad_with_fixed_data()
|
||||
|
||||
# Linear term is 0
|
||||
B = igl.eigen.MatrixXd()
|
||||
B.setZero(V.rows(),1);
|
||||
B.setZero(V.rows(), 1)
|
||||
|
||||
# Empty constraints
|
||||
Beq = igl.eigen.MatrixXd()
|
||||
Aeq = igl.eigen.SparseMatrixd()
|
||||
|
||||
# Our cotmatrix is _negative_ definite, so flip sign
|
||||
igl.min_quad_with_fixed_precompute(-L,b,Aeq,True,mqwf)
|
||||
igl.min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z)
|
||||
igl.min_quad_with_fixed_precompute(-L, b, Aeq, True, mqwf)
|
||||
igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z)
|
||||
|
||||
# Pseudo-color based on solution
|
||||
C = igl.eigen.MatrixXd()
|
||||
igl.jet(Z,True,C)
|
||||
igl.jet(Z, True, C)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
igl.readOFF("../../tutorial/shared/cheburashka.off",V,F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F)
|
||||
|
||||
# Two fixed points
|
||||
# Left hand, left foot
|
||||
b = igl.eigen.MatrixXi([[4331],[5957]])
|
||||
bc = igl.eigen.MatrixXd([[1],[-1]])
|
||||
b = igl.eigen.MatrixXi([[4331], [5957]])
|
||||
bc = igl.eigen.MatrixXd([[1], [-1]])
|
||||
|
||||
# Construct Laplacian and mass matrix
|
||||
L = igl.eigen.SparseMatrixd()
|
||||
@@ -20,17 +26,17 @@ M = igl.eigen.SparseMatrixd()
|
||||
Minv = igl.eigen.SparseMatrixd()
|
||||
Q = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.cotmatrix(V,F,L)
|
||||
igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M)
|
||||
igl.invert_diag(M,Minv)
|
||||
igl.cotmatrix(V, F, L)
|
||||
igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M)
|
||||
igl.invert_diag(M, Minv)
|
||||
|
||||
# Bi-Laplacian
|
||||
Q = L * (Minv * L);
|
||||
Q = L * (Minv * L)
|
||||
|
||||
# Zero linear term
|
||||
B = igl.eigen.MatrixXd.Zero(V.rows(),1);
|
||||
B = igl.eigen.MatrixXd.Zero(V.rows(), 1)
|
||||
|
||||
Z = igl.eigen.MatrixXd()
|
||||
Z = igl.eigen.MatrixXd()
|
||||
Z_const = igl.eigen.MatrixXd()
|
||||
|
||||
# Alternative, short hand
|
||||
@@ -40,37 +46,33 @@ mqwf = igl.min_quad_with_fixed_data()
|
||||
Beq = igl.eigen.MatrixXd()
|
||||
Aeq = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.min_quad_with_fixed_precompute(Q,b,Aeq,True,mqwf)
|
||||
igl.min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z)
|
||||
igl.min_quad_with_fixed_precompute(Q, b, Aeq, True, mqwf)
|
||||
igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z)
|
||||
|
||||
# Constraint forcing difference of two points to be 0
|
||||
Aeq = igl.eigen.SparseMatrixd(1,V.rows())
|
||||
Aeq = igl.eigen.SparseMatrixd(1, V.rows())
|
||||
|
||||
# Right hand, right foot
|
||||
Aeq.insert(0,6074,1)
|
||||
Aeq.insert(0,6523,-1)
|
||||
Aeq.insert(0, 6074, 1)
|
||||
Aeq.insert(0, 6523, -1)
|
||||
Aeq.makeCompressed()
|
||||
|
||||
Beq = igl.eigen.MatrixXd([[0]])
|
||||
igl.min_quad_with_fixed_precompute(Q,b,Aeq,True,mqwf)
|
||||
igl.min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z_const)
|
||||
igl.min_quad_with_fixed_precompute(Q, b, Aeq, True, mqwf)
|
||||
igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z_const)
|
||||
|
||||
# Global definitions for viewer
|
||||
# Pseudo-color based on solution
|
||||
global C
|
||||
C = igl.eigen.MatrixXd()
|
||||
|
||||
global C_const
|
||||
C_const = igl.eigen.MatrixXd()
|
||||
|
||||
global toggle
|
||||
toggle = True
|
||||
|
||||
# Use same color axes
|
||||
min_z = min(Z.minCoeff(),Z_const.minCoeff())
|
||||
max_z = max(Z.maxCoeff(),Z_const.maxCoeff())
|
||||
min_z = min(Z.minCoeff(), Z_const.minCoeff())
|
||||
max_z = max(Z.maxCoeff(), Z_const.maxCoeff())
|
||||
|
||||
igl.jet( Z,min_z,max_z,C);
|
||||
igl.jet(Z_const,min_z,max_z,C_const);
|
||||
igl.jet(Z, min_z, max_z, C)
|
||||
igl.jet(Z_const, min_z, max_z, C_const)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
@@ -78,22 +80,22 @@ viewer.data.set_mesh(V, F)
|
||||
viewer.core.show_lines = False
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
def key_down(viewer,key,mode):
|
||||
|
||||
def key_down(viewer, key, mode):
|
||||
if key == ord(' '):
|
||||
global toggle
|
||||
global C
|
||||
global C_const
|
||||
global toggle, C, C_const
|
||||
|
||||
if toggle:
|
||||
viewer.data.set_colors(C)
|
||||
else:
|
||||
viewer.data.set_colors(C_const)
|
||||
|
||||
toggle = not toggle;
|
||||
toggle = not toggle
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
viewer.callback_key_down = key_down
|
||||
|
||||
print("Press [space] to toggle between unconstrained and constrained.")
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
b = igl.eigen.MatrixXi()
|
||||
B = igl.eigen.MatrixXd()
|
||||
bc = igl.eigen.MatrixXd()
|
||||
@@ -17,37 +23,39 @@ Q = igl.eigen.SparseMatrixd()
|
||||
Aeq = igl.eigen.SparseMatrixd()
|
||||
Aieq = igl.eigen.SparseMatrixd()
|
||||
|
||||
|
||||
def solve(viewer):
|
||||
global Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,Z
|
||||
global Q, B, b, bc, Aeq, Beq, Aieq, Bieq, lx, ux, Z
|
||||
params = igl.active_set_params()
|
||||
params.max_iter = 8
|
||||
|
||||
igl.active_set(Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,params,Z)
|
||||
igl.active_set(Q, B, b, bc, Aeq, Beq, Aieq, Bieq, lx, ux, params, Z)
|
||||
|
||||
C = igl.eigen.MatrixXd()
|
||||
igl.jet(Z,0,1,C)
|
||||
igl.jet(Z, 0, 1, C)
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
|
||||
def key_down(viewer, key, mod):
|
||||
global Beq,solve
|
||||
global Beq, solve
|
||||
if key == ord('.'):
|
||||
Beq[0,0] = Beq[0,0] * 2.0
|
||||
solve(viewer)
|
||||
return True
|
||||
Beq[0, 0] = Beq[0, 0] * 2.0
|
||||
solve(viewer)
|
||||
return True
|
||||
elif key == ord(','):
|
||||
Beq[0,0] = Beq[0,0] / 2.0
|
||||
solve(viewer)
|
||||
return True
|
||||
Beq[0, 0] = Beq[0, 0] / 2.0
|
||||
solve(viewer)
|
||||
return True
|
||||
elif key == ord(' '):
|
||||
solve(viewer)
|
||||
return True
|
||||
return False;
|
||||
solve(viewer)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
igl.readOFF("../../tutorial/shared/cheburashka.off",V,F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F)
|
||||
|
||||
# Plot the mesh
|
||||
viewer = igl.viewer.Viewer()
|
||||
@@ -56,7 +64,7 @@ viewer.core.show_lines = False
|
||||
viewer.callback_key_down = key_down
|
||||
|
||||
# One fixed point on belly
|
||||
b = igl.eigen.MatrixXi([[2556]])
|
||||
b = igl.eigen.MatrixXi([[2556]])
|
||||
bc = igl.eigen.MatrixXd([[1]])
|
||||
|
||||
# Construct Laplacian and mass matrix
|
||||
@@ -64,19 +72,19 @@ L = igl.eigen.SparseMatrixd()
|
||||
M = igl.eigen.SparseMatrixd()
|
||||
Minv = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.cotmatrix(V,F,L)
|
||||
igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M);
|
||||
igl.invert_diag(M,Minv)
|
||||
igl.cotmatrix(V, F, L)
|
||||
igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M)
|
||||
igl.invert_diag(M, Minv)
|
||||
|
||||
# Bi-Laplacian
|
||||
Q = L.transpose() * (Minv * L)
|
||||
|
||||
# Zero linear term
|
||||
B = igl.eigen.MatrixXd.Zero(V.rows(),1)
|
||||
B = igl.eigen.MatrixXd.Zero(V.rows(), 1)
|
||||
|
||||
# Lower and upper bound
|
||||
lx = igl.eigen.MatrixXd.Zero(V.rows(),1)
|
||||
ux = igl.eigen.MatrixXd.Ones(V.rows(),1)
|
||||
lx = igl.eigen.MatrixXd.Zero(V.rows(), 1)
|
||||
ux = igl.eigen.MatrixXd.Ones(V.rows(), 1)
|
||||
|
||||
# Equality constraint constrain solution to sum to 1
|
||||
Beq = igl.eigen.MatrixXd([[0.08]])
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
U = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
@@ -12,7 +18,7 @@ c = 0
|
||||
bbd = 1.0
|
||||
twod = False
|
||||
|
||||
if not igl.read_triangle_mesh("../../tutorial/shared/beetle.off",V,F):
|
||||
if not igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "beetle.off", V, F):
|
||||
print("failed to load mesh")
|
||||
|
||||
twod = V.col(2).minCoeff() == V.col(2).maxCoeff()
|
||||
@@ -21,40 +27,42 @@ bbd = (V.colwiseMaxCoeff() - V.colwiseMinCoeff()).norm()
|
||||
L = igl.eigen.SparseMatrixd()
|
||||
M = igl.eigen.SparseMatrixd()
|
||||
|
||||
igl.cotmatrix(V,F,L)
|
||||
igl.cotmatrix(V, F, L)
|
||||
L = -L
|
||||
igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_DEFAULT,M)
|
||||
igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_DEFAULT, M)
|
||||
k = 5
|
||||
|
||||
D = igl.eigen.MatrixXd()
|
||||
if not igl.eigs(L,M,k+1,igl.EIGS_TYPE_SM,U,D):
|
||||
if not igl.eigs(L, M, k + 1, igl.EIGS_TYPE_SM, U, D):
|
||||
print("Eigs failed.")
|
||||
|
||||
U = (U-U.minCoeff())/(U.maxCoeff()-U.minCoeff());
|
||||
U = (U - U.minCoeff()) / (U.maxCoeff() - U.minCoeff())
|
||||
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
def key_down(viewer,key,mod):
|
||||
|
||||
def key_down(viewer, key, mod):
|
||||
global U, c
|
||||
|
||||
if key == ord(' '):
|
||||
U = U.rightCols(k)
|
||||
|
||||
# Rescale eigen vectors for visualization
|
||||
Z = bbd*0.5*U.col(c)
|
||||
Z = bbd * 0.5 * U.col(c)
|
||||
C = igl.eigen.MatrixXd()
|
||||
igl.parula(U.col(c),False,C)
|
||||
c = (c+1)%U.cols()
|
||||
igl.parula(U.col(c), False, C)
|
||||
c = (c + 1) % U.cols()
|
||||
|
||||
if twod:
|
||||
V.setcol(2,Z)
|
||||
V.setcol(2, Z)
|
||||
|
||||
viewer.data.set_mesh(V,F)
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.compute_normals()
|
||||
viewer.data.set_colors(C)
|
||||
return True
|
||||
|
||||
|
||||
viewer.callback_key_down = key_down
|
||||
viewer.callback_key_down(viewer,ord(' '),0);
|
||||
viewer.callback_key_down(viewer, ord(' '), 0)
|
||||
viewer.core.show_lines = False
|
||||
viewer.launch()
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
global bc_frac, bc_dir,deformation_field, V, U, V_bc, U_bc, F, b
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
bc_frac = 1.0
|
||||
bc_dir = -0.03
|
||||
deformation_field = False
|
||||
@@ -18,77 +22,79 @@ U_bc = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
b = igl.eigen.MatrixXi()
|
||||
|
||||
|
||||
def pre_draw(viewer):
|
||||
global bc_frac, bc_dir,deformation_field, V, U, V_bc, U_bc, F, b
|
||||
global bc_frac, bc_dir, deformation_field, V, U, V_bc, U_bc, F, b
|
||||
# Determine boundary conditions
|
||||
if (viewer.core.is_animating):
|
||||
bc_frac += bc_dir
|
||||
bc_dir *= (-1.0 if bc_frac>=1.0 or bc_frac <= 0.0 else 1.0)
|
||||
bc_dir *= (-1.0 if bc_frac >= 1.0 or bc_frac <= 0.0 else 1.0)
|
||||
|
||||
U_bc_anim = V_bc+bc_frac*(U_bc-V_bc)
|
||||
U_bc_anim = V_bc + bc_frac * (U_bc - V_bc)
|
||||
|
||||
if (deformation_field):
|
||||
D = igl.eigen.MatrixXd()
|
||||
D_bc = U_bc_anim - V_bc
|
||||
igl.harmonic(V,F,b,D_bc,2,D)
|
||||
U = V+D
|
||||
igl.harmonic(V, F, b, D_bc, 2, D)
|
||||
U = V + D
|
||||
else:
|
||||
igl.harmonic(V,F,b,U_bc_anim,2,U)
|
||||
igl.harmonic(V, F, b, U_bc_anim, 2, U)
|
||||
|
||||
viewer.data.set_vertices(U)
|
||||
viewer.data.compute_normals()
|
||||
return False
|
||||
|
||||
|
||||
def key_down(viewer, key, mods):
|
||||
global bc_frac, bc_dir,deformation_field, V, U, V_bc, U_bc, F, b
|
||||
global bc_frac, bc_dir, deformation_field, V, U, V_bc, U_bc, F, b
|
||||
|
||||
if key == ord(' '):
|
||||
viewer.core.is_animating = not viewer.core.is_animating
|
||||
return True
|
||||
if key == ord('D') or key == ord('d'):
|
||||
deformation_field = not deformation_field;
|
||||
deformation_field = not deformation_field
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
igl.readOBJ("../../tutorial/shared/decimated-max.obj",V,F)
|
||||
igl.readOBJ(TUTORIAL_SHARED_PATH + "decimated-max.obj", V, F)
|
||||
U = igl.eigen.MatrixXd(V)
|
||||
|
||||
# S(i) = j: j<0 (vertex i not in handle), j >= 0 (vertex i in handle j)
|
||||
S = igl.eigen.MatrixXd()
|
||||
igl.readDMAT("../../tutorial/shared/decimated-max-selection.dmat",S)
|
||||
igl.readDMAT(TUTORIAL_SHARED_PATH + "decimated-max-selection.dmat", S)
|
||||
|
||||
S = S.castint()
|
||||
|
||||
b = igl.eigen.MatrixXi([[t[0] for t in [(i,S[i]) for i in range(0,V.rows())] if t[1] >= 0]]).transpose()
|
||||
b = igl.eigen.MatrixXi([[t[0] for t in [(i, S[i]) for i in range(0, V.rows())] if t[1] >= 0]]).transpose()
|
||||
|
||||
# Boundary conditions directly on deformed positions
|
||||
U_bc.resize(b.rows(),V.cols())
|
||||
V_bc.resize(b.rows(),V.cols())
|
||||
U_bc.resize(b.rows(), V.cols())
|
||||
V_bc.resize(b.rows(), V.cols())
|
||||
|
||||
for bi in range(0,b.rows()):
|
||||
V_bc.setRow(bi,V.row(b[bi]))
|
||||
for bi in range(0, b.rows()):
|
||||
V_bc.setRow(bi, V.row(b[bi]))
|
||||
|
||||
if (S[b[bi]] == 0):
|
||||
if S[b[bi]] == 0:
|
||||
# Don't move handle 0
|
||||
U_bc.setRow(bi,V.row(b[bi]))
|
||||
U_bc.setRow(bi, V.row(b[bi]))
|
||||
elif S[b[bi]] == 1:
|
||||
# Move handle 1 down
|
||||
U_bc.setRow(bi,V.row(b[bi]) + igl.eigen.MatrixXd([[0,-50,0]]))
|
||||
U_bc.setRow(bi, V.row(b[bi]) + igl.eigen.MatrixXd([[0, -50, 0]]))
|
||||
else:
|
||||
# Move other handles forward
|
||||
U_bc.setRow(bi,V.row(b[bi]) + igl.eigen.MatrixXd([[0,0,-25]]))
|
||||
U_bc.setRow(bi, V.row(b[bi]) + igl.eigen.MatrixXd([[0, 0, -25]]))
|
||||
|
||||
# Pseudo-color based on selection
|
||||
C = igl.eigen.MatrixXd(F.rows(),3)
|
||||
purple = igl.eigen.MatrixXd([[80.0/255.0,64.0/255.0,255.0/255.0]])
|
||||
gold = igl.eigen.MatrixXd([[255.0/255.0,228.0/255.0,58.0/255.0]])
|
||||
C = igl.eigen.MatrixXd(F.rows(), 3)
|
||||
purple = igl.eigen.MatrixXd([[80.0 / 255.0, 64.0 / 255.0, 255.0 / 255.0]])
|
||||
gold = igl.eigen.MatrixXd([[255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0]])
|
||||
|
||||
for f in range(0,F.rows()):
|
||||
if (S[F[f,0]])>=0 and S[F[f,1]]>=0 and S[F[f,2]]>=0:
|
||||
C.setRow(f,purple)
|
||||
for f in range(0, F.rows()):
|
||||
if (S[F[f, 0]]) >= 0 and S[F[f, 1]] >= 0 and S[F[f, 2]] >= 0:
|
||||
C.setRow(f, purple)
|
||||
else:
|
||||
C.setRow(f,gold)
|
||||
C.setRow(f, gold)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
global z_max, z_dir, k, resolve, V, U, Z, F, b, bc
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
z_max = 1.0
|
||||
z_dir = -0.03
|
||||
k = 2
|
||||
resolve = True
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
U = igl.eigen.MatrixXd()
|
||||
|
||||
@@ -22,23 +25,25 @@ b = igl.eigen.MatrixXi()
|
||||
|
||||
bc = igl.eigen.MatrixXd()
|
||||
|
||||
|
||||
def pre_draw(viewer):
|
||||
global z_max, z_dir, k, resolve, V, U, Z, F, b, bc
|
||||
|
||||
if resolve:
|
||||
igl.harmonic(V,F,b,bc,k,Z)
|
||||
igl.harmonic(V, F, b, bc, k, Z)
|
||||
resolve = False
|
||||
|
||||
U.setCol(2,z_max*Z)
|
||||
U.setCol(2, z_max * Z)
|
||||
viewer.data.set_vertices(U)
|
||||
viewer.data.compute_normals()
|
||||
|
||||
if viewer.core.is_animating:
|
||||
z_max += z_dir
|
||||
z_dir *= (-1.0 if z_max>=1.0 or z_max<=0.0 else 1.0)
|
||||
z_dir *= (-1.0 if z_max >= 1.0 or z_max <= 0.0 else 1.0)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def key_down(viewer, key, mods):
|
||||
global z_max, z_dir, k, resolve, V, U, Z, F, b, bc
|
||||
|
||||
@@ -46,42 +51,42 @@ def key_down(viewer, key, mods):
|
||||
viewer.core.is_animating = not viewer.core.is_animating
|
||||
elif key == ord('.'):
|
||||
k = k + 1
|
||||
k = (4 if k>4 else k)
|
||||
k = (4 if k > 4 else k)
|
||||
resolve = True
|
||||
elif key == ord(','):
|
||||
k = k - 1
|
||||
k = (1 if k<1 else k)
|
||||
k = (1 if k < 1 else k)
|
||||
resolve = True
|
||||
return True
|
||||
|
||||
|
||||
igl.readOBJ("../../tutorial/shared/bump-domain.obj",V,F)
|
||||
igl.readOBJ(TUTORIAL_SHARED_PATH + "bump-domain.obj", V, F)
|
||||
U = igl.eigen.MatrixXd(V)
|
||||
|
||||
# Find boundary vertices outside annulus
|
||||
|
||||
Vrn = V.rowwiseNorm()
|
||||
is_outer = [Vrn[i]-1.00 > -1e-15 for i in range(0,V.rows())]
|
||||
is_inner = [Vrn[i]-0.15 < 1e-15 for i in range(0,V.rows())]
|
||||
in_b = [ is_outer[i] or is_inner[i] for i in range(0,len(is_outer))]
|
||||
is_outer = [Vrn[i] - 1.00 > -1e-15 for i in range(0, V.rows())]
|
||||
is_inner = [Vrn[i] - 0.15 < 1e-15 for i in range(0, V.rows())]
|
||||
in_b = [is_outer[i] or is_inner[i] for i in range(0, len(is_outer))]
|
||||
|
||||
b = igl.eigen.MatrixXi([[i for i in range(0,V.rows()) if (in_b[i])]]).transpose();
|
||||
b = igl.eigen.MatrixXi([[i for i in range(0, V.rows()) if (in_b[i])]]).transpose()
|
||||
|
||||
bc.resize(b.size(),1)
|
||||
bc.resize(b.size(), 1)
|
||||
|
||||
for bi in range(0,b.size()):
|
||||
for bi in range(0, b.size()):
|
||||
bc[bi] = (0.0 if is_outer[b[bi]] else 1.0)
|
||||
|
||||
# Pseudo-color based on selection
|
||||
C = igl.eigen.MatrixXd(F.rows(),3)
|
||||
purple = igl.eigen.MatrixXd([[80.0/255.0,64.0/255.0,255.0/255.0]])
|
||||
gold = igl.eigen.MatrixXd([[255.0/255.0,228.0/255.0,58.0/255.0]])
|
||||
C = igl.eigen.MatrixXd(F.rows(), 3)
|
||||
purple = igl.eigen.MatrixXd([[80.0 / 255.0, 64.0 / 255.0, 255.0 / 255.0]])
|
||||
gold = igl.eigen.MatrixXd([[255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0]])
|
||||
|
||||
for f in range(0,F.rows()):
|
||||
if( in_b[F[f,0]] and in_b[F[f,1]] and in_b[F[f,2]]):
|
||||
C.setRow(f,purple)
|
||||
for f in range(0, F.rows()):
|
||||
if in_b[F[f, 0]] and in_b[F[f, 1]] and in_b[F[f, 2]]:
|
||||
C.setRow(f, purple)
|
||||
else:
|
||||
C.setRow(f,gold)
|
||||
C.setRow(f, gold)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
@@ -97,4 +102,4 @@ viewer.core.animation_max_fps = 30.0
|
||||
print("Press [space] to toggle animation.")
|
||||
print("Press '.' to increase k.")
|
||||
print("Press ',' to decrease k.")
|
||||
viewer.launch();
|
||||
viewer.launch()
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
from math import sin, cos, pi
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
import pyigl as igl
|
||||
from math import sin,cos,pi
|
||||
|
||||
sea_green = igl.eigen.MatrixXd([[70./255.,252./255.,167./255.]])
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
sea_green = igl.eigen.MatrixXd([[70. / 255., 252. / 255., 167. / 255.]])
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
U = igl.eigen.MatrixXd()
|
||||
@@ -17,30 +23,31 @@ b = igl.eigen.MatrixXi()
|
||||
|
||||
mid = igl.eigen.MatrixXd()
|
||||
|
||||
anim_t = 0.0;
|
||||
anim_t_dir = 0.03;
|
||||
anim_t = 0.0
|
||||
anim_t_dir = 0.03
|
||||
arap_data = igl.ARAPData()
|
||||
|
||||
|
||||
def pre_draw(viewer):
|
||||
global anim_t
|
||||
|
||||
bc = igl.eigen.MatrixXd(b.size(),V.cols())
|
||||
for i in range(0,b.size()):
|
||||
bc.setRow(i,V.row(b[i]))
|
||||
bc = igl.eigen.MatrixXd(b.size(), V.cols())
|
||||
for i in range(0, b.size()):
|
||||
bc.setRow(i, V.row(b[i]))
|
||||
if S[b[i]] == 0:
|
||||
r = mid[0]*0.25
|
||||
bc[i,0] = bc[i,0] + r*sin(0.5*anim_t*2.*pi)
|
||||
bc[i,1] = bc[i,1] - r+r*cos(pi+0.5*anim_t*2.*pi)
|
||||
r = mid[0] * 0.25
|
||||
bc[i, 0] += r * sin(0.5 * anim_t * 2. * pi)
|
||||
bc[i, 1] = bc[i, 1] - r + r * cos(pi + 0.5 * anim_t * 2. * pi)
|
||||
elif S[b[i]] == 1:
|
||||
r = mid[1]*0.15
|
||||
bc[i,1] = bc[i,1] + r + r*cos(pi + 0.15*anim_t*2.*pi)
|
||||
bc[i,2] = bc[i,2] - r*sin(0.15*anim_t*2.*pi)
|
||||
r = mid[1] * 0.15
|
||||
bc[i, 1] = bc[i, 1] + r + r * cos(pi + 0.15 * anim_t * 2. * pi)
|
||||
bc[i, 2] -= r * sin(0.15 * anim_t * 2. * pi)
|
||||
elif S[b[i]] == 2:
|
||||
r = mid[1]*0.15
|
||||
bc[i,2] = bc[i,2] + r+r*cos(pi+0.35*anim_t*2.*pi)
|
||||
bc[i,0] = bc[i,0] + r*sin(0.35*anim_t*2.*pi)
|
||||
r = mid[1] * 0.15
|
||||
bc[i, 2] = bc[i, 2] + r + r * cos(pi + 0.35 * anim_t * 2. * pi)
|
||||
bc[i, 0] += r * sin(0.35 * anim_t * 2. * pi)
|
||||
|
||||
igl.arap_solve(bc,arap_data,U)
|
||||
igl.arap_solve(bc, arap_data, U)
|
||||
viewer.data.set_vertices(U)
|
||||
viewer.data.compute_normals()
|
||||
|
||||
@@ -49,37 +56,39 @@ def pre_draw(viewer):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def key_down(viewer, key, mods):
|
||||
if key == ord(' '):
|
||||
viewer.core.is_animating = not viewer.core.is_animating
|
||||
return True
|
||||
return False
|
||||
|
||||
igl.readOFF("../../tutorial/shared/decimated-knight.off",V,F)
|
||||
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", V, F)
|
||||
U = igl.eigen.MatrixXd(V)
|
||||
igl.readDMAT("../../tutorial/shared/decimated-knight-selection.dmat",S)
|
||||
igl.readDMAT(TUTORIAL_SHARED_PATH + "decimated-knight-selection.dmat", S)
|
||||
|
||||
# Vertices in selection
|
||||
|
||||
b = igl.eigen.MatrixXi([[t[0] for t in [(i,S[i]) for i in range(0,V.rows())] if t[1] >= 0]]).transpose()
|
||||
b = igl.eigen.MatrixXi([[t[0] for t in [(i, S[i]) for i in range(0, V.rows())] if t[1] >= 0]]).transpose()
|
||||
|
||||
# Centroid
|
||||
mid = 0.5*(V.colwiseMaxCoeff() + V.colwiseMinCoeff())
|
||||
mid = 0.5 * (V.colwiseMaxCoeff() + V.colwiseMinCoeff())
|
||||
|
||||
# Precomputation
|
||||
arap_data.max_iter = 100
|
||||
igl.arap_precomputation(V,F,V.cols(),b,arap_data)
|
||||
igl.arap_precomputation(V, F, V.cols(), b, arap_data)
|
||||
|
||||
# Set color based on selection
|
||||
C = igl.eigen.MatrixXd(F.rows(),3)
|
||||
purple = igl.eigen.MatrixXd([[80.0/255.0,64.0/255.0,255.0/255.0]])
|
||||
gold = igl.eigen.MatrixXd([[255.0/255.0,228.0/255.0,58.0/255.0]])
|
||||
C = igl.eigen.MatrixXd(F.rows(), 3)
|
||||
purple = igl.eigen.MatrixXd([[80.0 / 255.0, 64.0 / 255.0, 255.0 / 255.0]])
|
||||
gold = igl.eigen.MatrixXd([[255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0]])
|
||||
|
||||
for f in range(0,F.rows()):
|
||||
if S[F[f,0]]>=0 and S[F[f,1]]>=0 and S[F[f,2]]>=0:
|
||||
C.setRow(f,purple)
|
||||
for f in range(0, F.rows()):
|
||||
if S[F[f, 0]] >= 0 and S[F[f, 1]] >= 0 and S[F[f, 2]] >= 0:
|
||||
C.setRow(f, purple)
|
||||
else:
|
||||
C.setRow(f,gold)
|
||||
C.setRow(f, gold)
|
||||
|
||||
# Plot the mesh with pseudocolors
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,41 +1,49 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
V_uv = igl.eigen.MatrixXd()
|
||||
|
||||
|
||||
def key_down(viewer, key, modifier):
|
||||
if key == ord('1'):
|
||||
# Plot the 3D mesh
|
||||
viewer.data.set_mesh(V,F)
|
||||
viewer.core.align_camera_center(V,F)
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.core.align_camera_center(V, F)
|
||||
elif key == ord('2'):
|
||||
# Plot the mesh in 2D using the UV coordinates as vertex coordinates
|
||||
viewer.data.set_mesh(V_uv,F)
|
||||
viewer.core.align_camera_center(V_uv,F)
|
||||
viewer.data.set_mesh(V_uv, F)
|
||||
viewer.core.align_camera_center(V_uv, F)
|
||||
viewer.data.compute_normals()
|
||||
return False
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/camelhead.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F)
|
||||
|
||||
# Find the open boundary
|
||||
bnd = igl.eigen.MatrixXi()
|
||||
igl.boundary_loop(F,bnd)
|
||||
igl.boundary_loop(F, bnd)
|
||||
|
||||
# Map the boundary to a circle, preserving edge proportions
|
||||
bnd_uv = igl.eigen.MatrixXd()
|
||||
igl.map_vertices_to_circle(V,bnd,bnd_uv)
|
||||
igl.map_vertices_to_circle(V, bnd, bnd_uv)
|
||||
|
||||
# Harmonic parametrization for the internal vertices
|
||||
igl.harmonic(V,F,bnd,bnd_uv,1,V_uv)
|
||||
igl.harmonic(V, F, bnd, bnd_uv, 1, V_uv)
|
||||
|
||||
# Scale UV to make the texture more clear
|
||||
V_uv *= 5;
|
||||
V_uv *= 5
|
||||
|
||||
# Plot the mesh
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
@@ -1,39 +1,47 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
V_uv = igl.eigen.MatrixXd()
|
||||
|
||||
|
||||
def key_down(viewer, key, modifier):
|
||||
if key == ord('1'):
|
||||
# Plot the 3D mesh
|
||||
viewer.data.set_mesh(V,F)
|
||||
viewer.core.align_camera_center(V,F)
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.core.align_camera_center(V, F)
|
||||
elif key == ord('2'):
|
||||
# Plot the mesh in 2D using the UV coordinates as vertex coordinates
|
||||
viewer.data.set_mesh(V_uv,F)
|
||||
viewer.core.align_camera_center(V_uv,F)
|
||||
viewer.data.set_mesh(V_uv, F)
|
||||
viewer.core.align_camera_center(V_uv, F)
|
||||
viewer.data.compute_normals()
|
||||
return False
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/camelhead.off", V, F);
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F)
|
||||
|
||||
# Fix two points on the boundary
|
||||
bnd = igl.eigen.MatrixXi()
|
||||
b = igl.eigen.MatrixXi(2,1)
|
||||
b = igl.eigen.MatrixXi(2, 1)
|
||||
|
||||
igl.boundary_loop(F,bnd)
|
||||
igl.boundary_loop(F, bnd)
|
||||
b[0] = bnd[0]
|
||||
b[1] = bnd[int(bnd.size()/2)]
|
||||
bc = igl.eigen.MatrixXd([[0,0],[1,0]])
|
||||
b[1] = bnd[int(bnd.size() / 2)]
|
||||
bc = igl.eigen.MatrixXd([[0, 0], [1, 0]])
|
||||
|
||||
# LSCM parametrization
|
||||
igl.lscm(V,F,b,bc,V_uv)
|
||||
igl.lscm(V, F, b, bc, V_uv)
|
||||
|
||||
# Scale the uv
|
||||
V_uv *= 5
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
V_uv = igl.eigen.MatrixXd()
|
||||
@@ -11,6 +17,7 @@ initial_guess = igl.eigen.MatrixXd()
|
||||
|
||||
show_uv = False
|
||||
|
||||
|
||||
def key_down(viewer, key, modifier):
|
||||
global show_uv, V_uv
|
||||
if key == ord('1'):
|
||||
@@ -20,43 +27,44 @@ def key_down(viewer, key, modifier):
|
||||
elif key == ord('q'):
|
||||
V_uv = initial_guess
|
||||
|
||||
if (show_uv):
|
||||
viewer.data.set_mesh(V_uv,F)
|
||||
viewer.core.align_camera_center(V_uv,F)
|
||||
if show_uv:
|
||||
viewer.data.set_mesh(V_uv, F)
|
||||
viewer.core.align_camera_center(V_uv, F)
|
||||
else:
|
||||
viewer.data.set_mesh(V,F)
|
||||
viewer.core.align_camera_center(V,F)
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.core.align_camera_center(V, F)
|
||||
|
||||
viewer.data.compute_normals()
|
||||
return False
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/camelhead.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F)
|
||||
|
||||
# Compute the initial solution for ARAP (harmonic parametrization)
|
||||
bnd = igl.eigen.MatrixXi()
|
||||
igl.boundary_loop(F,bnd)
|
||||
igl.boundary_loop(F, bnd)
|
||||
bnd_uv = igl.eigen.MatrixXd()
|
||||
igl.map_vertices_to_circle(V,bnd,bnd_uv)
|
||||
igl.map_vertices_to_circle(V, bnd, bnd_uv)
|
||||
|
||||
igl.harmonic(V,F,bnd,bnd_uv,1,initial_guess)
|
||||
igl.harmonic(V, F, bnd, bnd_uv, 1, initial_guess)
|
||||
|
||||
# Add dynamic regularization to avoid to specify boundary conditions
|
||||
arap_data = igl.ARAPData()
|
||||
arap_data.with_dynamics = True
|
||||
b = igl.eigen.MatrixXi.Zero(0,0);
|
||||
bc = igl.eigen.MatrixXd.Zero(0,0);
|
||||
b = igl.eigen.MatrixXi.Zero(0, 0)
|
||||
bc = igl.eigen.MatrixXd.Zero(0, 0)
|
||||
|
||||
# Initialize ARAP
|
||||
arap_data.max_iter = 100
|
||||
|
||||
# 2 means that we're going to *solve* in 2d
|
||||
igl.arap_precomputation(V,F,2,b,arap_data)
|
||||
igl.arap_precomputation(V, F, 2, b, arap_data)
|
||||
|
||||
# Solve arap using the harmonic map as initial guess
|
||||
V_uv = igl.eigen.MatrixXd(initial_guess) # important, make a copy of it!
|
||||
V_uv = igl.eigen.MatrixXd(initial_guess) # important, make a copy of it!
|
||||
|
||||
igl.arap_solve(bc,arap_data,V_uv)
|
||||
igl.arap_solve(bc, arap_data, V_uv)
|
||||
|
||||
# Scale UV to make the texture more clear
|
||||
V_uv *= 20
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
from math import atan2, pi, cos, sin
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
from math import atan2,pi,cos,sin
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["comiso", "viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
# Mesh
|
||||
V = igl.eigen.MatrixXd()
|
||||
@@ -16,7 +22,8 @@ b = igl.eigen.MatrixXi()
|
||||
bc = igl.eigen.MatrixXd()
|
||||
|
||||
# Degree of the N-RoSy field
|
||||
N = 4;
|
||||
N = 4
|
||||
|
||||
|
||||
# Converts a representative vector per face in the full set of vectors that describe
|
||||
# an N-RoSy field
|
||||
@@ -25,27 +32,28 @@ def representative_to_nrosy(V, F, R, N, Y):
|
||||
B2 = igl.eigen.MatrixXd()
|
||||
B3 = igl.eigen.MatrixXd()
|
||||
|
||||
igl.local_basis(V,F,B1,B2,B3)
|
||||
igl.local_basis(V, F, B1, B2, B3)
|
||||
|
||||
Y.resize(F.rows()*N, 3)
|
||||
Y.resize(F.rows() * N, 3)
|
||||
|
||||
for i in range (0,F.rows()):
|
||||
for i in range(0, F.rows()):
|
||||
x = R.row(i) * B1.row(i).transpose()
|
||||
y = R.row(i) * B2.row(i).transpose()
|
||||
angle = atan2(y[0],x[0])
|
||||
angle = atan2(y[0], x[0])
|
||||
|
||||
for j in range(0,N):
|
||||
anglej = angle + 2*pi*j/float(N)
|
||||
for j in range(0, N):
|
||||
anglej = angle + 2 * pi * j / float(N)
|
||||
xj = cos(anglej)
|
||||
yj = sin(anglej)
|
||||
Y.setRow(i*N+j, xj * B1.row(i) + yj * B2.row(i))
|
||||
Y.setRow(i * N + j, xj * B1.row(i) + yj * B2.row(i))
|
||||
|
||||
|
||||
# Plots the mesh with an N-RoSy field and its singularities on top
|
||||
# The constrained faces (b) are colored in red.
|
||||
def plot_mesh_nrosy(viewer, V, F, N, PD1, S, b):
|
||||
# Clear the mesh
|
||||
viewer.data.clear()
|
||||
viewer.data.set_mesh(V,F)
|
||||
viewer.data.set_mesh(V, F)
|
||||
|
||||
# Expand the representative vectors in the full vector set and plot them as lines
|
||||
avg = igl.avg_edge_length(V, F)
|
||||
@@ -53,48 +61,50 @@ def plot_mesh_nrosy(viewer, V, F, N, PD1, S, b):
|
||||
representative_to_nrosy(V, F, PD1, N, Y)
|
||||
|
||||
B = igl.eigen.MatrixXd()
|
||||
igl.barycenter(V,F,B)
|
||||
igl.barycenter(V, F, B)
|
||||
|
||||
Be = igl.eigen.MatrixXd(B.rows()*N,3)
|
||||
for i in range(0,B.rows()):
|
||||
for j in range(0,N):
|
||||
Be.setRow(i*N+j,B.row(i))
|
||||
Be = igl.eigen.MatrixXd(B.rows() * N, 3)
|
||||
for i in range(0, B.rows()):
|
||||
for j in range(0, N):
|
||||
Be.setRow(i * N + j, B.row(i))
|
||||
|
||||
viewer.data.add_edges(Be,Be+Y*(avg/2),igl.eigen.MatrixXd([[0,0,1]]))
|
||||
viewer.data.add_edges(Be, Be + Y * (avg / 2), igl.eigen.MatrixXd([[0, 0, 1]]))
|
||||
|
||||
# Plot the singularities as colored dots (red for negative, blue for positive)
|
||||
for i in range(0,S.size()):
|
||||
for i in range(0, S.size()):
|
||||
if S[i] < -0.001:
|
||||
viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
elif S[i] > 0.001:
|
||||
viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[0,1,0]]));
|
||||
viewer.data.add_points(V.row(i), igl.eigen.MatrixXd([[0, 1, 0]]));
|
||||
|
||||
# Highlight in red the constrained faces
|
||||
C = igl.eigen.MatrixXd.Constant(F.rows(),3,1)
|
||||
for i in range(0,b.size()):
|
||||
C = igl.eigen.MatrixXd.Constant(F.rows(), 3, 1)
|
||||
for i in range(0, b.size()):
|
||||
C.setRow(b[i], igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
|
||||
# It allows to change the degree of the field when a number is pressed
|
||||
def key_down(viewer, key, modifier):
|
||||
global N
|
||||
if key >= ord('1') and key <= ord('9'):
|
||||
if ord('1') <= key <= ord('9'):
|
||||
N = key - ord('0')
|
||||
|
||||
R = igl.eigen.MatrixXd()
|
||||
S = igl.eigen.MatrixXd()
|
||||
|
||||
igl.comiso.nrosy(V,F,b,bc,igl.eigen.MatrixXi(),igl.eigen.MatrixXd(),igl.eigen.MatrixXd(),N,0.5,R,S)
|
||||
plot_mesh_nrosy(viewer,V,F,N,R,S,b)
|
||||
igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), N, 0.5, R, S)
|
||||
plot_mesh_nrosy(viewer, V, F, N, R, S, b)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/bumpy.off", V, F);
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F)
|
||||
|
||||
# Threshold faces with high anisotropy
|
||||
b = igl.eigen.MatrixXi([[0]])
|
||||
bc = igl.eigen.MatrixXd([[1,1,1]])
|
||||
b = igl.eigen.MatrixXi([[0]])
|
||||
bc = igl.eigen.MatrixXd([[1, 1, 1]])
|
||||
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
|
||||
+77
-87
@@ -1,10 +1,16 @@
|
||||
# Add the igl library to the modules search path
|
||||
import sys, os
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
import pyigl as igl
|
||||
from math import pi
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["comiso", "viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
@@ -13,7 +19,7 @@ B = igl.eigen.MatrixXd()
|
||||
|
||||
# Scale for visualizing the fields
|
||||
global_scale = 1
|
||||
extend_arrows = False;
|
||||
extend_arrows = False
|
||||
|
||||
# Cross field
|
||||
X1 = igl.eigen.MatrixXd()
|
||||
@@ -54,25 +60,27 @@ texture_R = igl.eigen.MatrixXuc()
|
||||
texture_G = igl.eigen.MatrixXuc()
|
||||
texture_B = igl.eigen.MatrixXuc()
|
||||
|
||||
|
||||
# Create a texture that hides the integer translation in the parametrization
|
||||
def line_texture():
|
||||
size = 128
|
||||
size2 = int(size/2)
|
||||
size2 = int(size / 2)
|
||||
lineWidth = 3
|
||||
texture_R.setConstant(size, size, 255)
|
||||
|
||||
for i in range(0,size):
|
||||
for j in range(size2-lineWidth,size2+lineWidth+1):
|
||||
texture_R[i,j] = 0
|
||||
for i in range(0, size):
|
||||
for j in range(size2 - lineWidth, size2 + lineWidth + 1):
|
||||
texture_R[i, j] = 0
|
||||
|
||||
for i in range(size2-lineWidth,size2+lineWidth+1):
|
||||
for j in range(0,size):
|
||||
texture_R[i,j] = 0
|
||||
for i in range(size2 - lineWidth, size2 + lineWidth + 1):
|
||||
for j in range(0, size):
|
||||
texture_R[i, j] = 0
|
||||
|
||||
texture_G = texture_R.copy()
|
||||
texture_B = texture_R.copy()
|
||||
return (texture_R, texture_G, texture_B)
|
||||
|
||||
|
||||
def key_down(viewer, key, modifier):
|
||||
global extend_arrows, texture_R, texture_G, texture_B
|
||||
|
||||
@@ -80,7 +88,7 @@ def key_down(viewer, key, modifier):
|
||||
extend_arrows = not extend_arrows
|
||||
|
||||
if key < ord('1') or key > ord('8'):
|
||||
return False;
|
||||
return False
|
||||
|
||||
viewer.data.clear()
|
||||
viewer.core.show_lines = False
|
||||
@@ -89,20 +97,26 @@ def key_down(viewer, key, modifier):
|
||||
if key == ord('1'):
|
||||
# Cross field
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.add_edges(B - global_scale*X1 if extend_arrows else B, B + global_scale*X1 , igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_edges(B - global_scale*X2 if extend_arrows else B, B + global_scale*X2 , igl.eigen.MatrixXd([[0,0,1]]))
|
||||
viewer.data.add_edges(B - global_scale * X1 if extend_arrows else B, B + global_scale * X1,
|
||||
igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
viewer.data.add_edges(B - global_scale * X2 if extend_arrows else B, B + global_scale * X2,
|
||||
igl.eigen.MatrixXd([[0, 0, 1]]))
|
||||
|
||||
if key == ord('2'):
|
||||
# Bisector field
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.add_edges(B - global_scale*BIS1 if extend_arrows else B, B + global_scale*BIS1 , igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_edges(B - global_scale*BIS2 if extend_arrows else B, B + global_scale*BIS2 , igl.eigen.MatrixXd([[0,0,1]]))
|
||||
viewer.data.add_edges(B - global_scale * BIS1 if extend_arrows else B, B + global_scale * BIS1,
|
||||
igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
viewer.data.add_edges(B - global_scale * BIS2 if extend_arrows else B, B + global_scale * BIS2,
|
||||
igl.eigen.MatrixXd([[0, 0, 1]]))
|
||||
|
||||
if key == ord('3'):
|
||||
# Bisector field combed
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.add_edges(B - global_scale*BIS1_combed if extend_arrows else B, B + global_scale*BIS1_combed , igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_edges(B - global_scale*BIS2_combed if extend_arrows else B, B + global_scale*BIS2_combed , igl.eigen.MatrixXd([[0,0,1]]))
|
||||
viewer.data.add_edges(B - global_scale * BIS1_combed if extend_arrows else B, B + global_scale * BIS1_combed,
|
||||
igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
viewer.data.add_edges(B - global_scale * BIS2_combed if extend_arrows else B, B + global_scale * BIS2_combed,
|
||||
igl.eigen.MatrixXd([[0, 0, 1]]))
|
||||
|
||||
if key == ord('4'):
|
||||
# Singularities and cuts
|
||||
@@ -110,53 +124,55 @@ def key_down(viewer, key, modifier):
|
||||
|
||||
# Plot cuts
|
||||
l_count = Seams.sum()
|
||||
P1 = igl.eigen.MatrixXd(l_count,3)
|
||||
P2 = igl.eigen.MatrixXd(l_count,3)
|
||||
P1 = igl.eigen.MatrixXd(l_count, 3)
|
||||
P2 = igl.eigen.MatrixXd(l_count, 3)
|
||||
|
||||
for i in range(0,Seams.rows()):
|
||||
for j in range(0,Seams.cols()):
|
||||
if Seams[i,j] != 0:
|
||||
P1.setRow(l_count-1, V.row(F[i,j]))
|
||||
P2.setRow(l_count-1, V.row(F[i,(j+1)%3]))
|
||||
l_count = l_count - 1
|
||||
for i in range(0, Seams.rows()):
|
||||
for j in range(0, Seams.cols()):
|
||||
if Seams[i, j] != 0:
|
||||
P1.setRow(l_count - 1, V.row(F[i, j]))
|
||||
P2.setRow(l_count - 1, V.row(F[i, (j + 1) % 3]))
|
||||
l_count -= 1
|
||||
|
||||
viewer.data.add_edges(P1, P2, igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
|
||||
# Plot the singularities as colored dots (red for negative, blue for positive)
|
||||
for i in range(0,singularityIndex.size()):
|
||||
if singularityIndex[i] < 2 and singularityIndex[i] > 0:
|
||||
viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[1,0,0]]))
|
||||
for i in range(0, singularityIndex.size()):
|
||||
if 2 > singularityIndex[i] > 0:
|
||||
viewer.data.add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
elif singularityIndex[i] > 2:
|
||||
viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
|
||||
if key == ord('5'):
|
||||
# Singularities and cuts, original field
|
||||
# Singularities and cuts
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.add_edges(B - global_scale*X1_combed if extend_arrows else B, B + global_scale*X1_combed ,igl.eigen.MatrixXd([[1,0,0]]))
|
||||
viewer.data.add_edges(B - global_scale*X2_combed if extend_arrows else B, B + global_scale*X2_combed ,igl.eigen.MatrixXd([[0,0,1]]))
|
||||
viewer.data.add_edges(B - global_scale * X1_combed if extend_arrows else B, B + global_scale * X1_combed,
|
||||
igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
viewer.data.add_edges(B - global_scale * X2_combed if extend_arrows else B, B + global_scale * X2_combed,
|
||||
igl.eigen.MatrixXd([[0, 0, 1]]))
|
||||
|
||||
# Plot cuts
|
||||
l_count = Seams.sum()
|
||||
|
||||
P1 = igl.eigen.MatrixXd(l_count,3)
|
||||
P2 = igl.eigen.MatrixXd(l_count,3)
|
||||
P1 = igl.eigen.MatrixXd(l_count, 3)
|
||||
P2 = igl.eigen.MatrixXd(l_count, 3)
|
||||
|
||||
for i in range(0, Seams.rows()):
|
||||
for j in range(0, Seams.cols()):
|
||||
if Seams[i,j] != 0:
|
||||
P1.setRow(l_count-1,V.row(F[i,j]))
|
||||
P2.setRow(l_count-1,V.row(F[i,(j+1)%3]))
|
||||
l_count = l_count - 1
|
||||
if Seams[i, j] != 0:
|
||||
P1.setRow(l_count - 1, V.row(F[i, j]))
|
||||
P2.setRow(l_count - 1, V.row(F[i, (j + 1) % 3]))
|
||||
l_count -= 1
|
||||
|
||||
viewer.data.add_edges(P1, P2, igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
|
||||
# Plot the singularities as colored dots (red for negative, blue for positive)
|
||||
for i in range(0,singularityIndex.size()):
|
||||
if singularityIndex[i] < 2 and singularityIndex[i] > 0:
|
||||
viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[1,0,0]]))
|
||||
for i in range(0, singularityIndex.size()):
|
||||
if 2 > singularityIndex[i] > 0:
|
||||
viewer.data.add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]]))
|
||||
elif singularityIndex[i] > 2:
|
||||
viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[0,1,0]]))
|
||||
viewer.data.add_points(V.row(i), igl.eigen.MatrixXd([[0, 1, 0]]))
|
||||
|
||||
if key == ord('6'):
|
||||
# Global parametrization UV
|
||||
@@ -167,49 +183,50 @@ def key_down(viewer, key, modifier):
|
||||
if key == ord('7'):
|
||||
# Global parametrization in 3D
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.set_uv(UV,FUV)
|
||||
viewer.data.set_uv(UV, FUV)
|
||||
viewer.core.show_texture = True
|
||||
|
||||
if key == ord('8'):
|
||||
# Global parametrization in 3D with seams
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.data.set_uv(UV_seams,FUV_seams)
|
||||
viewer.data.set_uv(UV_seams, FUV_seams)
|
||||
viewer.core.show_texture = True
|
||||
|
||||
viewer.data.set_colors(igl.eigen.MatrixXd([[1,1,1]]))
|
||||
viewer.data.set_colors(igl.eigen.MatrixXd([[1, 1, 1]]))
|
||||
|
||||
viewer.data.set_texture(texture_R, texture_B, texture_G)
|
||||
|
||||
viewer.core.align_camera_center(viewer.data.V,viewer.data.F)
|
||||
viewer.core.align_camera_center(viewer.data.V, viewer.data.F)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF("../../tutorial/shared/3holes.off", V, F)
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "3holes.off", V, F)
|
||||
|
||||
# Compute face barycenters
|
||||
igl.barycenter(V, F, B)
|
||||
|
||||
# Compute scale for visualizing fields
|
||||
global_scale = .5*igl.avg_edge_length(V, F)
|
||||
global_scale = .5 * igl.avg_edge_length(V, F)
|
||||
|
||||
# Contrain one face
|
||||
b = igl.eigen.MatrixXi([[0]])
|
||||
bc = igl.eigen.MatrixXd([[1,0,0]])
|
||||
b = igl.eigen.MatrixXi([[0]])
|
||||
bc = igl.eigen.MatrixXd([[1, 0, 0]])
|
||||
|
||||
# Create a smooth 4-RoSy field
|
||||
S = igl.eigen.MatrixXd()
|
||||
|
||||
igl.comiso.nrosy(V,F,b,bc,igl.eigen.MatrixXi(),igl.eigen.MatrixXd(),igl.eigen.MatrixXd(),4,0.5,X1,S)
|
||||
igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), 4, 0.5, X1, S)
|
||||
|
||||
# Find the the orthogonal vector
|
||||
B1 = igl.eigen.MatrixXd()
|
||||
B2 = igl.eigen.MatrixXd()
|
||||
B3 = igl.eigen.MatrixXd()
|
||||
|
||||
igl.local_basis(V,F,B1,B2,B3)
|
||||
igl.local_basis(V, F, B1, B2, B3)
|
||||
|
||||
X2 = igl.rotate_vectors(X1, igl.eigen.MatrixXd.Constant(1,1,pi/2), B1, B2)
|
||||
X2 = igl.rotate_vectors(X1, igl.eigen.MatrixXd.Constant(1, 1, pi / 2), B1, B2)
|
||||
|
||||
gradient_size = 50
|
||||
iterations = 0
|
||||
@@ -226,7 +243,7 @@ igl.comb_cross_field(V, F, BIS1, BIS2, BIS1_combed, BIS2_combed)
|
||||
igl.cross_field_missmatch(V, F, BIS1_combed, BIS2_combed, True, MMatch)
|
||||
|
||||
# Find the singularities
|
||||
igl.find_cross_field_singularities(V, F, MMatch, isSingularity, singularityIndex);
|
||||
igl.find_cross_field_singularities(V, F, MMatch, isSingularity, singularityIndex)
|
||||
|
||||
# Cut the mesh, duplicating all vertices on the seams
|
||||
igl.cut_mesh_from_singularities(V, F, MMatch, Seams)
|
||||
@@ -235,39 +252,12 @@ igl.cut_mesh_from_singularities(V, F, MMatch, Seams)
|
||||
igl.comb_frame_field(V, F, X1, X2, BIS1_combed, BIS2_combed, X1_combed, X2_combed)
|
||||
|
||||
# Global parametrization
|
||||
igl.comiso.miq(V,
|
||||
F,
|
||||
X1_combed,
|
||||
X2_combed,
|
||||
MMatch,
|
||||
isSingularity,
|
||||
Seams,
|
||||
UV,
|
||||
FUV,
|
||||
gradient_size,
|
||||
stiffness,
|
||||
direct_round,
|
||||
iterations,
|
||||
5,
|
||||
True,
|
||||
True);
|
||||
igl.comiso.miq(V, F, X1_combed, X2_combed, MMatch, isSingularity, Seams, UV, FUV, gradient_size, stiffness,
|
||||
direct_round, iterations, 5, True, True)
|
||||
|
||||
# Global parametrization (with seams, only for demonstration)
|
||||
igl.comiso.miq(V,
|
||||
F,
|
||||
X1_combed,
|
||||
X2_combed,
|
||||
MMatch,
|
||||
isSingularity,
|
||||
Seams,
|
||||
UV_seams,
|
||||
FUV_seams,
|
||||
gradient_size,
|
||||
stiffness,
|
||||
direct_round,
|
||||
iterations,
|
||||
5,
|
||||
False);
|
||||
igl.comiso.miq(V, F, X1_combed, X2_combed, MMatch, isSingularity, Seams, UV_seams, FUV_seams, gradient_size,
|
||||
stiffness, direct_round, iterations, 5, False)
|
||||
|
||||
# Plot the mesh
|
||||
viewer = igl.viewer.Viewer()
|
||||
@@ -276,7 +266,7 @@ viewer = igl.viewer.Viewer()
|
||||
(texture_R, texture_G, texture_B) = line_texture()
|
||||
|
||||
# Plot the original mesh with a texture parametrization
|
||||
key_down(viewer,ord('7'),0)
|
||||
key_down(viewer, ord('7'), 0)
|
||||
|
||||
# Launch the viewer
|
||||
viewer.callback_key_down = key_down
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import sys, os
|
||||
import random
|
||||
from math import cos, sin, pi
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
@@ -12,7 +10,6 @@ dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
|
||||
viewer = igl.viewer.Viewer()
|
||||
|
||||
# Quad mesh generated from conjugate field
|
||||
|
||||
@@ -9,6 +9,7 @@ from shared import check_dependencies
|
||||
dependencies = ["triangle", "viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
# Input polygon
|
||||
V = igl.eigen.MatrixXd([[-1, -1], [1, -1], [1, 1], [-1, 1], [-2, -2], [2, -2], [2, 2], [-2, 2]])
|
||||
E = igl.eigen.MatrixXi([[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6,7], [7,4]])
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import sys, os
|
||||
import math
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
|
||||
@@ -5,16 +5,12 @@ import math
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
|
||||
from iglhelpers import e2p
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
|
||||
|
||||
global V, F, T, tree, FN, VN, EN, E, EMAP, max_distance, slice_z, overlay
|
||||
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
T = igl.eigen.MatrixXi()
|
||||
@@ -133,7 +129,7 @@ igl.per_vertex_normals(V, F, igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE, FN, VN
|
||||
igl.per_edge_normals(V, F, igl.PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM, FN, EN, E, EMAP)
|
||||
|
||||
# Plot the generated mesh
|
||||
update_visualization(viewer);
|
||||
update_visualization(viewer)
|
||||
viewer.callback_key_down = key_down
|
||||
viewer.core.show_lines = False
|
||||
viewer.launch()
|
||||
|
||||
Reference in New Issue
Block a user