Exemplo n.º 1
0
 def transformColors(c, colormap):
     if colormap == "jet":
         color = igl.eigen.MatrixXd()
         igl.jet(p2e(c.astype(np.float64)), True, color)
     else:
         # colormap: "blue", "red", "green", "default"
         color = colorMap(c, colormap=colormap)
         color = p2e(color.astype(np.float64))
     return color
def solve(viewer):
    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)

    C = igl.eigen.MatrixXd()
    igl.jet(Z, 0, 1, C)
    viewer.data.set_colors(C)
Exemplo n.º 3
0
def solve(viewer):
    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)

    C = igl.eigen.MatrixXd()
    igl.jet(Z,0,1,C)
    viewer.data.set_colors(C)
Exemplo n.º 4
0
def key_down(viewer, key, modifier):
    if key == ord('1'):
        # Draw the triangulated quad mesh
        viewer.data().set_mesh(VQC, FQCtri)

        # Assign a color to each quad that corresponds to its planarity
        planarity = igl.eigen.MatrixXd()
        igl.quad_planarity(VQC, FQC, planarity)
        Ct = igl.eigen.MatrixXd()
        igl.jet(planarity, 0, 0.01, Ct)
        C = igl.eigen.MatrixXd(FQCtri.rows(), 3)
        C.setTopRows(Ct.rows(), Ct)
        C.setBottomRows(Ct.rows(), Ct)
        viewer.data().set_colors(C)

        # Plot a line for each edge of the quad mesh
        viewer.data().add_edges(PQC0, PQC1, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data().add_edges(PQC1, PQC2, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data().add_edges(PQC2, PQC3, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data().add_edges(PQC3, PQC0, igl.eigen.MatrixXd([[0, 0, 0]]))

    elif key == ord('2'):
        # Draw the planar quad mesh
        viewer.data().set_mesh(VQCplan, FQCtri)

        # Assign a color to each quad that corresponds to its planarity
        planarity = igl.eigen.MatrixXd()
        igl.quad_planarity(VQCplan, FQC, planarity)
        Ct = igl.eigen.MatrixXd()
        igl.jet(planarity, 0, 0.01, Ct)
        C = igl.eigen.MatrixXd(FQCtri.rows(), 3)
        C.setTopRows(Ct.rows(), Ct)
        C.setBottomRows(Ct.rows(), Ct)
        viewer.data().set_colors(C)

        # Plot a line for each edge of the quad mesh
        viewer.data().add_edges(PQC0plan, PQC1plan,
                                igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data().add_edges(PQC1plan, PQC2plan,
                                igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data().add_edges(PQC2plan, PQC3plan,
                                igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data().add_edges(PQC3plan, PQC0plan,
                                igl.eigen.MatrixXd([[0, 0, 0]]))

    else:
        return False

    return True
Exemplo n.º 5
0
def key_down(viewer, key, modifier):
    if key < ord('1') or key > ord('8'):
        return False

    viewer.data.lines.resize(0, 9)

    num = key - ord('0')

    # Interpolate
    print("Interpolating " + repr(num * 2) + "-PolyVector field")

    b = igl.eigen.MatrixXi([[4550, 2321, 5413, 5350]]).transpose()

    bc = igl.eigen.MatrixXd(b.size(), num * 3)

    for i in range(0, b.size()):
        t = random_constraints(B1.row(b[i]), B2.row(b[i]), num)
        bc.setRow(i, t)

    # Interpolated PolyVector field
    pvf = igl.eigen.MatrixXd()
    igl.n_polyvector(V, F, b, bc, pvf)

    # Highlight in red the constrained faces
    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)

    for n in range(0, num):
        VF = igl.eigen.MatrixXd.Zero(F.rows(), 3)

        for i in range(0, b.size()):
            VF.setRow(b[i], bc.block(i, n * 3, 1, 3))

        for i in range(0, samples.rows()):
            VF.setRow(samples[i], pvf.block(samples[i], n * 3, 1, 3))

        c = VF.rowwiseNorm()

        C2 = igl.eigen.MatrixXd()
        igl.jet(c, 1, 1 + rand_factor, C2)
        viewer.data.add_edges(B - global_scale * VF, B + global_scale * VF, C2)

    return False
Exemplo n.º 6
0
def key_down(viewer, key, modifier):
    if key < ord('1') or key > ord('8'):
        return False

    viewer.data.lines.resize(0,9)

    num = key  - ord('0')

    # Interpolate
    print("Interpolating " + repr(num * 2) + "-PolyVector field")

    b = igl.eigen.MatrixXi([[4550, 2321, 5413, 5350]]).transpose()

    bc = igl.eigen.MatrixXd(b.size(),num*3)

    for i in range(0,b.size()):
        t = random_constraints(B1.row(b[i]),B2.row(b[i]),num)
        bc.setRow(i,t)

    # Interpolated PolyVector field
    pvf = igl.eigen.MatrixXd()
    igl.n_polyvector(V, F, b, bc, pvf)

    # Highlight in red the constrained faces
    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)

    for n in range(0,num):
        VF = igl.eigen.MatrixXd.Zero(F.rows(),3)

        for i in range(0,b.size()):
            VF.setRow(b[i],bc.block(i,n*3,1,3))

        for i in range(0,samples.rows()):
            VF.setRow(samples[i],pvf.block(samples[i],n*3,1,3))

        c = VF.rowwiseNorm()

        C2 = igl.eigen.MatrixXd()
        igl.jet(c,1,1+rand_factor,C2)
        viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2)

    return False
def key_down(viewer, key, modifier):
    if key == ord('1'):
        # Draw the triangulated quad mesh
        viewer.data.set_mesh(VQC, FQCtri)

        # Assign a color to each quad that corresponds to its planarity
        planarity = igl.eigen.MatrixXd()
        igl.quad_planarity(VQC, FQC, planarity)
        Ct = igl.eigen.MatrixXd()
        igl.jet(planarity, 0, 0.01, Ct)
        C = igl.eigen.MatrixXd(FQCtri.rows(), 3)
        C.setTopRows(Ct.rows(), Ct)
        C.setBottomRows(Ct.rows(), Ct)
        viewer.data.set_colors(C)

        # Plot a line for each edge of the quad mesh
        viewer.data.add_edges(PQC0, PQC1, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data.add_edges(PQC1, PQC2, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data.add_edges(PQC2, PQC3, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data.add_edges(PQC3, PQC0, igl.eigen.MatrixXd([[0, 0, 0]]))

    elif key == ord('2'):
        # Draw the planar quad mesh
        viewer.data.set_mesh(VQCplan, FQCtri)

        # Assign a color to each quad that corresponds to its planarity
        planarity = igl.eigen.MatrixXd()
        igl.quad_planarity(VQCplan, FQC, planarity)
        Ct = igl.eigen.MatrixXd()
        igl.jet(planarity, 0, 0.01, Ct)
        C = igl.eigen.MatrixXd(FQCtri.rows(), 3)
        C.setTopRows(Ct.rows(), Ct)
        C.setBottomRows(Ct.rows(), Ct)
        viewer.data.set_colors(C)

        # Plot a line for each edge of the quad mesh
        viewer.data.add_edges(PQC0plan, PQC1plan, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data.add_edges(PQC1plan, PQC2plan, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data.add_edges(PQC2plan, PQC3plan, igl.eigen.MatrixXd([[0, 0, 0]]))
        viewer.data.add_edges(PQC3plan, PQC0plan, igl.eigen.MatrixXd([[0, 0, 0]]))

    else:
        return False

    return True
Exemplo n.º 8
0
def triMesh(V,F,c = np.array([0]), colormap = "default"):
	if (c.shape[0] != V.shape[0]):
		c = np.zeros((V.shape[0],3)) + 0.7
		color = p2e(c.astype(np.float64))
	elif ((c.shape[0] == V.shape[0]) and colormap == "jet"):
		color = igl.eigen.MatrixXd()
		igl.jet(p2e(c.astype(np.float64)), True, color)
	elif c.shape == V.shape:
		color = p2e(c.astype(np.float64))
	else:
		# colormap: "blue", "red", "green", "default"
		color = colorMap(c, colormap = colormap)
		color = p2e(color.astype(np.float64))

	viewer = igl.viewer.Viewer()
	viewer.data.set_mesh(p2e(V.astype(np.float64)), p2e(F.astype(np.int32)))
	viewer.core.show_lines = False
	viewer.data.set_colors(color)
	backColor = p2e(np.array([1,1,1,1]).astype(np.float64))
	viewer.core.background_color = backColor
	viewer.launch()
Exemplo n.º 9
0
def scatter3(p, c = np.array([0]), size = 3, colormap = "default"):
	if (c.shape[0] != p.shape[0]):
		c = np.zeros((p.shape[0],3)) + 0.7
		color = p2e(c.astype(np.float64))
	elif ((c.shape[0] == p.shape[0]) and colormap == "jet"):
		color = igl.eigen.MatrixXd()
		igl.jet(p2e(c.astype(np.float64)), True, color)
	elif c.shape == p.shape:
		color = p2e(c.astype(np.float64))
	else:
		from colorMap import *
		# colormap: "blue", "red", "green", "default"
		color = colorMap(c, colormap = colormap)
		color = p2e(color.astype(np.float64))

	p = np.ascontiguousarray(p, dtype=np.float64)
	backColor = p2e(np.array([1,1,1,1]).astype(np.float64))
	viewer = igl.viewer.Viewer()
	viewer.data.set_points(p2e(p.astype(np.float64)), color)
	viewer.core.point_size = size
	viewer.core.background_color = backColor
	viewer.launch()
Exemplo n.º 10
0
G = igl.eigen.SparseMatrixd()
igl.grad(V, F, G)

# Compute gradient of U
GU = (G * U).MapMatrix(F.rows(), 3)

# Compute gradient magnitude
GU_mag = GU.rowwiseNorm()

viewer = igl.glfw.Viewer()
viewer.data().set_mesh(V, F)

# Compute pseudocolor for original function
C = igl.eigen.MatrixXd()

igl.jet(U, True, C)

# Or for gradient magnitude
# igl.jet(GU_mag,True,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()

# Draw a black segment in direction of gradient at face barycenters
BC = igl.eigen.MatrixXd()
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)
Exemplo n.º 11
0
# 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())

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()
viewer.data.set_mesh(V, F)
viewer.core.show_lines = False
viewer.data.set_colors(C)

def key_down(viewer,key,mode):
    if key == ord(' '):
        global toggle
        global C
        global C_const

        if toggle:
Exemplo n.º 12
0
G = igl.eigen.SparseMatrixd()
igl.grad(V, F, G)

# Compute gradient of U
GU = (G * U).MapMatrix(F.rows(), 3)

# Compute gradient magnitude
GU_mag = GU.rowwiseNorm()

viewer = igl.glfw.Viewer()
viewer.data().set_mesh(V, F)

# Compute pseudocolor for original function
C = igl.eigen.MatrixXd()

igl.jet(U, True, C)

# Or for gradient magnitude
# igl.jet(GU_mag,True,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()

# Draw a black segment in direction of gradient at face barycenters
BC = igl.eigen.MatrixXd()
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)
Exemplo n.º 13
0
Z_in = solver.solve(L_in_b*bc)

# slice into solution
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);

# 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)

# Pseudo-color based on solution
C = igl.eigen.MatrixXd()
igl.jet(Z,True,C)

# Plot the mesh with pseudocolors
viewer = igl.viewer.Viewer()
viewer.data.set_mesh(V, F)
viewer.core.show_lines = False
viewer.data.set_colors(C)
viewer.launch()
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)

# Global definitions for viewer
# Pseudo-color based on solution
C = igl.eigen.MatrixXd()
C_const = igl.eigen.MatrixXd()
toggle = True

# Use same color axes
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)

# Plot the mesh with pseudocolors
viewer = igl.viewer.Viewer()
viewer.data.set_mesh(V, F)
viewer.core.show_lines = False
viewer.data.set_colors(C)


def key_down(viewer, key, mode):
    if key == ord(' '):
        global toggle, C, C_const

        if toggle:
            viewer.data.set_colors(C)
Exemplo n.º 15
0
def set_color(viewer):
    global selected, W
    C = igl.eigen.MatrixXd()
    igl.jet(W.col(selected), True, C)
    viewer.data.set_colors(C)
Exemplo n.º 16
0
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_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)

# Compute per-vertex colors
igl.jet(Z, True, C)

# Add per-vertex colors
viewer.data.set_colors(C)

# Launch the viewer
viewer.launch()
Exemplo n.º 17
0
def main():
    global verts_sample

    initial_verts, initial_faces = get_initial_verts_and_faces()
    numpy_base_verts = e2p(initial_verts).flatten()

    start = time.time()
    num_samples = 250
    numpy_verts_sample = load_samples(num_samples)
    numpy_displacements_sample = numpy_verts_sample - initial_verts

    num_verts = len(numpy_verts_sample[0])
    print(num_verts)

    print('Loading...')
    verts_sample = [p2e(m) for m in numpy_verts_sample]
    displacements_sample = [p2e(m) for m in numpy_displacements_sample]
    print("Took:", time.time() - start)

    use_pca = False
    if use_pca:
        ### PCA Version
        print("Doing PCA...")
        train_size = num_samples
        test_size = num_samples
        test_data = numpy_displacements_sample[:test_size] * 1.0
        test_data_eigen = verts_sample[:test_size]
        numpy.random.shuffle(numpy_displacements_sample)
        # train_data = numpy_verts_sample[test_size:test_size+train_size]
        train_data = numpy_displacements_sample[0:train_size]

        pca = PCA(n_components=3)
        pca.fit(train_data.reshape((train_size, 3 * num_verts)))

        # def encode(q):
        #     return pca.transform(numpy.array([q.flatten() - numpy_base_verts]))[0]

        # def decode(z):
        #     return (numpy_base_verts + pca.inverse_transform(numpy.array([z]))[0]).reshape((num_verts, 3))

        # print(numpy.equal(test_data[0].flatten().reshape((len(test_data[0]),3)), test_data[0]))
        # print(encode(test_data[0]))

        test_data_encoded = pca.transform(
            test_data.reshape(test_size, 3 * num_verts))
        test_data_decoded = (numpy_base_verts +
                             pca.inverse_transform(test_data_encoded)).reshape(
                                 test_size, num_verts, 3)
        test_data_decoded_eigen = [p2e(m) for m in test_data_decoded]
        ### End of PCA version
    else:
        ### Autoencoder
        import keras
        from keras.layers import Input, Dense
        from keras.models import Model, load_model
        import datetime

        start_time = time.time()

        train_size = num_samples
        test_size = num_samples
        test_data = numpy_displacements_sample[:test_size].reshape(
            test_size, 3 * num_verts)
        test_data_eigen = verts_sample[:test_size]
        # numpy.random.shuffle(numpy_displacements_sample)
        # train_data = numpy_verts_sample[test_size:test_size+train_size]
        train_data = numpy_displacements_sample[0:train_size].reshape(
            (train_size, 3 * num_verts))

        mean = numpy.mean(train_data, axis=0)
        std = numpy.std(train_data, axis=0)

        mean = numpy.mean(train_data)
        std = numpy.std(train_data)

        s_min = numpy.min(train_data)
        s_max = numpy.max(train_data)

        def normalize(data):
            return numpy.nan_to_num((data - mean) / std)
            # return numpy.nan_to_num((train_data - s_min) / (s_max - s_min))
        def denormalize(data):
            return data * std + mean
            # return data * (s_max - s_min) + s_min

        train_data = normalize(train_data)
        test_data = normalize(test_data)

        # print(train_data)
        # print(mean)
        # print(std)
        # exit()
        # this is the size of our encoded representations
        encoded_dim = 3

        # Single autoencoder
        # initializer = keras.initializers.RandomUniform(minval=0.0, maxval=0.01, seed=5)
        # bias_initializer = initializer
        activation = keras.layers.advanced_activations.LeakyReLU(
            alpha=0.3)  #'relu'

        input = Input(shape=(len(train_data[0]), ))
        output = input
        output = Dense(30, activation=activation)(input)
        output = Dense(512, activation=activation)(output)
        output = Dense(64, activation=activation)(output)
        output = Dense(encoded_dim, activation=activation,
                       name="encoded")(output)
        output = Dense(64, activation=activation)(output)
        output = Dense(512, activation=activation)(output)
        output = Dense(30, activation=activation)(output)
        output = Dense(len(train_data[0]), activation='linear')(
            output
        )  #'linear',)(output) # First test seems to indicate no change on output with linear

        autoencoder = Model(input, output)

        optimizer = keras.optimizers.Adam(lr=0.001,
                                          beta_1=0.9,
                                          beta_2=0.999,
                                          epsilon=1e-08,
                                          decay=0)
        autoencoder.compile(optimizer=optimizer, loss='mean_squared_error')

        model_start_time = time.time()
        autoencoder.fit(train_data,
                        train_data,
                        epochs=1000,
                        batch_size=num_samples,
                        shuffle=True,
                        validation_data=(test_data, test_data))

        # output_path = 'trained_models/' + datetime.datetime.now().strftime("%I %M%p %B %d %Y") + '.h5'
        # autoencoder.save(output_path)

        print("Total model time: ", time.time() - model_start_time)

        # Display

        decoded_samples = denormalize(autoencoder.predict(test_data))
        #decoded_samples = autoencoder.predict(test_data) * std + mean

        test_data_decoded = (numpy_base_verts + decoded_samples).reshape(
            test_size, num_verts, 3)
        test_data_decoded_eigen = [p2e(m) for m in test_data_decoded]
        ### End of Autoencoder

    # Error colours
    error = numpy.sum((test_data_decoded - numpy_verts_sample)**2, axis=2)
    colours = [igl.eigen.MatrixXd() for _ in range(num_samples)]
    for i in range(num_samples):
        igl.jet(p2e(error[i]), True, colours[i])

    # Set up
    viewer = igl.viewer.Viewer()

    viewer.data.set_mesh(initial_verts, initial_faces)

    def pre_draw(viewer):
        global current_frame, verts_sample, show_decoded

        if viewer.core.is_animating:
            print(current_frame)
            print(show_decoded)
            if show_decoded:
                viewer.data.set_vertices(
                    test_data_decoded_eigen[current_frame])
                viewer.data.set_colors(colours[current_frame])
            else:
                viewer.data.set_vertices(test_data_eigen[current_frame])

            viewer.data.compute_normals()
            current_frame = (current_frame + 1) % test_size

        return False

    viewer.callback_pre_draw = pre_draw
    viewer.callback_key_down = key_down
    viewer.core.is_animating = False
    # viewer.core.camera_zoom = 2.5
    viewer.core.animation_max_fps = 30.0

    viewer.launch()
Exemplo n.º 18
0
# Add the igl library to the modules search path
import sys, os
sys.path.insert(0, os.getcwd() + "/../")

import pyigl as igl

# Load mesh
V = igl.eigen.MatrixXd()
F = igl.eigen.MatrixXi()
igl.readOFF("../../tutorial/shared/bumpy.off",V,F);

# Compute Gaussian curvature
K = igl.eigen.MatrixXd();
igl.gaussian_curvature(V,F,K);

# Compute pseudocolor
C = igl.eigen.MatrixXd();
igl.jet(K,True,C);

# Plot the mesh with pseudocolors
viewer = igl.viewer.Viewer()
viewer.data.set_mesh(V, F)
viewer.data.set_colors(C)
viewer.launch()
Exemplo n.º 19
0
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, check_dependencies

dependencies = ["glfw"]
check_dependencies(dependencies)


# Load mesh
V = igl.eigen.MatrixXd()
F = igl.eigen.MatrixXi()
igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F)

# Compute Gaussian curvature
K = igl.eigen.MatrixXd()
igl.gaussian_curvature(V, F, K)

# Compute pseudocolor
C = igl.eigen.MatrixXd()
igl.jet(K, True, C)

# Plot the mesh with pseudocolors
viewer = igl.glfw.Viewer()
viewer.data().set_mesh(V, F)
viewer.data().set_colors(C)
viewer.launch()
Exemplo n.º 20
0
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)

I = igl.eigen.MatrixXi()
J = igl.eigen.MatrixXi()

# sorted_BC = BC(I,:)
igl.sortrows(BC, True, sorted_BC, I)

# Get sorted "place" from sorted indices
J.resize(I.rows(), 1)
# J(I) = 1:numel(I)

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)

# Plot the mesh with pseudocolors
viewer = igl.viewer.Viewer()
viewer.data.set_mesh(V, F)
viewer.data.set_colors(C)
viewer.launch()