diff --git a/README.html b/README.html
index 6c13281..c163d77 100644
--- a/README.html
+++ b/README.html
@@ -343,7 +343,7 @@
Constant function approximation
Linear function approximation
-If we make make a slightly more appropriate assuming that in the neighborhood
+
If we make make a slightly more appropriate assumption that in the neighborhood
of the \(P_Y(\z₀)\) the surface \(Y\) is a plane, then we can improve this
approximation while keeping \(\f\) linear in \(\z\):
diff --git a/README.md b/README.md
index bce5dc2..ce58753 100644
--- a/README.md
+++ b/README.md
@@ -263,7 +263,7 @@ derived our gradients geometrically.
### Linear function approximation
-If we make make a slightly more appropriate assuming that in the neighborhood
+If we make make a slightly more appropriate assumption that in the neighborhood
of the $P_Y(\z₀)$ the surface $Y$ is a plane, then we can improve this
approximation while keeping $\f$ linear in $\z$:
diff --git a/include/closest_rotation.h b/include/closest_rotation.h
index cc67fd0..641d5f2 100644
--- a/include/closest_rotation.h
+++ b/include/closest_rotation.h
@@ -1,6 +1,9 @@
#ifndef CLOSEST_ROTATION_H
#define CLOSEST_ROTATION_H
#include
+#include
+#include
+
// Given a 3×3 matrix `M`, find the closest rotation matrix `R`.
//
// Inputs:
diff --git a/include/hausdorff_lower_bound.h b/include/hausdorff_lower_bound.h
index 15e4db0..efa54e1 100644
--- a/include/hausdorff_lower_bound.h
+++ b/include/hausdorff_lower_bound.h
@@ -1,6 +1,9 @@
#ifndef HAUSDORFF_LOWER_BOUND_H
#define HAUSDORFF_LOWER_BOUND_H
#include
+#include
+#include
+
// Compute a lower bound on the _directed_ Hausdorff distance from a given mesh
// (VX,FX) to another mesh (VY,FY).
//
diff --git a/include/icp_single_iteration.h b/include/icp_single_iteration.h
index 03e4040..a6e6358 100644
--- a/include/icp_single_iteration.h
+++ b/include/icp_single_iteration.h
@@ -1,6 +1,10 @@
#ifndef ICP_SINGLE_ITERATION_H
#define ICP_SINGLE_ITERATION_H
#include
+#include
+#include
+#include
+#include
enum ICPMethod
{
diff --git a/include/point_mesh_distance.h b/include/point_mesh_distance.h
index f542c54..4266e36 100644
--- a/include/point_mesh_distance.h
+++ b/include/point_mesh_distance.h
@@ -1,6 +1,10 @@
#ifndef POINT_MESH_DISTANCE_H
#define POINT_MESH_DISTANCE_H
#include
+#include
+#include "point_triangle_distance.h"
+#include "igl/per_face_normals.h"
+
// Compute the distances `D` between a set of given points `X` and their
// closest points `P` on a given mesh with vertex positions `VY` and face
// indices `FY`.
diff --git a/include/point_to_plane_rigid_matching.h b/include/point_to_plane_rigid_matching.h
index 149620f..f412df2 100644
--- a/include/point_to_plane_rigid_matching.h
+++ b/include/point_to_plane_rigid_matching.h
@@ -1,6 +1,8 @@
#ifndef POINT_TO_PLANE_RIGID_MATCHING_H
#define POINT_TO_PLANE_RIGID_MATCHING_H
#include
+#include
+
// Given a set of source points `X` and corresponding target points `P` and
// normals `N`, find the optimal rigid transformation (`R`,`t`) that aligns `X`
// to `P`, minimizing the matching energy:
diff --git a/include/point_to_point_rigid_matching.h b/include/point_to_point_rigid_matching.h
index dacc628..d5386b9 100644
--- a/include/point_to_point_rigid_matching.h
+++ b/include/point_to_point_rigid_matching.h
@@ -1,6 +1,8 @@
#ifndef POINT_TO_POINT_RIGID_MATCHING_H
#define POINT_TO_POINT_RIGID_MATCHING_H
#include
+#include
+
// Given a set of source points X and corresponding target points P, find the
// optimal rigid transformation (R,t) that aligns X to P, minimizing the
// matching energy:
@@ -19,5 +21,4 @@ void point_to_point_rigid_matching(
const Eigen::MatrixXd & P,
Eigen::Matrix3d & R,
Eigen::RowVector3d & t);
-#endif
-
+#endif
\ No newline at end of file
diff --git a/include/point_triangle_distance.h b/include/point_triangle_distance.h
index ecdd14e..8c9c4b8 100644
--- a/include/point_triangle_distance.h
+++ b/include/point_triangle_distance.h
@@ -1,6 +1,8 @@
#ifndef POINT_TRIANGLE_DISTANCE_H
#define POINT_TRIANGLE_DISTANCE_H
#include
+#include
+
// Compute the distance `d` between a given point `x` and the closest point `p` on
// a given triangle with corners `a`, `b`, and `c`.
//
diff --git a/include/random_points_on_mesh.h b/include/random_points_on_mesh.h
index 4fe2497..869580b 100644
--- a/include/random_points_on_mesh.h
+++ b/include/random_points_on_mesh.h
@@ -1,6 +1,9 @@
#ifndef RANDOM_POINTS_ON_MESH_H
#define RANDOM_POINTS_ON_MESH_H
#include
+#include
+#include
+#include
// RANDOM_POINTS_ON_MESH Randomly sample a mesh (V,F) n times.
//
// Inputs:
diff --git a/src/closest_rotation.cpp b/src/closest_rotation.cpp
index 54403c1..27dfcca 100644
--- a/src/closest_rotation.cpp
+++ b/src/closest_rotation.cpp
@@ -4,6 +4,15 @@ void closest_rotation(
const Eigen::Matrix3d & M,
Eigen::Matrix3d & R)
{
- // Replace with your code
- R = Eigen::Matrix3d::Identity();
-}
+ Eigen::JacobiSVD svd(M, Eigen::ComputeThinU | Eigen::ComputeThinV);
+ Eigen::Matrix3d U = svd.matrixU();
+ Eigen::Matrix3d V = svd.matrixV();
+ Eigen::Matrix3d omega_star;
+ double dt = (U*V.transpose()).determinant();
+
+ omega_star << 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, dt;
+
+ R = U*omega_star*V.transpose();
+}
\ No newline at end of file
diff --git a/src/hausdorff_lower_bound.cpp b/src/hausdorff_lower_bound.cpp
index 8608964..af7a722 100644
--- a/src/hausdorff_lower_bound.cpp
+++ b/src/hausdorff_lower_bound.cpp
@@ -7,6 +7,11 @@ double hausdorff_lower_bound(
const Eigen::MatrixXi & FY,
const int n)
{
- // Replace with your code
- return 0;
-}
+ Eigen::MatrixXd pointsX, P, N;
+ Eigen::VectorXd D;
+
+ random_points_on_mesh(n, VX, FX, pointsX);
+ point_mesh_distance(pointsX, VY, FY, D, P, N);
+
+ return D.maxCoeff();
+}
\ No newline at end of file
diff --git a/src/icp_single_iteration.cpp b/src/icp_single_iteration.cpp
index 1e8fda9..e7ce569 100644
--- a/src/icp_single_iteration.cpp
+++ b/src/icp_single_iteration.cpp
@@ -10,7 +10,19 @@ void icp_single_iteration(
Eigen::Matrix3d & R,
Eigen::RowVector3d & t)
{
- // Replace with your code
- R = Eigen::Matrix3d::Identity();
- t = Eigen::RowVector3d::Zero();
+ // R = Eigen::Matrix3d::Identity();
+ // t = Eigen::RowVector3d::Zero();
+
+ Eigen::MatrixXd pointsX, P, N;
+ Eigen::VectorXd D;
+
+ random_points_on_mesh(num_samples, VX, FX, pointsX);
+ point_mesh_distance(pointsX, VY, FY, D, P, N);
+
+ if(method == ICP_METHOD_POINT_TO_POINT){
+ point_to_point_rigid_matching(pointsX, P, R, t);
+ }
+ else{
+ point_to_plane_rigid_matching(pointsX, P, N, R, t);
+ }
}
diff --git a/src/point_mesh_distance.cpp b/src/point_mesh_distance.cpp
index 2e6a070..b3f4440 100644
--- a/src/point_mesh_distance.cpp
+++ b/src/point_mesh_distance.cpp
@@ -1,4 +1,5 @@
#include "point_mesh_distance.h"
+// #include
void point_mesh_distance(
const Eigen::MatrixXd & X,
@@ -8,9 +9,43 @@ void point_mesh_distance(
Eigen::MatrixXd & P,
Eigen::MatrixXd & N)
{
- // Replace with your code
P.resizeLike(X);
+ D = Eigen::VectorXd(X.rows());
N = Eigen::MatrixXd::Zero(X.rows(),X.cols());
- for(int i = 0;i::max(), tmp_d;
+ Eigen::RowVector3d closest_point, tmp_point, b;
+ int min_index = 0;
+
+ for(int j = 0;j::max();
+
+ Eigen::RowVector3d ba = b - a;
+ Eigen::RowVector3d ca = c - a;
+ Eigen::RowVector3d xa = x - a;
+ Eigen::RowVector3d n = ba.cross(ca);
+ n.normalize();
+
+ // find point on plane
+ double t = n.dot(xa);
+ Eigen::RowVector3d pop = x + t*n;
+
+ // find barycentric coordinates
+ double d00 = ba.dot(ba);
+ double d01 = ba.dot(ca);
+ double d11 = ca.dot(ca);
+ double d20 = xa.dot(ba);
+ double d21 = xa.dot(ca);
+
+ double denom = d00 * d11 - d01 * d01;
+
+ double beta = (d11 * d20 - d01 * d21) / denom;
+ double gamma = (d00 * d21 - d01 * d20) / denom;
+ double alpha = 1 - beta - gamma;
+
+ if(alpha > 0 && alpha < 1 && beta > 0 && beta < 1 && gamma > 0 && gamma < 1){
+ p = alpha * a + beta * b + gamma * c;
+ d = (p - x).norm();
+ return;
+ }
+
+ // check three vertices
+ double tmp = (x-a).norm();
+ if (d > tmp){
+ d = tmp;
+ p = a;
+ }
+
+ tmp = (x-b).norm();
+ if (d > tmp){
+ d = tmp;
+ p = b;
+ }
+
+ tmp = (x-c).norm();
+ if (d > tmp){
+ d = tmp;
+ p = c;
+ }
+
+ // check three edges
+ // ab
+ t = (b - a).dot(x - a)/(b-a).dot(b-a);
+ if (t > 0 && t < 1){
+ Eigen::RowVector3d tmp_p = a + t*(b-a);
+ tmp = (tmp_p - x).norm();
+ if (d > tmp){
+ p = tmp_p;
+ d = tmp;
+ }
+ }
+
+ // bc
+ t = (c - b).dot(x - b)/(c-b).dot(c-b);
+ if (t > 0 && t < 1){
+ Eigen::RowVector3d tmp_p = b + t*(c-b);
+ tmp = (tmp_p - x).norm();
+ if (d > tmp){
+ p = tmp_p;
+ d = tmp;
+ }
+ }
+
+ // ca
+ t = (a - c).dot(x - c)/(a-c).dot(a-c);
+ if (t > 0 && t < 1){
+ Eigen::RowVector3d tmp_p = c + t*(a-c);
+ tmp = (tmp_p - x).norm();
+ if (d > tmp){
+ p = tmp_p;
+ d = tmp;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/random_points_on_mesh.cpp b/src/random_points_on_mesh.cpp
index 6e85d75..6006ae3 100644
--- a/src/random_points_on_mesh.cpp
+++ b/src/random_points_on_mesh.cpp
@@ -1,4 +1,5 @@
#include "random_points_on_mesh.h"
+#include
void random_points_on_mesh(
const int n,
@@ -6,8 +7,48 @@ void random_points_on_mesh(
const Eigen::MatrixXi & F,
Eigen::MatrixXd & X)
{
- // REPLACE WITH YOUR CODE:
X.resize(n,3);
- for(int i = 0;i 1){
+ alpha = 1 - alpha;
+ beta = 1 - beta;
+ }
+
+ Eigen::VectorXd va = V.row(F(face_idx, 0)), vb = V.row(F(face_idx, 1)), vc = V.row(F(face_idx, 2));
+ X.row(i) = va + alpha*(vb - va) + beta*(vc - va);
+ }
+}
\ No newline at end of file