资讯详情

三维薄板样条,用于三维模型变形(c++)

刚接触变形算法,其实不想碰三维变形算法,一只菜鸡,但导师总是让试试,然后试试,事实证明薄板样条不特别适合古建筑云变形,第一次写文章只是记录我学过,否则根据我的记忆,基本上忘记了。

薄板样条一般用于图像匹配,二维图像处理不可战胜,三维真的不太强,至少只有二维变形,三维作为二维,忽略第三维信息,用二维图像提取轮廓,用类似的三角形变形,这里说的是基于轮廓线和薄板样条的三维自动化建模方法毕竟,论文类型可以完全避免同时三个维度的变形,我们不知道它是否正确。经过这几天的研究,我写的三维薄板样条的代码总是变形不是特别好。圆柱体、长方体、正方体简单。提供控制点和控制点和变形坐标来变形,但在使用一些点云时,最后通过薄板样条计算出各种各样的点。

失败的就不放了,丢人现眼。本来不想碰拉普拉斯的,看来还得去自己编。

static double tps_base_func(double r)///用于计算基函数r {  if (r == 0.0)   return 0.0;  else   return r*r * log(r*r); } static void calc_tps() {  // You We need at least 3 points to define a plane  if (control_points.size() < 3)   return;   unsigned p = control_points.size();   // Allocate the matrix and vector  matrix<double> mtx_l(p   4, p   4);//L矩阵    matrix<double> mtx_v(p   4, 3);//包含v 和  o  matrix<double> mtx_orig_k(p, p);//K矩阵  matrix<double>w(p, 4);          double a = 0.0;  for (unsigned i = 0; i < p;   i)  {   for (unsigned j = i   1; j < p;   j)   {       mtx_l(i, j) = mtx_l(j, i) =     mtx_orig_k(i, j) = mtx_orig_k(j, i) = tps_base_func((control_points[i] - control_points[j]).len()); //tps_base_func(elen);//????//Uij上下对角传递    //a  = elen * 2; // same for upper & lower tri   }  }  a /= (double)(p*p);//a=a/p^2         // Fill the rest of L  for (unsigned i = 0; i < p;   i)  {   // diagonal: reqularization parameters (lambda * a^2)重新量化对角线的参数   mtx_l(i, i) = mtx_orig_k(i, i) =     regularization * (a*a);///变形程度 目前为0             // P (p x 3, upper right) 已改 4*P 增加Y   mtx_l(i, p   0) = 1.0;   mtx_l(i, p   1) = control_points[i].x;    mtx_l(i, p   2) = control_points[i].y;   mtx_l(i, p   3) = control_points[i].z;  //fill P up right and down left   mtx_l(p   0, i) = 1.0;   mtx_l(p   1, i) = control_points[i].x;   mtx_l(p   2, i) = control_points[i].y;   mtx_l(p   3, i) = control_points[i].z;   }  // O (3 x 3, lower right)  改4*4  for (unsigned i = p; i < p   4;   i)  {   for (unsigned j = p; j < p   4;   j)   {    mtx_l(i, j) = 0.0;   }  }  // Fill the right hand vector V   maybe is matrix  for (unsigned j = 0; j < 3;   j)  {   for (int i = 0; i < 4; i  )   {    mtx_v(p   i, j) = 0;   }  }  for (size_t i = 0; i < TransformationPoint.size(); i  )  {        mtx_v(i, 0) = TransformationPoint[i].x;     mtx_v(i, 1) = TransformationPoint[i].y;     mtx_v(i, 2) = TransformationPoint[i].z;  }  cout << "--------------------L矩阵-----------------" << endl;  for (unsigned i = 0; i < p 4; i  )  {   for (unsigned j = 0; j < p 4; j  )   {    cout << mtx_l(i, j) << "\t";   }   cout << endl;  }  cout << " ----------------v矩阵-----------------------" << endl;  for (int i = 0; i < p 4; i  )  {   for (int j = 0; j < 3; j  )   {    cout << mtx_v(i, j) << "\t";    }   cout << endl;  }   if (0!= LU_Solve(mtx_l, mtx_v)&&1== LU_Solve(mtx_l, mtx_v))//0为成功  1为奇异矩阵 2 行数不对等  {   puts("Singular matrix! Aborting.");   cout << "计算不成功,奇异矩阵" << endl;   exit(1);     }  cout << "---------------------------系数----------------------------------" << endl;  for (int i = 0; i < p   4; i  )  {   for (int j = 0; j < 3; j  )   {    cout << mtx_v(i, j) << "\t";   }   cout << endl;  }  //WxU  WyU  WzU权重分配  float WxU = 0;  float WyU = 0;  float WzU = 0;    for (int i = 0; i < EnteredPoint.size(); i  )  {   double x= mtx_v(p   0, 0)   mtx_v(p   1, 0)*EnteredPoint[i].x      mtx_v(p   2, 0)*EnteredPoint[i].y   mtx_v(p   3, 0)*EnteredPoint[i].z;   double y= mtx_v(p   0, 1)   mtx_v(p   1, 1)*EnteredPoint[i].x      mtx_v(p   2, 1)*EnteredPoint[i].y   mtx_v(p   3, 1)*EnteredPoint[i].z;   double z= mtx_v(p   0, 2)   mtx_v(p   1, 2)*EnteredPoint[i].x      mtx_v(p   2, 2)*EnteredPoint[i].y   mtx_v(p   3, 2)*EnteredPoint[i].z;      for (int j = 0; j < p; j  )//权重系数很小   {     WxU  = mtx_v(j, 0) * tps_base_func((EnteredPoint[i] - control_points[j]).len());     WyU  = mtx_v(j, 1) * tps_base_func((EnteredPoint[i] - control_points[j]).len());     WzU  = mtx_v(j, 2) * tps_base_func((EnteredPoint[i] - control_points[j]).len());   }   //cout <<"v    "<< x WxU << "   " << y   WyU << " " << z   WzU << "" << endl; 	//cout <<  WxU << " " <<  WyU << "  " <<  WzU << endl;
		std::cout << "计算第" << i << "次" << "   " << "还剩" << EnteredPoint.size() - i << "待计算" << std::endl;
		cout <<" v  "<<x+ WxU << " " <<y+ WyU << "  " << z+WzU << endl;
		
		AfterDeformPoint.push_back(Vec(x + WxU, y + WyU, z + WzU));
		
	}
	
	std::cout << "计算完成" << endl;
	
	// Calc bending energy
	
	for (int i = 0; i < p; ++i)
	{
		w(i, 0) = mtx_v(i, 0);//    弯曲能量部分待研究
		w(i, 1) = mtx_v(i, 1);
		w(i, 2) = mtx_v(i, 2);
		
	}
	matrix<double> be = prod(prod<matrix<double> >(trans(w), mtx_orig_k), w);
	bending_energy = be(0, 0);
	cout << "弯曲能量为=  " << bending_energy << endl;
	
}
void ReadControlPoint()
{
	ifstream infile("E:\\ExperimentalData\\expData\\test\\gd.txt");
	float a, b, c;
	while (infile >> a >> b >> c)
	{
		control_points.push_back(Vec(a, b, c));
	}

}
void ReadTransformationPoint()
{
	ifstream tranfile("E:\\ExperimentalData\\expData\\test\\mv.txt");//C:\\Users\\Administrator\\Desktop
																   //E:\\ExperimentalData\\expData\\test\\zhenshi700.txt
	float a, b, c,N1,N2,N3,N4,N5,N6;
	while (tranfile>>a>>b>>c)//tranfile >> a>> b >> c>>N1>>N2>>N3>>N4>>N5>>N6
	{
		TransformationPoint.push_back(Vec(a, b, c));
	}
}
void reaeAllPoints()
{
	        //c_obj 定义一个网格对象
	int mask;     //定义mask
				  //注意your filePath不能有中文路径
	vcg::tri::io::ImporterOBJ<MyMesh>::Open(m_obj, "E:\\ExperimentalData\\expData\\test\\524.obj", mask);
	//为每个点计算法线并归一化
	vcg::tri::RequirePerVertexNormal(m_obj);
	vcg::tri::UpdateNormal<MyMesh>::PerVertexNormalized(m_obj);
	std::vector <MyVertex> &vs = m_obj.vert;
	std::vector<MyEdge> &es = m_obj.edge;
	std::vector<MyFace> &fs = m_obj.face;
	for (auto i = 0; i < m_obj.vert.size(); ++i)
	{
		MyVertex v = vs[i];
		EnteredPoint.push_back(Vec(v.P().X(), v.P().Y(), v.P().Z()));
	}
}
void OutputPoints()
{
	MyVertex v;
	for (int i = 0; i < EnteredPoint.size(); i++)
	{
		v.P().X() = AfterDeformPoint[i].x;
		v.P().Y() = AfterDeformPoint[i].y;
		v.P().Z() = AfterDeformPoint[i].z;
		c_obj.vert.push_back(v);
		//cout << "x=  "<< AfterDeformPoint[i].x << "y=  " << AfterDeformPoint[i].y << "z= " << AfterDeformPoint[i].z << endl;
	}
	
	/*for (size_t i = 0; i < c_obj.vert.size(); i++)
	{
		cout <<"v"<<"  "<< c_obj.vert[i].P().X() << "  " << c_obj.vert[i].P().Y() << "   " << c_obj.vert[i].P().Z()<< endl;
	}*/
	c_obj.edge = m_obj.edge;
	c_obj.face = m_obj.face;
	//vcg::tri::BuildMeshFromCoordVectorIndexVector(c_obj, c_obj.vert, c_obj.face);
	//vcg::tri::Octahedron(c_obj);
	vcg::tri::io::ExporterOBJ<MyMesh>::Save(c_obj, "C:\\Users\\Administrator\\Desktop\\c_obj.obj", 0);
}
void outDataToTxt()
{
	ofstream location_out;
	///*/注意路径前面不能有!空格否则会读不进去坐标//
	location_out.open("E:\\ExperimentalData\\expData\\test\\location_out.txt", std::ios::out | std::ios::app);  //以写入和在文件末尾添加的方式打开.txt文件,没有的话就创建该文件。
	if (!location_out.is_open())
		cout << "open file error" << endl;

	for (int i = 0; i < EnteredPoint.size(); i++)
	{
		location_out << "v " << AfterDeformPoint[i].x << " " << AfterDeformPoint[i].y << " " << AfterDeformPoint[i].z << endl;
	}
	location_out.close();
	
}

int main()
{
	
	
	reaeAllPoints();
	ReadControlPoint();
	ReadTransformationPoint();
	
	
	calc_tps();
	outDataToTxt();
	system("pause");
	return 0;

}

代码水平有限,也是自己摸索。真实点云作变形,计算出的模型顶点坐标会是特别大的数简直离谱。懂的大佬有没有知道古建筑三维变形最好用什么变形算法~难道只有拉普拉斯吗?

标签: 韩国继电器wyu

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台