|
@@ -0,0 +1,123 @@
|
|
|
|
|
+// This file is part of libigl, a simple c++ geometry processing library.
|
|
|
|
|
+//
|
|
|
|
|
+// Copyright (C) 2019 Alec Jacobson <[email protected]>
|
|
|
|
|
+//
|
|
|
|
|
+// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
|
|
|
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
|
|
+// obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
+#include "iterative_closest_point.h"
|
|
|
|
|
+#include "AABB.h"
|
|
|
|
|
+#include "per_face_normals.h"
|
|
|
|
|
+#include "matlab_format.h"
|
|
|
|
|
+#include "slice.h"
|
|
|
|
|
+#include "random_points_on_mesh.h"
|
|
|
|
|
+#include "rigid_alignment.h"
|
|
|
|
|
+#include "writeOBJ.h"
|
|
|
|
|
+#include "writeDMAT.h"
|
|
|
|
|
+#include <cassert>
|
|
|
|
|
+#include <iostream>
|
|
|
|
|
+
|
|
|
|
|
+template <
|
|
|
|
|
+ typename DerivedVX,
|
|
|
|
|
+ typename DerivedFX,
|
|
|
|
|
+ typename DerivedVY,
|
|
|
|
|
+ typename DerivedFY,
|
|
|
|
|
+ typename DerivedR,
|
|
|
|
|
+ typename Derivedt
|
|
|
|
|
+ >
|
|
|
|
|
+IGL_INLINE void igl::iterative_closest_point(
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedVX> & VX,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedFX> & FX,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedVY> & VY,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedFY> & FY,
|
|
|
|
|
+ const int num_samples,
|
|
|
|
|
+ const int max_iters,
|
|
|
|
|
+ Eigen::PlainObjectBase<DerivedR> & R,
|
|
|
|
|
+ Eigen::PlainObjectBase<Derivedt> & t)
|
|
|
|
|
+{
|
|
|
|
|
+
|
|
|
|
|
+ assert(VX.cols() == 3 && "X should be a mesh in 3D");
|
|
|
|
|
+ assert(VY.cols() == 3 && "Y should be a mesh in 3D");
|
|
|
|
|
+
|
|
|
|
|
+ typedef typename DerivedVX::Scalar Scalar;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MatrixXS;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> VectorXS;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,3,3> Matrix3S;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
|
|
|
|
|
+
|
|
|
|
|
+ // Precompute BVH on Y
|
|
|
|
|
+ AABB<DerivedVY,3> Ytree;
|
|
|
|
|
+ Ytree.init(VY,FY);
|
|
|
|
|
+ MatrixXS NY;
|
|
|
|
|
+ per_face_normals(VY,FY,NY);
|
|
|
|
|
+ return iterative_closest_point(
|
|
|
|
|
+ VX,FX,VY,FY,Ytree,NY,num_samples,max_iters,R,t);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template <
|
|
|
|
|
+ typename DerivedVX,
|
|
|
|
|
+ typename DerivedFX,
|
|
|
|
|
+ typename DerivedVY,
|
|
|
|
|
+ typename DerivedFY,
|
|
|
|
|
+ typename DerivedNY,
|
|
|
|
|
+ typename DerivedR,
|
|
|
|
|
+ typename Derivedt
|
|
|
|
|
+ >
|
|
|
|
|
+IGL_INLINE void igl::iterative_closest_point(
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedVX> & VX,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedFX> & FX,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedVY> & VY,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedFY> & FY,
|
|
|
|
|
+ const igl::AABB<DerivedVY,3> & Ytree,
|
|
|
|
|
+ const Eigen::MatrixBase<DerivedNY> & NY,
|
|
|
|
|
+ const int num_samples,
|
|
|
|
|
+ const int max_iters,
|
|
|
|
|
+ Eigen::PlainObjectBase<DerivedR> & R,
|
|
|
|
|
+ Eigen::PlainObjectBase<Derivedt> & t)
|
|
|
|
|
+{
|
|
|
|
|
+ typedef typename DerivedVX::Scalar Scalar;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MatrixXS;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> VectorXS;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,3,3> Matrix3S;
|
|
|
|
|
+ typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
|
|
|
|
|
+ R.setIdentity(3,3);
|
|
|
|
|
+ t.setConstant(1,3,0);
|
|
|
|
|
+
|
|
|
|
|
+ for(int iter = 0;iter<max_iters;iter++)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Sample random points on X
|
|
|
|
|
+ MatrixXS X;
|
|
|
|
|
+ {
|
|
|
|
|
+ Eigen::VectorXi XI;
|
|
|
|
|
+ Eigen::MatrixXd B;
|
|
|
|
|
+ MatrixXS VXRT = (VX*R).rowwise()+t;
|
|
|
|
|
+
|
|
|
|
|
+ random_points_on_mesh(num_samples,VXRT,FX,B,XI,X);
|
|
|
|
|
+ }
|
|
|
|
|
+ // Compute closest point
|
|
|
|
|
+ Eigen::VectorXi I;
|
|
|
|
|
+ MatrixXS P;
|
|
|
|
|
+ {
|
|
|
|
|
+ VectorXS sqrD;
|
|
|
|
|
+ Ytree.squared_distance(VY,FY,X,sqrD,I,P);
|
|
|
|
|
+ }
|
|
|
|
|
+ // Use better normals?
|
|
|
|
|
+ MatrixXS N;
|
|
|
|
|
+ slice(NY,I,1,N);
|
|
|
|
|
+ //MatrixXS N = (X - P).rowwise().normalized();
|
|
|
|
|
+ // fit rotation,translation
|
|
|
|
|
+ Matrix3S Rup;
|
|
|
|
|
+ RowVector3S tup;
|
|
|
|
|
+ // Note: Should try out Szymon Rusinkiewicz's new symmetric icp
|
|
|
|
|
+ rigid_alignment(X,P,N,Rup,tup);
|
|
|
|
|
+ // update running rigid transformation
|
|
|
|
|
+ R = (R*Rup).eval();
|
|
|
|
|
+ t = (t*Rup + tup).eval();
|
|
|
|
|
+ // Better stopping condition?
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef IGL_STATIC_LIBRARY
|
|
|
|
|
+// Explicit template instantiation
|
|
|
|
|
+template void igl::iterative_closest_point<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 3, 0, 3, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 3, 0, 3, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
|
|
|
|
|
+#endif
|