vcg面面关系
vcg的面面关系通过tri::UpdateTopology<CMeshO>::FaceFace
方法初始化
FaceFace
1.先获取所有的边
static void FillEdgeVector(MeshType &m, std::vector<PEdge> &e, bool includeFauxEdge=true)
。。。
//先遍历面获取边的数量
for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(! (*fi).IsD()) n_edges+=(*fi).VN();
//遍历所有的面获取边信息
(*p).Set(&(*pf),j) //pf为面 j代表第几个顶点(边)
//对所有的边进行排序,排序的依据取决于 inline bool operator < ( const PEdge & pe ) const
//先比较第一个点的地址,然后比较第二个,由于顶点是存储在vector中,所以地址是连续的
//根据边信息获取面信息
//重第一条边开始
typename std::vector<PEdge>::iterator pe,ps;
ps = e.begin();pe=e.begin();
//循环分析关系
do
{
//判断是否已到结尾或者边是否相等(两个顶点相同)
if( pe==e.end() || !(*pe == *ps) )
{
typename std::vector<PEdge>::iterator q,q_next;
//遍历重开始到迭代器结尾迭代器前一个迭代器的所有边
for (q=ps;q<pe-1;++q)
{
//边序号必须大于-1
assert((*q).z>=0);
//获取相对于当前迭代器的下一个迭代器
q_next = q;
++q_next;
//确保下一个迭代器边序号大于-1
assert((*q_next).z>=0);
//确保下一个迭代器变序号小于面的顶点数
assert((*q_next).z< (*q_next).f->VN());
//FFp函数:(*this).Base().AF[(*this).Index()]._fp[j]
//(*this).Index()表示当前面的序号,也就是(*q).f这个面的序号
//AF为std::vector<struct AdjTypePack> AV
//整句代码表示(*q).f这个面的第q->z条边的邻接面为(*q_next).f
(*q).f->FFp(q->z) = (*q_next).f;
//类似的,(*q).f这个面的第q->z个点(边)是(*q_next).f这个面的第z个点(边)
(*q).f->FFi(q->z) = (*q_next).z;
}
assert((*q).z>=0);
assert((*q).z< (*q).f->VN());
//回过头来处理q_next的信息
(*q).f->FFp((*q).z) = ps->f;
(*q).f->FFi((*q).z) = ps->z;
//下个循环从pe开始
ps = pe;
++ne;
}
//结尾的迭代器已到结尾那么分析结束
if(pe==e.end()) break;
//否则结尾迭代器往前进一位
++pe;
} while(true);
分析边的几种情况
1.ps边没有是边界边,也就是没有多个三角形共用这条边,这种情况下pe为ps+1,也就是说for (q=ps;q<pe-1;++q)
循环无法进入,但是for循环下面的代码会执行,也就是
(*q).f->FFp((*q).z) = ps->f;
(*q).f->FFi((*q).z) = ps->z;
此时q==ps,所以边界边的邻接三角形就是自己
2.ps边为两个三角形共用的边,这是比较常规的情况,此时pe=pe+1,由于边数据是排过序的,所以此时pe=ps,那么++pe,接着进行下一次判断,此时q_next就是pe+1,由于pe与q_next是同一条边当时属于两个三角形,所以三角形的邻接关系就出来了,处理完两条边相互之间的邻接关系之后,ps=pe,++pe,开始下一轮循环
3.ps边为超过两个三角形共用的边,也就是交叠边现象,此时pe会多次++跳过这些三角形,for循环中会依次处理这些交叠的三角形,但是否循环之后,只会处理最后一个三角形与倒数第一个三角形关于这条边的邻接关系:
比如 f1 f2 f3是这种交叠的关系,
那么f1对于交叠边的邻接三角形是f2
f2对于交叠边的邻接三角形是f3
f3对于交叠边的临界三角形是f1
情况二是情况三的一种特殊情况
tri::Clean<CMeshO>::CountNonManifoldEdgeFF
获取交叠边的数量
主要方法为
//如果是流形边,返回true,否则返回false
template <class FaceType>
inline bool IsManifold( FaceType const & f, const int j )
{
//确保面面关系不为空,也就是经过了FaceFace函数
assert(f.cFFp(j) != 0); // never try to use this on uncomputed topology
if(FaceType::HasFFAdjacency())
//f.cFFp(j) == &f代表边界边
//f.cFFp(j)->cFFp(f.cFFi(j)) f第j条边的邻接面的对应边的邻接面f1,如果f==f1,说明是正常的邻
//接关系
return ( f.cFFp(j) == &f || &f == f.cFFp(j)->cFFp(f.cFFi(j)) );
else
return true;
}