You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.9 KiB

// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2019 Alec Jacobson <alecjacobson@gmail.com>
//
// 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 "random_points_on_mesh.h"
#include "rigid_alignment.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;
// 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,Eigen::Dynamic,3> MatrixX3S;
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;
MatrixX3S 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 = NY(I,Eigen::all);
//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