Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/cotmatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define COTMATRIX_H
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <cmath>
// Construct the "cotangent Laplacian" for a mesh with edge lengths `l`. Each
// entry in the output sparse, symmetric matrix `L` is given by:
//
Expand Down
3 changes: 2 additions & 1 deletion include/massmatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#define MASSMATRIX_H
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <igl/doublearea.h>
// Construct the diagonal(ized) mass matrix for a mesh with edge lengths `l`.
// Each enetry in the output sparse, symmetric matrix `M` is given by:
// Each entry in the output sparse, symmetric matrix `M` is given by:
//
// \\[
// M_{ij} = \begin{cases}
Expand Down
3 changes: 3 additions & 0 deletions include/smooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#define SMOOTH_H
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <igl/edge_lengths.h>
#include "cotmatrix.h"
#include "massmatrix.h"
// Given a mesh (`V`,`F`) and data specified per-vertex (`G`), smooth this data
// using a single implicit Laplacian smoothing step.
//
Expand Down
47 changes: 43 additions & 4 deletions src/cotmatrix.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,49 @@
#include "cotmatrix.h"

// Calcutes 1/2 * cot(theta) in a triangle with side lengths
// a, b, and c, where theta is the angle opposite c.
double halfcot(
double a,
double b,
double c)
{
// Heron's formula for area
double s = (a + b + c) / 2;
double A = std::sqrt(s * (s - a) * (s - b) * (s - c));

// cos(theta) / sin(theta)
return (std::pow(c, 2) - std::pow(a, 2) - std::pow(b, 2)) / (-8 * A);
}

void cotmatrix(
const Eigen::MatrixXd & l,
const Eigen::MatrixXi & F,
Eigen::SparseMatrix<double> & L)
const Eigen::MatrixXd & l,
const Eigen::MatrixXi & F,
Eigen::SparseMatrix<double> & L)
{
// Add your code here
typedef Eigen::Triplet<double> T;
std::vector<T> triplets;
triplets.reserve(F.size() * 4);

for (int i = 0; i < F.rows(); i++)
{
Eigen::Vector3i f = F.row(i);
Eigen::Vector3d lengths = l.row(i);

for (int j = 0; j < f.size(); j++)
{
// lengths[j] corresponds to the length of the edge
// between vertices f[(j + 1) % 3] and f[(j + 2) % 3]
double c = halfcot(lengths[(j + 1) % 3], lengths[(j + 2) % 3], lengths[j]);
triplets.push_back(T(f[(j + 1) % 3], f[(j + 2) % 3], c));
triplets.push_back(T(f[(j + 2) % 3], f[(j + 1) % 3], c));

// populate diagonal with negative sum of off-diagonal entries
triplets.push_back(T(f[(j + 1) % 3], f[(j + 1) % 3], -c));
triplets.push_back(T(f[(j + 2) % 3], f[(j + 2) % 3], -c));
}
}

L.resize(F.maxCoeff() + 1, F.maxCoeff() + 1);
L.setFromTriplets(triplets.begin(), triplets.end());
}

27 changes: 23 additions & 4 deletions src/massmatrix.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
#include "massmatrix.h"

void massmatrix(
const Eigen::MatrixXd & l,
const Eigen::MatrixXi & F,
Eigen::DiagonalMatrix<double,Eigen::Dynamic> & M)
const Eigen::MatrixXd & l,
const Eigen::MatrixXi & F,
Eigen::DiagonalMatrix<double,Eigen::Dynamic> & M)
{
// Add your code here
Eigen::VectorXd dblA(F.rows());
igl::doublearea(l, 0, dblA);

Eigen::VectorXd areas = Eigen::VectorXd::Zero(F.maxCoeff() + 1);

for (int i = 0; i < F.rows(); i++)
{
Eigen::Vector3i f = F.row(i);
double area = dblA[i];

for (int j = 0; j < f.size(); j++)
{
int v = f[j];
areas[v] += area;

}
}

M.resize(F.maxCoeff() + 1);
M.diagonal() = 1 / (double)6 * areas;
}

22 changes: 20 additions & 2 deletions src/smooth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ void smooth(
double lambda,
Eigen::MatrixXd & U)
{
// Replace with your code
U = G;
Eigen::MatrixXd l;
igl::edge_lengths(V, F, l);

Eigen::DiagonalMatrix<double, Eigen::Dynamic> M;
massmatrix(l, F, M);

Eigen::SparseMatrix<double> L;
cotmatrix(l, F, L);

Eigen::MatrixXd MG = M * G;

// A = M - lamda * L
Eigen::SparseMatrix<double> A = -lambda * L;
for (int i = 0; i < A.rows(); i++)
{
A.coeffRef(i, i) += M.diagonal()[i];
}

Eigen::SimplicialCholesky<Eigen::SparseMatrix<double>> chol(A);
U = chol.solve(MG);
}