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