基于多边形网格的三维模型在我们的工作中是最常见的,这里,我们只针对被多边形面片“离散化”的三维模型。
计算机图形学相关的项目(比如快速成型,逆向工程等等)中,经常的需要判断三维模型是否闭合,最常规的做法就是对每个n边形面片进行判断,如果每个n边形面片都与其他n个m边形面片相邻(m可以等于n,也可以不等于),那么这个三维模型就是闭合的,这样做的时间复杂度是:O(n方);对比较复杂的模型,比如:几万个甚至更多的n边形面片,这个复杂度过大了,会影响系统效率。
这里,提出一个效率比较好的方法,假设三维模型网格的边数为:line_count,组成三维模型的w个n边形面片分别为:polygon1,polygon2,……polygonw;它们的边数依次是:n1,n2,……nw,则假如是闭合的三维模型,就满足:line_count*2=polygon1*n1+polygon2*n2+……+polygonw*nw。否则(line_count*2!=polygon1*n1+polygon2*n2+……+polygonw*nw),就是不闭合的三维模型;使用这个公式,除了line_count,其他变量都为已知,时间复杂度为:O(n*logn)。这是因为:如果三维模型闭合,则每条边必然是两个n边形面片的邻边,我们把邻边看成是两条边,则顺利成章的出来了上面的公式。在模型离散化表示中,三角面片是最常见的,下面我们将以三角面片为例进行阐述,其他的可以类推。
在中国图像图形学报上的一篇“三维散乱点集的曲面三角剖分”上有这样一个公式,也印证了我的想法,看下图:
下面呈上简单的代码,代码中使用了红黑树,红黑树相关的内容,详见我的另一篇博文:红黑树的代码实现。这里代码略去:
struct Section
{
Triangle** tri;
int tri_count;
};
enum SectionType
{
SECTION_TYPE_CLOSED, SECTION_TYPE_CONNECTED, SECTION_DETACH, SECTION_TYPE_UNDEFINE
};
//获得三维模型中点的个数
static int get_vertex_count(Triangle ** pTri,int tri_num)
{
float3* vertex_collection=new float3[tri_num*5];
int i = 0;
RB_Tree tree_vertex;
initial_tree_with_vertex( pTri, tree_vertex, vertex_collection, i );
for ( int j = 1; j != tri_num; ++j )
{
add__tree_with_vertex( pTri, tree_vertex, vertex_collection, i, j );
}
delete[] vertex_collection;
return tree_vertex.size;
}
//获得三维模型中边的数量
static int get_line_count( Triangle** pTri,int tri_num)
{
float3* line_center_collection = new float3[tri_num*5];
int i = 0;
RB_Tree tree_line;
initial_tree_for_judgeTopological( pTri, tree_line, line_center_collection, i );
for ( int j = 1; j != tri_num; ++j )
{
add__tree_for_judgeTopological( pTri, tree_line, line_center_collection, i, j );
}
delete[] line_center_collection;
return tree_line.size;
}
/// <summary>
///获得模型的拓扑结构(连通,闭合,分离)
/// </summary>
/// <param name="sect">三维模型</param>
/// <returns>模型的拓扑结构(连通,闭合,分离)</returns>
SectionType get_section_type(Section *sect)
{
LinkObject object;
int vertex_count=get_vertex_count(sect->tri,sect->tri_count);
int line_count=get_line_count(sect->tri,sect->tri_count);
if(line_count<vertex_count-1)
{
return SECTION_DETACH;
}
split_STL_model(object,sect->tri,sect->tri_count);
if(object.m_pEnd!=NULL)
{
return SECTION_DETACH;
}
else if(line_count * 2 == sect->tri_count * 3 )
{
return SECTION_TYPE_CLOSED;
}
else if(line_count * 2 > sect->tri_count * 3)
{
return SECTION_TYPE_CONNECTED;
}
return SECTION_TYPE_UNDEFINE;
}
参考文献:
1,三维散乱点集的曲面三角剖分 张永春,达飞鹏,宋文忠(东南大学自动化研究所)