参考文献:三维模型空洞修补算法的研究
拉普拉斯算子的应用非常广泛,它是椭圆型算子中的一个重要例子。在物理
中,常用于热传导方程、波方程的数学模型以及亥姆霍兹方程。在静电学中,拉普拉斯方程和泊松方程的应用随处可见。Laplace-Beltrami 算子的定义:是梯度的散度
Laplace-Beltrami 将 Laplace 算子的定义推广到曲面上,对于定义在流形曲面 S上的函数 f ,Laplace-Beltrami 的定义为
接下来我们讨论 Laplace − Beltrami 算子的离散化形式
过程归纳:求解离散点的权重、边的权重、求解邻域面积、最后求得拉普拉斯算子的模
1.计算边、点的权重:
void Curvature::calc_weights(){
Mesh::VertexIter v_it,v_end(m_mesh.vertices().end());
Mesh::EdgeIter e_it,e_end(m_mesh.edges().end());
Mesh::VertexFaceIter vf_it;
Mesh::FaceVertexIter fv_it;
Mesh::HalfedgeHandle h0,h1,h2;
Mesh::VertexHandle v0,v1;
Mesh::Point p0,p1,p2,d0,d1;
Mesh::Scalar w,area,b(0.99);
for(e_it=m_mesh.edges().begin();e_it!=e_end;++e_it){
w=0.0;
h0=m_mesh.halfedge_handle(e_it.handle(),0);
v0=m_mesh.to_vertex_handle(h0); //转换为半边结构中的目标点;
p0=m_mesh.point(v0);
h1=m_mesh.halfedge_handle(e_it.handle(),1);
v1=m_mesh.to_vertex_handle(h1);
p1=m_mesh.point(v1);
if(!m_mesh.is_boundary(h0)){
h2=m_mesh.next_halfedge_handle(h0);
p2=m_mesh.point(m_mesh.to_vertex_handle(h2));
d0=(p0-p2).normalize();
d1=(p1-p2).normalize();
w+=1.0/tan(acos(std::max(-b,std::min(b,d0|d1))));
}
if(!m_mesh.is_boundary(h1)){
h2=m_mesh.next_halfedge_handle(h1);
p2=m_mesh.point(m_mesh.to_vertex_handle(h2));
d0=(p0-p2).normalize();
d1=(p1-p2).normalize();
w+=1.0/tan(acos(std::max(-b,std::min(b,d0|d1))));
}
w=std::max(w,0.0f);
//边的权重;
weight(e_it)=w;
}
for(v_it=m_mesh.vertices().begin();v_it!=v_end;++v_it)
{
area=0.0f; //面积;
for(vf_it=m_mesh.vf_iter(v_it);vf_it;++vf_it)
{
fv_it=m_mesh.fv_iter(vf_it); //面对应的点;
const Mesh::Point&P=m_mesh.point(fv_it);
fv_it++;//面中的点;
const Mesh::Point&Q=m_mesh.point(fv_it);
fv_it++;
const Mesh::Point&R=m_mesh.point(fv_it);
area+=((Q-P)%(R-P)).norm()*0.5f*0.3333f;
}
//点的权重;
weight(v_it)=(fabs(area)>FLT_MIN?1.0/(2.0*area):0.0);
}
}
2.拉普拉斯算子的模的计算
void Curvature::calc_curvalture(){
Mesh::VertexIter v_it,v_end(m_mesh.vertices().end());
Mesh::HalfedgeHandle h;
Mesh::EdgeHandle e;
Mesh::VertexVertexIter vv_it;
Mesh::Point laplace(0.0,0.0,0.0);
for(v_it=m_mesh.vertices().begin();v_it!=v_end;++v_it){
curvature(v_it)=0.0;
laplace=Mesh::Point(0,0,0);
if(!m_mesh.is_boundary(v_it.handle())){
//遍历所有的点;
for(vv_it=m_mesh.vv_iter(v_it);vv_it;++vv_it){
h=vv_it.current_halfedge_handle();
e=m_mesh.edge_handle(h); //半边对应的边;
laplace+=weight(e)*(m_mesh.point(vv_it)-m_mesh.point(v_it));
}
laplace*=weight(v_it);
curvature(v_it)=laplace.norm();
//比较相互邻接的顶点的曲率;
}
}
}