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/src/closest_rotation.cpp b/src/closest_rotation.cpp
old mode 100644
new mode 100755
index 54403c1..da0038c
--- a/src/closest_rotation.cpp
+++ b/src/closest_rotation.cpp
@@ -1,9 +1,17 @@
#include "closest_rotation.h"
+#include
+#include
void closest_rotation(
const Eigen::Matrix3d & M,
Eigen::Matrix3d & R)
{
// Replace with your code
- R = Eigen::Matrix3d::Identity();
+ //R = Eigen::Matrix3d::Identity();
+ Eigen::JacobiSVD svd(M, Eigen::ComputeThinU | Eigen::ComputeThinV);
+ Eigen::Matrix3d O = Eigen::Matrix3d::Zero();
+ O(0,0) = 1;
+ O(1,1) = 1;
+ O(2,2) = (svd.matrixU() * (svd.matrixV().transpose())).determinant();
+ R = svd.matrixU() * O * (svd.matrixV().transpose());
}
diff --git a/src/hausdorff_lower_bound.cpp b/src/hausdorff_lower_bound.cpp
old mode 100644
new mode 100755
index 8608964..07feb40
--- a/src/hausdorff_lower_bound.cpp
+++ b/src/hausdorff_lower_bound.cpp
@@ -1,4 +1,6 @@
#include "hausdorff_lower_bound.h"
+#include "random_points_on_mesh.h"
+#include "point_mesh_distance.h"
double hausdorff_lower_bound(
const Eigen::MatrixXd & VX,
@@ -8,5 +10,11 @@ double hausdorff_lower_bound(
const int n)
{
// Replace with your code
- return 0;
+ //return 0;
+ Eigen::MatrixXd X,P,N;
+ Eigen::VectorXd D;
+ random_points_on_mesh(n,VX,FX,X);
+ point_mesh_distance(X,VY,FY,D,P,N);
+ double lowerbound = D.maxCoeff();
+ return lowerbound;
}
diff --git a/src/icp_single_iteration.cpp b/src/icp_single_iteration.cpp
old mode 100644
new mode 100755
index 1e8fda9..165a7f3
--- a/src/icp_single_iteration.cpp
+++ b/src/icp_single_iteration.cpp
@@ -1,4 +1,8 @@
#include "icp_single_iteration.h"
+#include "point_to_plane_rigid_matching.h"
+#include "point_to_point_rigid_matching.h"
+#include "point_mesh_distance.h"
+#include "random_points_on_mesh.h"
void icp_single_iteration(
const Eigen::MatrixXd & VX,
@@ -11,6 +15,20 @@ void icp_single_iteration(
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 X;
+ random_points_on_mesh(num_samples,VX,FX,X);
+
+ Eigen::MatrixXd P,N;
+ Eigen::VectorXd D;
+ point_mesh_distance(X,VY,FY,D,P,N);
+
+ if (method == ICP_METHOD_POINT_TO_POINT) {
+ point_to_point_rigid_matching(X,P,R,t);
+ }
+ else { // ICP_METHOD_POINT_TO_PLANE
+ point_to_plane_rigid_matching(X,P,N,R,t);
+ }
}
diff --git a/src/point_mesh_distance.cpp b/src/point_mesh_distance.cpp
old mode 100644
new mode 100755
index 2e6a070..11106d3
--- a/src/point_mesh_distance.cpp
+++ b/src/point_mesh_distance.cpp
@@ -1,4 +1,8 @@
#include "point_mesh_distance.h"
+#include
+#include "point_triangle_distance.h"
+#include
+#include
void point_mesh_distance(
const Eigen::MatrixXd & X,
@@ -10,7 +14,35 @@ void point_mesh_distance(
{
// Replace with your code
P.resizeLike(X);
+ //N.resize(X.rows(),3);
N = Eigen::MatrixXd::Zero(X.rows(),X.cols());
- for(int i = 0;i::max();
+ Eigen::RowVector3d x = X.row(i);
+ Eigen::RowVector3d ip;
+
+ for (int j=0; j
void point_to_plane_rigid_matching(
const Eigen::MatrixXd & X,
@@ -8,6 +10,52 @@ void point_to_plane_rigid_matching(
Eigen::RowVector3d & t)
{
// Replace with your code
- R = Eigen::Matrix3d::Identity();
- t = Eigen::RowVector3d::Zero();
+ // R = Eigen::Matrix3d::Identity();
+ // t = Eigen::RowVector3d::Zero();
+ // nT
+ Eigen::MatrixXd nT;
+ nT.resize(X.rows(),3*X.rows());
+ nT << Eigen::MatrixXd (N.col(0).asDiagonal()),
+ Eigen::MatrixXd (N.col(1).asDiagonal()),
+ Eigen::MatrixXd (N.col(2).asDiagonal());
+
+ // A
+ Eigen::MatrixXd A;
+ A.resize(3*X.rows(),6);
+ Eigen::VectorXd diag_one = Eigen::VectorXd::Ones(X.rows());
+ Eigen::VectorXd zero = Eigen::VectorXd::Zero(X.rows());
+ A << zero, X.col(2), -X.col(1), diag_one, zero, zero,
+ -X.col(2), zero, X.col(0), zero, diag_one, zero,
+ X.col(1), -X.col(0), zero, zero, zero, diag_one;
+ A = nT * A;
+
+ // X - P
+ Eigen::VectorXd X_minus_P;
+ X_minus_P.resize(3*X.rows());
+ X_minus_P << X.col(0) - P.col(0),
+ X.col(1) - P.col(1),
+ X.col(2) - P.col(2);
+ X_minus_P = nT * X_minus_P;
+
+ // u
+ Eigen::Matrix u = ((A.transpose()*A).inverse()) * (-A.transpose()*X_minus_P);
+
+ // a,b,r
+ double a, b, r;
+ a = u(0,0);
+ b = u(1,0);
+ r = u(2,0);
+
+ // t
+ t << u(3,0),u(4,0),u(5,0);
+
+ // M
+ Eigen::Matrix3d M;
+ M << 1, -r, b,
+ r, 1, -a,
+ -b, a, 1;
+
+ // R
+ closest_rotation(M, R);
+
}
diff --git a/src/point_to_point_rigid_matching.cpp b/src/point_to_point_rigid_matching.cpp
old mode 100644
new mode 100755
index 079151f..99047ef
--- a/src/point_to_point_rigid_matching.cpp
+++ b/src/point_to_point_rigid_matching.cpp
@@ -1,5 +1,7 @@
#include "point_to_point_rigid_matching.h"
#include
+#include "closest_rotation.h"
+#include
void point_to_point_rigid_matching(
const Eigen::MatrixXd & X,
@@ -8,7 +10,45 @@ void point_to_point_rigid_matching(
Eigen::RowVector3d & t)
{
// Replace with your code
- R = Eigen::Matrix3d::Identity();
- t = Eigen::RowVector3d::Zero();
+ // R = Eigen::Matrix3d::Identity();
+ // t = Eigen::RowVector3d::Zero();
+ // A
+ Eigen::MatrixXd A;
+ A.resize(3*X.rows(),6);
+ Eigen::VectorXd diag_one = Eigen::VectorXd::Ones(X.rows());
+ Eigen::VectorXd zero = Eigen::VectorXd::Zero(X.rows());
+ A << zero, X.col(2), -X.col(1), diag_one, zero, zero,
+ -X.col(2), zero, X.col(0), zero, diag_one, zero,
+ X.col(1), -X.col(0), zero, zero, zero, diag_one;
+
+ // X - P
+ Eigen::MatrixXd X_minus_P;
+ X_minus_P.resize(3*X.rows(),1);
+ X_minus_P << X.col(0) - P.col(0),
+ X.col(1) - P.col(1),
+ X.col(2) - P.col(2);
+
+ // u
+ Eigen::Matrix u = (A.transpose()*A).inverse() * (-A.transpose()*X_minus_P);
+
+ // a,b,r
+ double a, b, r;
+ a = u(0,0);
+ b = u(1,0);
+ r = u(2,0);
+
+ // t
+ t << u(3,0),u(4,0),u(5,0);
+
+ // M
+ Eigen::Matrix3d M;
+ M << 1, -r, b,
+ r, 1, -a,
+ -b, a, 1;
+
+ // R
+ closest_rotation(M, R);
+
+
}
diff --git a/src/point_triangle_distance.cpp b/src/point_triangle_distance.cpp
old mode 100644
new mode 100755
index 6405100..94ab0d7
--- a/src/point_triangle_distance.cpp
+++ b/src/point_triangle_distance.cpp
@@ -1,4 +1,57 @@
#include "point_triangle_distance.h"
+#include
+
+bool point_in_triangle(
+ const Eigen::RowVector3d & a,
+ const Eigen::RowVector3d & b,
+ const Eigen::RowVector3d & c,
+ const Eigen::RowVector3d & p)
+{
+ Eigen::RowVector3d pa,pb,pc;
+ pa = (p - a).normalized();
+ pb = (p - b).normalized();
+ pc = (p - c).normalized();
+ double cos_theta = pa.dot(pb) + pa.dot(pc) + pb.dot(pc);
+ return (cos_theta == 1.0);
+}
+
+void point_line_distance (
+ const Eigen::RowVector3d & x,
+ const Eigen::RowVector3d & a,
+ const Eigen::RowVector3d & b,
+ double & d,
+ Eigen::RowVector3d & p
+)
+{
+ Eigen::RowVector3d ab,xa,n;
+ ab = a - b;
+ xa = x - a;
+ n = ab.cross(xa);
+ if ((n.norm() == 0) && (xa.norm() <= ab.norm())) { // x on ab
+ p = x;
+ d = 0;
+ return;
+ }
+
+ double dist = xa.dot(n);
+ Eigen::RowVector3d p_pontential = x - dist * n;
+
+ if ((p_pontential - a).norm() > ab.norm()) { // p is outside ab
+ p = b;
+ d = (x - b).norm();
+ }
+
+ else if ((p_pontential - b).norm() > ab.norm())
+ {
+ p = a;
+ d = (x - a).norm();
+ }
+ else {
+ p = p_pontential;
+ d = dist;
+ }
+
+}
void point_triangle_distance(
const Eigen::RowVector3d & x,
@@ -9,6 +62,30 @@ void point_triangle_distance(
Eigen::RowVector3d & p)
{
// Replace with your code
- d = 0;
- p = a;
+ // d = 0;
+ // p = a;
+ Eigen::RowVector3d n = ((a-b).cross(a-c)).normalized();
+ p = x - n.dot(x)*n;
+ // p in triangle
+ if (point_in_triangle(a,b,c,p)) {
+ d = (x - p).norm();
+ }
+ else // p outside triangle
+ {
+ double ad,bd,cd;
+ Eigen::RowVector3d ap,bp,cp;
+ point_line_distance(x,a,b,ad,ap);
+ point_line_distance(x,a,c,cd,cp);
+ point_line_distance(x,b,c,bd,bp);
+ d = ad;
+ p = ap;
+ if (cd > d) {
+ d = cd;
+ p = cp;
+ }
+ if (bd > d) {
+ d = bd;
+ p = bp;
+ }
+ }
}
diff --git a/src/random_points_on_mesh.cpp b/src/random_points_on_mesh.cpp
old mode 100644
new mode 100755
index 6e85d75..db1ade0
--- a/src/random_points_on_mesh.cpp
+++ b/src/random_points_on_mesh.cpp
@@ -1,4 +1,62 @@
#include "random_points_on_mesh.h"
+#include
+#include
+#include
+#include
+
+int find_random_index(Eigen::MatrixXd & C, double r, int start, int end) {
+// identifying the first entry in C whose value is greater than a uniform random variable γ.
+//int start = 0;
+//int end = C.rows() - 1;
+while (start != end) {
+ int mid = (start + end) / 2;
+ double c = C(mid,0);
+ if (c >= r) {
+ //start = start;
+ end = mid;
+ //mid = (start + end) / 2;
+ }
+ else if (c < r)
+ {
+ start = mid;
+ //end = end;
+ //mid = (start + end) / 2;
+ }
+}
+
+if (C(0,0) > r) {
+ return 0;
+}
+else {
+ return end;
+}
+
+
+// int mid = (start + end) / 2;
+// double c = C(mid,0);
+// if (c > r) {
+// start = start;
+// end = mid;
+// //mid = (start + end) / 2;
+// }
+
+// else if (c < r)
+// {
+// start = mid;
+// end = end;
+// //mid = (start + end) / 2;
+// }
+
+// else {
+// start = end;
+// }
+
+// if (start < end) {
+// find_random_index(C,r,start,end);
+// }
+// return mid;
+}
+
void random_points_on_mesh(
const int n,
@@ -8,6 +66,44 @@ void random_points_on_mesh(
{
// REPLACE WITH YOUR CODE:
X.resize(n,3);
- for(int i = 0;i distribution(0.0,1.0);
+ double a;
+ double b;
+ double r;
+ int index;
+
+ // random point in a single triangle mesh
+ Eigen::RowVector3d x;
+ Eigen::RowVector3i single;
+ Eigen::RowVector3d v1,v2,v3;
+
+ for (int i=0; i < X.rows(); i++){
+ r = distribution(generator);
+ index = find_random_index(C,r,0,C.rows()-1);
+ single = F.row(index);
+ v1 = V.row(single[0]);
+ v2 = V.row(single[1]);
+ v3 = V.row(single[2]);
+ a = distribution(generator);
+ b = distribution(generator);
+ if (a + b > 1) {
+ a = 1 - a;
+ b = 1 - b;
+ }
+ x = v1 + a * (v2 - v1) + b * (v3 - v1);
+ X.row(i) = x;
+ }
+
}