博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CGAL进行半边塌缩之前的可塌缩性判断
阅读量:6852 次
发布时间:2019-06-26

本文共 4476 字,大约阅读时间需要 14 分钟。

曲面简化中通过边塌缩的方式删除顶点、边和面。边塌缩有两种方式:一种是“edge-collapse”,另一种是“halfedge-collapse”。给定一个边e,其关联的顶点分别是w和v,edge-collapse用一个新顶点r取代边e和顶点w、v,而半边塌缩则是把顶点v移到w处,即w的位置是不变的。两种方式都能够删掉边e,以及e连接的两个三角形。CGAL中使用的是halfedge-collapse。

在对某个半边进行塌缩操作之前,要检查该半边是否可进行塌缩,代码如下:

// Edge_collapse_impl.h
// 有些边塌缩之后,会导致网格的拓扑一致性被破坏,因此不能对这些边进行塌缩操作。
// 该函数用于检查边p->q的可塌缩性,若p->q可塌缩,该函数返回true
// 判断p->q是否具有可塌缩性的依据是1993年Hoppe等人的论文“Mesh Optimization”中的“link condition”,
// link condition: 对于网格中每个既是p又是q的邻居的顶点k,p-k-q是网格的一个面。
//
template
bool EdgeCollapse
::Is_collapse_topologically_valid( Profile const& aProfile )
{
bool rR = true ;
 
CGAL_ECMS_TRACE(3,"Testing topological collapsabilty of p_q=V" << aProfile.v0()->id() << "(%" << aProfile.v0()->vertex_degree() << ")"
<< "->V" << aProfile.v1()->id() << "(%" << aProfile.v1()->vertex_degree() << ")"
);
 
CGAL_ECMS_TRACE(4, "is p_q border:" << aProfile.is_v0_v1_a_border() );
CGAL_ECMS_TRACE(4, "is q_q border:" << aProfile.is_v1_v0_a_border() );
 
out_edge_iterator eb1, ee1 ;
out_edge_iterator eb2, ee2 ;
 
CGAL_ECMS_TRACE(4,"  t=V"
<< ( aProfile.left_face_exists() ? aProfile.vL()->id() : -1 )
<< "(%"
<< ( aProfile.left_face_exists() ? aProfile.vL()->vertex_degree() : 0 )
<< ")"
);
CGAL_ECMS_TRACE(4,"  b=V"
<< ( aProfile.right_face_exists() ? aProfile.vR()->id() : -1 )
<< "(%"
<< ( aProfile.right_face_exists() ? aProfile.vR()->vertex_degree() :0 )
<< ")"
);
 
// The following loop checks the link condition for v0_v1.
// Specifically, that for every vertex 'k' adjacent to both 'p and 'q', 'pkq' is a face of the mesh.
//
for ( boost::tie(eb1,ee1) = out_edges(aProfile.v0(),mSurface) ; rR && eb1 != ee1 ; ++ eb1 )
{
edge_descriptor v0_k = *eb1 ;
 
if ( v0_k != aProfile.v0_v1() )//边v0_k不是边v0_v1
{
vertex_descriptor k = target(v0_k,mSurface);
 
for ( boost::tie(eb2,ee2) = out_edges(k,mSurface) ; rR && eb2 != ee2 ; ++ eb2 )//遍历环绕k的半边,找出连接k与v1的那条
{
edge_descriptor k_v1 = *eb2 ;
 
if ( target(k_v1,mSurface) == aProfile.v1() )//找到了连接k和v1的半边
{
// 现在已知p-q-k是连通的,接下来要判断这个三角形是否是网格的一个面
//
// 由于必须是三角网格,所以至多有两个面共享边p-q
//
// 若p->q不是border edge, 设t = target(next(p->q)),则p->q上方的面为p-q-t
// 若q->p不是border edge, 设b = target(next(q->p)),则q->p下方的面为q-p-b
//
// 若k是t或者b,则p-q-k ★可能★是网格的一个面。 It won't be if k==t but p->q is border
// 若p-q-k是一个面的话,则不会出现k==t,而k->q是border或k==b而q->b是border的情况
 
bool lIsFace =   ( aProfile.vL() == k && aProfile.left_face_exists () )
|| ( aProfile.vR() == k && aProfile.right_face_exists() ) ;
 
CGAL_SURF_SIMPL_TEST_assertion_code
(
if ( lIsFace )
{
// Is k_v1 the halfedge bounding the face 'k-v1-v0'?
if ( !k_v1->is_border() && k_v1->next()->vertex() == aProfile.v0() )
{
CGAL_SURF_SIMPL_TEST_assertion( !k_v1->is_border() ) ;
CGAL_SURF_SIMPL_TEST_assertion(  k_v1                ->vertex() == aProfile.v1() ) ;
CGAL_SURF_SIMPL_TEST_assertion(  k_v1->next()        ->vertex() == aProfile.v0() ) ;
CGAL_SURF_SIMPL_TEST_assertion(  k_v1->next()->next()->vertex() == k ) ;
}
else // or is it the opposite?
{
edge_descriptor v1_k = k_v1->opposite();
CGAL_SURF_SIMPL_TEST_assertion( !v1_k->is_border() ) ;
CGAL_SURF_SIMPL_TEST_assertion(  v1_k                ->vertex() == k ) ;
CGAL_SURF_SIMPL_TEST_assertion(  v1_k->next()        ->vertex() == aProfile.v0() ) ;
CGAL_SURF_SIMPL_TEST_assertion(  v1_k->next()->next()->vertex() == aProfile.v1() ) ;
}
}
);
 
if ( !lIsFace )
{
CGAL_ECMS_TRACE(3,"  k=V" << k->id() << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ;
rR = false ;
break ;
}
else
{
CGAL_ECMS_TRACE(4,"  k=V" << k->id() << " is in a face with p-q") ;
}
}
}
}
}
 
if ( rR )//rR为真,说明p-q-k是个面,但是有可能pq边关联的另一个三角形是个洞,或者顶点p、q周围存在border
{
if ( aProfile.is_v0_v1_a_border() )
{
if ( Is_open_triangle(aProfile.v0_v1()) )
{
rR = false ;
CGAL_ECMS_TRACE(3,"  p-q belongs to an open triangle. NON-COLLAPSABLE edge." ) ;
}
}
else if ( aProfile.is_v1_v0_a_border() )
{
if ( Is_open_triangle(aProfile.v1_v0()) )
{
rR = false ;
CGAL_ECMS_TRACE(3,"  p-q belongs to an open triangle. NON-COLLAPSABLE edge." ) ;
}
}
else
{
if ( is_border(aProfile.v0()) && is_border(aProfile.v1()) )
{
rR = false ;
CGAL_ECMS_TRACE(3,"  both p and q are boundary vertices but p-q is not. NON-COLLAPSABLE edge." ) ;
}
else
{
bool lTetra = Is_tetrahedron(aProfile.v0_v1());
 
CGAL_SURF_SIMPL_TEST_assertion( lTetra == mSurface.is_tetrahedron(aProfile.v0_v1()) ) ;
 
if ( lTetra )
{
rR = false ;
CGAL_ECMS_TRACE(3,"  p-q belongs to a tetrahedron. NON-COLLAPSABLE edge." ) ;
}
}
}
}
 
return rR ;
}

转载于:https://www.cnblogs.com/youthlion/archive/2012/08/12/2634253.html

你可能感兴趣的文章
我的友情链接
查看>>
子数组的和的最大值(包括升级版的首尾相连数组)
查看>>
LeetCode - Nth Highest Salary
查看>>
9.ORM数据访问
查看>>
在RHEL5下搭建SSH远程登录服务器
查看>>
使用Moblin SDK开发应用程序 -- Image Creator
查看>>
【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记14 视图绘制Demo
查看>>
/dev/null &
查看>>
在Ubuntu上安装Node.js的Upstream版本
查看>>
扩展GridView控件(8) - 导出数据源的数据为Excel、Word或Text
查看>>
CISCO路由器配置基础(3)
查看>>
linux下通过串口登陆交换机
查看>>
微信公众平台群发规则说明
查看>>
LINUX下直接使用ISO文件
查看>>
第四章 apache的工作模式
查看>>
mysql备份和恢复总结
查看>>
软件明明已经删除 控制面板里还有名称
查看>>
深入浅出的SQL server 查询优化
查看>>
Hyper-V vNext新的虚拟机配置文件、配置版本
查看>>
通俗易懂,各常用线程池的执行 流程图
查看>>