iterative_closest_point.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2019 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "iterative_closest_point.h"
  9. #include "AABB.h"
  10. #include "per_face_normals.h"
  11. #include "random_points_on_mesh.h"
  12. #include "rigid_alignment.h"
  13. #include <cassert>
  14. #include <iostream>
  15. template <
  16. typename DerivedVX,
  17. typename DerivedFX,
  18. typename DerivedVY,
  19. typename DerivedFY,
  20. typename DerivedR,
  21. typename Derivedt
  22. >
  23. IGL_INLINE void igl::iterative_closest_point(
  24. const Eigen::MatrixBase<DerivedVX> & VX,
  25. const Eigen::MatrixBase<DerivedFX> & FX,
  26. const Eigen::MatrixBase<DerivedVY> & VY,
  27. const Eigen::MatrixBase<DerivedFY> & FY,
  28. const int num_samples,
  29. const int max_iters,
  30. Eigen::PlainObjectBase<DerivedR> & R,
  31. Eigen::PlainObjectBase<Derivedt> & t)
  32. {
  33. assert(VX.cols() == 3 && "X should be a mesh in 3D");
  34. assert(VY.cols() == 3 && "Y should be a mesh in 3D");
  35. typedef typename DerivedVX::Scalar Scalar;
  36. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MatrixXS;
  37. // Precompute BVH on Y
  38. AABB<DerivedVY,3> Ytree;
  39. Ytree.init(VY,FY);
  40. MatrixXS NY;
  41. per_face_normals(VY,FY,NY);
  42. return iterative_closest_point(
  43. VX,FX,VY,FY,Ytree,NY,num_samples,max_iters,R,t);
  44. }
  45. template <
  46. typename DerivedVX,
  47. typename DerivedFX,
  48. typename DerivedVY,
  49. typename DerivedFY,
  50. typename DerivedNY,
  51. typename DerivedR,
  52. typename Derivedt
  53. >
  54. IGL_INLINE void igl::iterative_closest_point(
  55. const Eigen::MatrixBase<DerivedVX> & VX,
  56. const Eigen::MatrixBase<DerivedFX> & FX,
  57. const Eigen::MatrixBase<DerivedVY> & VY,
  58. const Eigen::MatrixBase<DerivedFY> & FY,
  59. const igl::AABB<DerivedVY,3> & Ytree,
  60. const Eigen::MatrixBase<DerivedNY> & NY,
  61. const int num_samples,
  62. const int max_iters,
  63. Eigen::PlainObjectBase<DerivedR> & R,
  64. Eigen::PlainObjectBase<Derivedt> & t)
  65. {
  66. typedef typename DerivedVX::Scalar Scalar;
  67. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MatrixXS;
  68. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> VectorXS;
  69. typedef Eigen::Matrix<Scalar,3,3> Matrix3S;
  70. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,3> MatrixX3S;
  71. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  72. R.setIdentity(3,3);
  73. t.setConstant(1,3,0);
  74. for(int iter = 0;iter<max_iters;iter++)
  75. {
  76. // Sample random points on X
  77. MatrixXS X;
  78. {
  79. Eigen::VectorXi XI;
  80. MatrixX3S B;
  81. MatrixXS VXRT = (VX*R).rowwise()+t;
  82. random_points_on_mesh(num_samples,VXRT,FX,B,XI,X);
  83. }
  84. // Compute closest point
  85. Eigen::VectorXi I;
  86. MatrixXS P;
  87. {
  88. VectorXS sqrD;
  89. Ytree.squared_distance(VY,FY,X,sqrD,I,P);
  90. }
  91. // Use better normals?
  92. MatrixXS N = NY(I,Eigen::placeholders::all);
  93. //MatrixXS N = (X - P).rowwise().normalized();
  94. // fit rotation,translation
  95. Matrix3S Rup;
  96. RowVector3S tup;
  97. // Note: Should try out Szymon Rusinkiewicz's new symmetric icp
  98. rigid_alignment(X,P,N,Rup,tup);
  99. // update running rigid transformation
  100. R = (R*Rup).eval();
  101. t = (t*Rup + tup).eval();
  102. // Better stopping condition?
  103. }
  104. }
  105. #ifdef IGL_STATIC_LIBRARY
  106. // Explicit template instantiation
  107. 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> >&);
  108. #endif