Cleaned up python tutorials and added dependency checks to all tutorials

This commit is contained in:
Sebastian Koch
2016-06-07 16:28:06 +02:00
parent dfbb411d9d
commit 246017f041
30 changed files with 621 additions and 513 deletions
+2 -9
View File
@@ -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='')
+3 -2
View File
@@ -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='')
+1
View File
@@ -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()
+11 -10
View File
@@ -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()
+16 -10
View File
@@ -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")
+11 -5
View File
@@ -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)
+42 -37
View File
@@ -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()
+20 -12
View File
@@ -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()
+13 -7
View File
@@ -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()
+24 -19
View File
@@ -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()
+18 -12
View File
@@ -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
+34 -34
View File
@@ -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
+15 -11
View File
@@ -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()
+14 -8
View File
@@ -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()
+25 -20
View File
@@ -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.")
+31 -23
View File
@@ -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]])
+22 -14
View File
@@ -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()
+35 -29
View File
@@ -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()
+29 -24
View File
@@ -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()
+40 -31
View File
@@ -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()
+19 -11
View File
@@ -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()
+20 -12
View File
@@ -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
+24 -16
View File
@@ -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
+39 -29
View File
@@ -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
View File
@@ -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
-3
View File
@@ -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
+1
View File
@@ -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
View File
@@ -1,5 +1,4 @@
import sys, os
import math
# Add the igl library to the modules search path
sys.path.insert(0, os.getcwd() + "/../")
+1 -5
View File
@@ -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()