Skip to content

Use solver

/**
 * This example shows how to use the solver
*/
#include <ultimaille/all.h>


using namespace UM;

int main() {

    // Set the input and output directories
    const std::string input_dir = ASSETS_INPUT_DIR;
    const std::string output_dir = OUTPUT_DIR;

    // Load mesh from file
    Triangles m;
    read_by_extension(input_dir + "catorus.geogram", m);
    m.connect();

    // Declare solver, set number of variables
    // Each vertex has 3 coordinates (x, y, z)
    // So we have m.nverts() * 3 variables
    LeastSquares solver(m.nverts() * 3);

    // Select some vertices to fix
    // I choose ears, muzzle and legs
    // These vertices are fixed in the original mesh
    // and we want to keep them in the same position
    int fix_vert[] = {1249, 2378, 485, 4095, 4034};
    for (auto vi : fix_vert) {
        vec3 v = m.vertex(vi);
        for (int dim = 0; dim < 3; dim++)
            solver.fix(vi * 3 + dim, v[dim]);
    }

    for (auto &v : m.iter_vertices()) {

        for (int dim = 0; dim < 3; dim++) {
            LinExpr lexpr;

            // For each vertex, we want to average the positions of its neighbors
            int n = 0;
            for (auto &h : v.iter_halfedges()) {
                auto neighbor = h.to();
                lexpr += Linear::X(neighbor * 3 + dim);
                n++;
            }

            lexpr *= (1.0 / n);

            // We want to minimize the distance between the vertex and the average of its neighbors
            solver.add_to_energy(Linear::X(v * 3 + dim) - lexpr);
        }
    }

    // Solve
    solver.solve();

    // Update vertex positions with the solution
    for (auto &v : m.iter_vertices()) {
        double x = solver.value(v * 3);
        double y = solver.value(v * 3 + 1);
        double z = solver.value(v * 3 + 2);
        v.pos() = {x, y, z};
    }

    // Save the mesh
    write_by_extension(output_dir + "catorus_solved.geogram", m);

    return 0;
}