基於多邊形網格的三維模型在我們的工作中是最常見的,這裏,我們只針對被多邊形面片“離散化”的三維模型。
計算機圖形學相關的項目(比如快速成型,逆向工程等等)中,經常的需要判斷三維模型是否閉合,最常規的做法就是對每個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,三維散亂點集的曲面三角剖分 張永春,達飛鵬,宋文忠(東南大學自動化研究所)