根据距离分类的算法:
总的流程图:(伪代码)
输入:网格src
得到src每个点的距离
if(如果距离>0.25)
{
归类为setA,进行优化求解;
优化求解后,已经和原网格很接近了,为了更高的精度再进行投影
}
else
{
归类为setB,直接进行投影;
}
先在Nonrigidreg里面读取偏差值,然后到MeshForFEA中进行分类,并进行显示,看下对不对
在Registration中进行读取,然后分类,因为非刚体配准是将网格进行缩小变换后得到的结果,所以单独读取网格,不进行网格的缩放,这个读取的网格后面都加N,参考下面函数进行初始化
函数调用
Mesh src_mesh;
Mesh tar_mesh;
read_data(src_file, src_mesh, use_demean);
read_data(tar_file, tar_mesh, use_demean);
reg->rigid_init(src_mesh, tar_mesh, paras);
类Registration中的实现
//.h
Mesh* src_mesh_;
Mesh* tar_mesh_;
void rigid_init(Mesh& src_mesh, Mesh& tar_mesh, RegParas& paras);
//.cpp
void Registration::rigid_init(Mesh & src_mesh, Mesh & tar_mesh, RegParas& paras)
{
src_mesh_ = new Mesh;
tar_mesh_ = new Mesh;
src_mesh_ = &src_mesh;
tar_mesh_ = &tar_mesh;
pars_ = paras;
n_src_vertex_ = src_mesh_->n_vertices();
n_tar_vertex_ = tar_mesh_->n_vertices();
}
我进行分类函数的使用,注意New后一定要进行delete,有可能最后我把整个reg类给delete后就没事了
//读取文件
Mesh src_mesh_N;
Mesh tar_mesh_N;
read_data(src_file, src_mesh_N,false);
read_data(tar_file, tar_mesh_N,false);
//读取网格进行处理,提取偏差数据
reg->rigid_init(src_mesh, tar_mesh, paras);//刚体配准初始化后,会初始化一个点对
reg->Sort_init(src_mesh_N, tar_mesh_N);//网格读取
reg->SortByDeviation();//根据距离分类
Sort_init(src_mesh_N, tar_mesh_N);用于得到网格初始值
void Registration::Sort_init(Mesh &src_mesh_N_, Mesh & tar_mesh_N_)
{
src_mesh_N = new Mesh;
tar_mesh_N = new Mesh;
src_mesh_ = &src_mesh_N_;
tar_mesh_ = &tar_mesh_N_;
}
SortByDeviation();用于分类并输出文件
void Registration::SortByDeviation(void)
{
//使用的数据
//Mesh* src_mesh_N;
//Mesh* tar_mesh_N;
//我已经找到了点对correspondence_pairs_,直接使用这个点对就行了
Eigen::VectorXd Deviation = Eigen::VectorXd::Zero(n_src_vertex_);
Eigen::Matrix3Xd rig_src_v = Eigen::Matrix3Xd::Zero(3, n_src_vertex_);
Eigen::Matrix3Xd rig_tar_v = Eigen::Matrix3Xd::Zero(3, n_src_vertex_);
double xs0, ys0, zs0;
double xt0, yt0, zt0;
double deviation;
#ifdef USE_OPENMP
#pragma omp parallel for
#endif
for (int i0 = 0; i0 < correspondence_pairs_.size(); i0++)
{
rig_src_v.col(i0) = Eigen::Map<Eigen::Vector3d>(src_mesh_N->
point(src_mesh_N->vertex_handle(correspondence_pairs_[i0].first)).data(), 3, 1);
rig_tar_v.col(i0) = Eigen::Map<Eigen::Vector3d>(tar_mesh_N
->point(tar_mesh_N->vertex_handle(correspondence_pairs_[i0].second)).data(), 3, 1);
xs0 = rig_src_v.col(i0)[0];
ys0 = rig_src_v.col(i0)[1];
zs0 = rig_src_v.col(i0)[2];
xt0 = rig_tar_v.col(i0)[0];
yt0 = rig_tar_v.col(i0)[1];
zt0 = rig_tar_v.col(i0)[2];
OpenMesh::Vec3d ps(xs0, ys0, zs0);
OpenMesh::Vec3d pt(xt0, yt0, zt0);
//norm =( (x2-x1)^2 + (y2-y1)^2 )^1/2,即两点之间的距离
deviation = (ps - pt).norm();
Deviation[i0] = deviation;
}
//输出文件
std::string Filename_Dev = "E://YZBdata//DebugFile//PointDeviation.txt";
std::ofstream File_Dev(Filename_Dev, std::ios::binary);
File_Dev << Deviation << std::endl;
File_Dev.flush();
}
点的提取参考
for (int i0 = 0; i0 < correspondence_pairs_.size(); i0++)
{
rig_src_v.col(i0) = Eigen::Map<Eigen::Vector3d>(src_mesh_->point(src_mesh_->vertex_handle(correspondence_pairs_[i0].first)).data(), 3, 1);
rig_tar_v.col(i0) = Eigen::Map<Eigen::Vector3d>(tar_mesh_->point(tar_mesh_->vertex_handle(correspondence_pairs_[i0].second)).data(), 3, 1);
xs0 = rig_src_v.col(i0)[0];
ys0 = rig_src_v.col(i0)[1];
zs0 = rig_src_v.col(i0)[2];
xt0 = rig_tar_v.col(i0)[0];
yt0 = rig_tar_v.col(i0)[1];
zt0 = rig_tar_v.col(i0)[2];
OpenMesh::Vec3d ps(xs0, ys0, zs0);
OpenMesh::Vec3d pt(xt0, yt0, zt0);
OpenMesh::Vec3d stepsize(0,0,0);
OpenMesh::Vec3d src_normal = src_mesh_->normal(src_mesh_->vertex_handle(i0));
double AC_dist = (pt - ps) | src_normal / src_normal.sqrnorm();
double step = 0.5;
if (AC_dist > step)
{
stepsize[0] = step * src_normal[0];
stepsize[1] = step * src_normal[1];
stepsize[2] = step * src_normal[2];
count++;
}
else
{
stepsize[0] = AC_dist * src_normal[0];
stepsize[1] = AC_dist * src_normal[1];
stepsize[2] = AC_dist * src_normal[2];
}
OpenMesh::Vec3d ptn;
ptn[0] = ps[0] + stepsize[0];
ptn[1] = ps[1] + stepsize[1];
ptn[2] = ps[2] + stepsize[2];
src_mesh_->set_point(src_mesh_->vertex_handle(i0), ptn);
}
分类参考的程序