本发明属于计算机图形学技术领域,涉及一种网格模型的表面边界恢复方法,可用于几何模型的逆向求取,在工程数值分析领域有重要的应用价值。
背景技术:
在工程数值分析方法中,网格划分是十分重要的一项工作,它的应用非常广泛,包括地理学、医学和力学等多个领域。网格划分技术主要分为结构化网格技术和非结构化网格技术。结构化网格是指网格区域内所有的内部点都具有相同的毗邻单元,而非结构化网格正相反,网格区域内的内部点不具有相同的毗邻单元。直观地来讲,结构化网格只包含四边形或者六面体,而非结构化网格是由三角形和四面体组成的。
结构化网格技术发展的相对来说比较成熟,但是其适用范围较窄。在计算机计算能力大幅提高和数值计算方法快速发展的今天,结构化网格技术已经显得力不从心了。与结构化网格相比,非结构化网格的生成技术比较复杂,但是它能够满足人们对一些复杂区域的计算要求。随着人们不断的探索和研究,非结构化网格技术也会变得越来越成熟。
网格的边界恢复是一个逆向工程问题,其意义在于利用恢复的几何模型进行模型修改或做进一步的工程分析(如网格划分)。但此问题仍然是一个难题,国内外研究较少,且没有一个广泛适用的方法。
在论文“三维约束Delaunay三角化的边界恢复方法”(机械设计与制造,2006年8月,61-63,作者:崔凌国,魏生民,姚忆斌)中,首先以两条线段的交点为圆心,以适当的边长为半径,在该圆与线段的交点处插入新节点;然后在那些非严格的Delaunay线段上,采用递归对分的方法,在该线段的中点插入新的结点,直到Delaunay化结束,便实现了边的恢复。论文“一种三角网格模型的边界提取快速算法”(计算机工程,2012年7月,208-211,作者:陈有兰,李占利,师玉璞)中,建立边栈,将所有边索引压入边栈中,并初始化一个空的边池。从边栈中弹出一个边索引与池中的所有边索引进行比较,如果2条边索引相同则视该边为内边,从池中删除;否则留在池中。继续执行该过程,直到边栈为空,结束边界提取,边池中的边即边界边。论文“基于网格模型的磨损区域边界提取方法研究”(计算机应用研究,2009年11月,4357-4359,作者:马朝霞,高健,陈新)根据磨损情况的不同,设置特征角的值,通过计算相邻三角面片法矢夹角,并与给定的特征角的值相比较来提取磨损边界点,将磨损插值成三次非均匀的有理B样条曲线,实现边界的恢复。可以看出,已有研究成果存在以下问题:(1)研究仅针对顶点铰接(顶点对顶点时称为铰接)的三角网格,而对于顶点铰接的四边形网格、三角形与四边形混合网格以及顶点不铰接的网格情况很少研究,已有成果适应面窄;(2)已提出的算法要人为的给定一些参数,如半径、特征角等,算法的健壮性不高;(3)算法仅是提取或恢复了边界边,而对于如何由边来组织形成表面的描述(如外环、内环)未见研究,已有研究不够深入。
技术实现要素:
本发明的目的是克服已有成果的不足,提供一种适应面广、逻辑关系严密、完备性好的网格模型的表面边界恢复方法。
本发明的目的是这样实现的:一种网格模型的表面边界恢复方法,其特征是:至少包括如下步骤:
步骤101:打开由点序为逆时针方向的三角形、四边形面片包络的网格模型文件,并将文件中的面片信息存入链表geo_patch_list中;三角形面片、四边形面片指的是平面片;面片包络指的是无重叠面片;点序为逆时针方向时,面片的边为有向边;
步骤102:将链表geo_patch_list中的面片按“共面同向”条件分类,并作标记,再存入共面同向分类链表sorted_patch_list中;“共面同向”面片指的是处在同一平面上且单位法向量相等的两个或多个面片;
步骤103:遍历链表sorted_patch_list,将位于一个平面上的共面同向面片存入链表coPlane_list中;
步骤104:搜索链表coPlane_list中边-边邻接的面片,找到可以组成模型的一个完整表面的所有面片,并存入链表coFace_list中;边-边邻接的面片指的是位于同一平面上且两面片的边部分重合或完全重合的面片;
步骤105:识别并提取链表coFace_list中面片的所有边界边,并将其存入边界边链表Edge_list中;边界边指的是表面边界恢复后能组成边界外环边、内环边的面片上的整条边,或者面片上边的一部分或几部分;
步骤106:将链表Edge_list中具有公共端点的边界边按顺序首尾相接连成单环,单环的所有边存入链表orderEdge_list中;
步骤107:按不共线的相邻两边的公共点即为环的顶点这一原则,从链表orderEdge_list中提取环顶点,将以点序表示的单环存入表面环链表loop_coFace_list中;
步骤108:清空链表orderEdge_list;
步骤109:判断链表Edge_list是否为空,若不为空,转至步骤106;若为空,转至步骤110;
步骤110:遍历表面环链表loop_coFace_list,求各环的轴向包围盒,只有一个环或具有最大包围盒的环即为外环,并做外环标记,其他环为内环并做内环标记,将做标记的环按先外环后内环的顺序存入恢复边界后的模型环总链表loop_list中;
步骤111:清空链表coFace_list、loop_coFace_list;
步骤112:判断链表coPlane_list是否为空,若不为空,转至步骤104;若为空,转至步骤113;
步骤113:判断链表sorted_patch_list是否遍历完,若未遍历完,转至步骤103;若遍历完,转至步骤114;
步骤114:输出恢复边界后的模型环总链表loop_list。
所述的步骤102中将链表geo_patch_list中的面片按“共面同向”条件分类,并作标记,再存入共面同向分类链表sorted_patch_list中,包括以下步骤:
步骤201:判断链表geo_patch_list是否为空,若为空,转至步骤208;若不为空,转至步骤202;
步骤202:读取链表geo_patch_list中第一个面片作为基准面片,并作类别标记;
步骤203:判断链表geo_patch_list中是否存在下一个面片,若存在,转至步骤205;若不存在,转至步骤204;
步骤204:将基准面片及其标记存入分类链表sorted_patch_list中,并将其从链表geo_patch_list中删除,转至步骤201;
步骤205:读取链表geo_patch_list中下一个面片作为被判断面片;
步骤206:判断基准面片与被判断面片是否为共面同向的面片,若是,转至步骤207;若不是,转至步骤203;面片A与面片B共面同向时须同时满足:面片A各顶点坐标代入面片B的平面方程时方程均成立、面片A和面片B的单位法向量的三个分量分别相等;
步骤207:将被判断面片作与基准面片同类标记后存入分类链表sorted_patch_list中,并将其从链表geo_patch_list中删除,转至步骤203;
步骤208:输出共面同向面片分类链表sorted_patch_list。
所述的步骤104中搜索链表coPlane_list中边-边邻接的面片,找到可以组成模型的一个完整表面的所有面片,并存入链表coFace_list中,包括以下步骤:
步骤301:将链表coPlane_list中第一个面片存入链表coFace_list中,再将其从链表coPlane_list中删除;
步骤302:判断coFace_list中的面片是否遍历完,若未遍历完,转至步骤303;若遍历完,转至步骤308;
步骤303:读取链表coFace_list中未遍历面片作为参考面片;
步骤304:判断链表coPlane_list中是否存在面片,若存在,转至步骤305;若不存在,转至步骤308;
步骤305:将链表coPlane_list中的面片作为目标面片,遍历所有目标面片;
步骤306:判断目标面片中是否有与参考面片边-边邻接的面片,若有,转至步骤307;若没有,转至步骤302;设面片1的有向边为面片2的有向边为面片1的有向边和面片2的有向边边-边邻接时须同时满足:①和距离为0;②设点C在上的投影系数为λC、点D在上的投影系数为λD,存在投影系数区间(λD,λC),使得区间(λD,λC)与区间(0,1)的交集不为空集,其中区间(λD,λC)中假定λD<λC,若不满足,则调换两者位置;设M、N是有向边的两个端点,P是有向边外一点,则点P到有向边的距离为点P在有向边上的投影系数定义为一个有向边的两个端点到另一个有向边的距离均为0时称为两个有向边的距离为0;
步骤307:将满足边-边邻接条件的面片存入链表coFace_list末尾,并将其从链表coPlane_list中删除,转至步骤302;
步骤308:输出含一个完整表面所有面片的链表coFace_list。
所述的步骤105中识别并提取链表coFace_list中面片的所有边界边,并将其存入边界边链表Edge_list中,包括以下步骤:
步骤401:判断coFace_list中的面片是否都遍历完,若遍历完,转至步骤415;若未遍历完,转至步骤402;
步骤402:读取coFace_list中未遍历的一个面片作为基面片,并作已遍历标记;
步骤403:判断基面片的边是否遍历完,若遍历完,转至步骤401;若未遍历完,转至步骤404;
步骤404:读取基面片的一条边作为被判断边,将coFace_list中除基面片外的其他面片的边作为判断边,遍历判断边;
步骤405:判断是否存在与被判断边距离为0的判断边,若存在,转至步骤406;若不存在,转至步骤414;
步骤406:依次求出这些判断边在被判断边上的投影系数区间;
步骤407:判断是否每一条判断边的投影系数区间与区间(0,1)均无交集,若是,转至步骤414;若不是,转至步骤408;
步骤408:用数组vec_Modu记录投影系数区间与区间(0,1)有交集的判断边,数组元素存储该判断边的两个端点及其投影系数;
步骤409:遍历数组vec_Modu中的元素,若两相邻元素有公共端点,则将两元素合并为一个元素,合并后的元素存储两个非公共端点及相应的投影系数;
步骤410:判断数组vec_Modu中的元素个数n是否为1,若是,转至步骤411;若不是,转至步骤413;
步骤411:判断区间(0,1)是否为数组vec_Modu中元素投影系数区间的子集,若是,转至步骤403;若不是,转至步骤412;
步骤412:分三种情况由被判断边生成次生边界边,将其两个端点存入边界边链表Edge_list中,转至步骤403;次生边界边是指参与组成表面边界外环或内环的面片边的一部分或几部分;设被判断边为AB、数组vec_Modu中元素存储的边为MN,边MN两端点M、N的投影系数分别为λM、λN,生成次生边界边的三种情况是:①若λN≤0<λM<1时,次生边界边为MB;②若0<λN<λM<1时,次生边界边为AN、MB;③若0<λN<1≤λM时,次生边界边为AN;
步骤413:分四种情况由被判断边生成次生边界边,将其两个端点存入边界边链表Edge_list中,转至步骤403;设被判断边为AB,数组vec_Modu中第i个元素(i=1,…,n)对应的边的端点分别为Mi、Ni,其投影系数满足生成次生边界边的四种情况是:①若且时,次生边界边为MiNi+1(i=1,…,n-1);②若且时,次生边界边为MiNi+1(i=1,…,n-1)、MnB;③若且时,次生边界边为AN1、MiNi+1(i=1,…,n-1);④若且时,次生边界边为AN1、MiNi+1(i=1,…,n-1)、MnB;
步骤414:被判断边为完全边界边,将其两个端点存入边界边链表Edge_list中,转至步骤403;完全边界边是指整条边都参与组成表面边界外环或内环的面片边;
步骤415:输出边界边链表Edge_list。
所述的步骤106中将链表Edge_list中具有公共端点的边界边按顺序首尾相接连成单环,单环的所有边存入链表orderEdge_list中,包括以下步骤:
步骤501:将链表Edge_list中第一条边存入单环的边链表orderEdge_list中,并将其从链表Edge_list中删除;
步骤502:读取链表orderEdge_list中的边作为前驱边;
步骤503:判断链表Edge_list中是否为空,若为空,转至步骤507;若不为空,转至步骤504;
步骤504:将链表Edge_list中的边作为被查找边,遍历被查找边,判断被查找边的起始点的坐标与前驱边的终止点的坐标是否相等,若相等,则此被查找边作为后继边;
步骤505:判断链表Edge_list中是否存在后继边,若存在,转至步骤506;若不存在,转至步骤507;
步骤506:将后继边存入单环的边链表orderEdge_list的末尾,并将其从链表Edge_list中删除,转至步骤502;
步骤507:输出组成单环的所有边的链表orderEdge_list。
所述的步骤107中按不共线的相邻两边的公共点即为环的顶点这一原则,从链表orderEdge_list中提取环顶点,将以点序表示的单环存入表面环链表loop_coFace_list中,包括以下步骤:
步骤601:将链表orderEdge_list中的第一条边的拷贝存入链表orderEdge_list的末尾;
步骤602:读取链表orderEdge_list中的第一条边作为前驱边;
步骤603:判断链表orderEdge_list是否遍历完成,若遍历完,转至步骤607;若未遍历完,转至步骤604;
步骤604:读取链表orderEdge_list中的下一条边作为后继边,将前一条边作为前驱边;
步骤605:判断前驱边和后继边是否不共线,若是,转至步骤606;若不是,转至步骤603;设前驱边为AB、后继边为BC,点A、B、C坐标为:A(x1,y1,z1)、B(x2,y2,z2)、C(x3,y3,z3),前驱边AB和后继BC不共线时须满足(Y1Z2-Y2Z1)2+(X2Z1-X1Z2)2+(X1Y2-X2Y1)2>ε2,X1=x2-x1,Y1=y2-y1,Z1=z2-z1,X2=x3-x1,Y2=y3-y1,Z2=z3-z1,ε为误差精度,取值为0.001;
步骤606:将前驱边和后继边的公共点存入表面环链表loop_coFace_list中,转至步骤603;表面环链表存储一个表面的各个环,每个环由环顶点按前后顺序组成;
步骤607:输出表面环链表loop_coFace_list。
所述的步骤110中遍历表面环链表loop_coFace_list,求各环的轴向包围盒,只有一个环或具有最大包围盒的环即为外环,并做外环标记,其他环为内环并做内环标记,将做标记的环按先外环后内环的顺序存入恢复边界后的模型环总链表loop_list中,包括以下步骤:
步骤701:判断表面环链表loop_coFace_list中是否只有一个环,若是,转至步骤704;若不是,转至步骤702;
步骤702:依次计算链表loop_coFace_list中每个环的轴向包围盒坐标极值;假设环由m个顶点组成,从这m个顶点的x坐标中找出最小x坐标xmin、最大x坐标xmax,从这m个顶点的y坐标中找出最小y坐标ymin、最大y坐标ymax,从这m个顶点的z坐标中找出最小z坐标zmin、最大z坐标zmax,则xmin、xmax、ymin、ymax、zmin、zmax为环的轴向包围盒坐标极值;
步骤703:找出最大的包围盒,此包围盒对应的环为外环,并作外环标记,其他环则为内环,并作内环标记;假设表面有n个环,第i(i=1,…,n)个环的轴向包围盒坐标极值为ximin、ximax、yimin、yimax、zimin、zimax,若第j(j∈{1,…,n})个环的轴向包围盒坐标极值xjmin、xjmax、yjmin、yjmax、zjmin、zjmax同时满足:xjmax≥ximax,xjmin≤ximin,yjmax≥yimax,yjmin≤yimin,zjmax≥zimax,zjmin≤zimin时,则第j个环的包围盒为最大包围盒,第j个环即为外环,除第j个以外的其他n-1个环即为内环;
步骤704:此环为外环,作外环标记,转至步骤705;
步骤705:将做标记的环按先外环后内环的顺序存入模型环总链表loop_list中。
本发明有如下优点:
(1)本发明具有适应面广,不论形状简单还是复杂的表面边界都能实现恢复。对于顶点铰接或不铰接的纯三角网格、纯四边形网格或三角形、四边形混合网格等大尺寸或小尺寸网格单元的平面网格均可实现表面边界的恢复。
(2)本发明具有逻辑关系严密、完备性好,不存在几何处理上的漏洞。
附图说明
图1是本发明的总流程图;
图2是共面同向面片分类的流程图;
图3是边-边邻接面片搜索的流程图;
图4是边界边识别和提取的流程图;
图5是表面单环的生成流程图;
图6是提取环顶点的流程图;
图7是区分内、外环的流程图;
图8是一个网格模型示例图;
图9是图8模型上一类共面同向面片的表面边界恢复示例图;
图10是图8模型表面边界恢复后的示例图。
具体实施方式
本发明的网格模型为表面模型,是由三角形平面片、四边形平面片包络而成的几何体,包络要求面片之间无重叠,面片尺寸可大可小,面片的顶点可以铰接(顶点对顶点称为铰接),也可以不铰接,且三角形面片、四边形面片的顶点顺序由模型外观察时是逆时针方向,三角形面片和四边形面片的边是有向边。
本发明研究网格模型的表面边界恢复,恢复完成后给出以点序形式表示的由内环、外环表示表面边界的一种模型。
本发明的实现过程为:首先,从模型中找出共面同向面片,共面同向面片指的是处在同一平面上且单位法向量相等的两个或多个面片,因为只有共面同向面片才能合并为模型的一个或几个表面;接着,对处在同一平面的共面同向面片的边-边邻接关系进行分析,获得能够组成模型每个表面的面片;之后,对每个表面,识别并提取表面面片的边界边,由边界边首尾相连形成若干个环,再提取环顶点得到以点序表示的环;最后,区分内、外环,得到模型表面的轮廓边界。
参照图1,本发明的一种网格模型的表面边界恢复方法包括如下步骤:
步骤101:打开由点序为逆时针方向的三角形、四边形面片包络的网格模型文件,并将文件中的面片信息存入链表geo_patch_list中;参照图8,此网格模型由37个四边形面片包络而成,将这些面片信息存入链表geo_patch_list中;
步骤102:将链表geo_patch_list中的面片按“共面同向”条件分类,并作标记,再存入共面同向分类链表sorted_patch_list中;“共面同向”面片指的是处在同一平面上且单位法向量相等的两个或多个面片;参照图9,面片1、2、3、4、5、6、7就是图8网格模型中的共面同向面片,将其标记为一类面片,并存入链表sorted_patch_list中,其余面片作同样的处理,图8模型的面片经此步骤分类后共有23类共面同向面片,分类标记后都存入sorted_patch_list中;
步骤102中将链表geo_patch_list中的面片按“共面同向”条件分类,并作标记,再存入共面同向分类链表sorted_patch_list中,参照图2,包括以下步骤:
步骤201:判断链表geo_patch_list是否为空,若为空,转至步骤208;若不为空,转至步骤202;
步骤202:读取链表geo_patch_list中第一个面片作为基准面片,并作类别标记;
步骤203:判断链表geo_patch_list中是否存在下一个面片,若存在,转至步骤205;若不存在,转至步骤204;
步骤204:将基准面片及其标记存入分类链表sorted_patch_list中,并将其从链表geo_patch_list中删除,转至步骤201;
步骤205:读取链表geo_patch_list中下一个面片作为被判断面片;
步骤206:判断基准面片与被判断面片是否为共面同向的面片,若是,转至步骤207;若不是,转至步骤203;面片A与面片B共面同向时须同时满足:面片A各顶点坐标代入面片B的平面方程时方程均成立、面片A和面片B的单位法向量的三个分量分别相等;
步骤207:将被判断面片作与基准面片同类标记后存入分类链表sorted_patch_list中,并将其从链表geo_patch_list中删除,转至步骤203;
步骤208:输出共面同向面片分类链表sorted_patch_list。
步骤103:遍历链表sorted_patch_list,将位于一个平面上的共面同向面片存入链表coPlane_list中;参照图9,假设面片1、2、3、4、5、6、7这一类是按顺序1、4、5、6、7、2、3存入链表coPlane_list的;
步骤104:搜索链表coPlane_list中边-边邻接的面片,找到可以组成模型的一个完整表面的所有面片,并存入链表coFace_list中;边-边邻接的面片指的是位于同一平面上且两面片的边部分重合或完全重合的面片;参照图9,在第一次循环到本步骤时,链表coFace_list中存储面片1;在第二次循环到本步骤时,链表coFace_list中存储面片4、5、6、2、3、7;
步骤104中搜索链表coPlane_list中边-边邻接的面片,找到可以组成模型的一个完整表面的所有面片,并存入链表coFace_list中,参照图3,包括以下步骤:
步骤301:将链表coPlane_list中第一个面片存入链表coFace_list中,再将其从链表coPlane_list中删除;
步骤302:判断coFace_list中的面片是否遍历完,若未遍历完,转至步骤303;若遍历完,转至步骤308;
步骤303:读取链表coFace_list中未遍历面片作为参考面片;
步骤304:判断链表coPlane_list中是否存在面片,若存在,转至步骤305;若不存在,转至步骤308;
步骤305:将链表coPlane_list中的面片作为目标面片,遍历所有目标面片;
步骤306:判断目标面片中是否有与参考面片边-边邻接的面片,若有,转至步骤307;若没有,转至步骤302;设面片1的有向边为面片2的有向边为面片1的有向边和面片2的有向边边-边邻接时须同时满足:①和距离为0;②设点C在上的投影系数为λC、点D在上的投影系数为λD,存在投影系数区间(λD,λC),使得区间(λD,λC)与区间(0,1)的交集不为空集,其中区间(λD,λC)中假定λD<λC,若不满足,则调换两者位置;设M、N是有向边的两个端点,P是有向边外一点,则点P到有向边的距离为点P在有向边上的投影系数定义为一个有向边的两个端点到另一个有向边的距离均为0时称为两个有向边的距离为0;
步骤307:将满足边-边邻接条件的面片存入链表coFace_list末尾,并将其从链表coPlane_list中删除,转至步骤302;
步骤308:输出含一个完整表面所有面片的链表coFace_list。
步骤105:识别并提取链表coFace_list中面片的所有边界边,并将其存入边界边链表Edge_list中;边界边指的是表面边界恢复后能组成边界外环边、内环边的面片上的整条边,或者面片上边的一部分或几部分;参照图9,以步骤104得到的链表coFace_list中存储面片4、5、6、2、3、7为例,假设图中每个面片按左边、下边、右边、上边的逆时针顺序存储,本步骤完成后,链表Edge_list中存储的边界边为:GF、ⅥⅤ、JM、ⅡⅠ、ML、ⅢⅡ、ⅤⅣ、KJ、AH、HG、IA、ED、DⅥ、FE、LK、ⅣC、CB、BⅢ;
步骤105中识别并提取链表coFace_list中面片的所有边界边,并将其存入边界边链表Edge_list中,参照图4,包括以下步骤:
步骤401:判断coFace_list中的面片是否都遍历完,若遍历完,转至步骤415;若未遍历完,转至步骤402;
步骤402:读取coFace_list中未遍历的一个面片作为基面片,并作已遍历标记;
步骤403:判断基面片的边是否遍历完,若遍历完,转至步骤401;若未遍历完,转至步骤404;
步骤404:读取基面片的一条边作为被判断边,将coFace_list中除基面片外的其他面片的边作为判断边,遍历判断边;边界边在被判断边上产生;
步骤405:判断是否存在与被判断边距离为0的判断边,若存在,转至步骤406;若不存在,转至步骤414;
步骤406:依次求出这些判断边在被判断边上的投影系数区间;
步骤407:判断是否每一条判断边的投影系数区间与区间(0,1)均无交集,若是,转至步骤414;若不是,转至步骤408;区间(0,1)代表被判断边;
步骤408:用数组vec_Modu记录投影系数区间与区间(0,1)有交集的判断边,数组元素存储该判断边的两个端点及其投影系数;
步骤409:遍历数组vec_Modu中的元素,若两相邻元素有公共端点,则将两元素合并为一个元素,合并后的元素存储两个非公共端点及相应的投影系数;
步骤410:判断数组vec_Modu中的元素个数n是否为1,若是,转至步骤411;若不是,转至步骤413;
步骤411:判断区间(0,1)是否为数组vec_Modu中元素投影系数区间的子集,若是,说明被判断边被其他判断边完全覆盖,被判断边为非边界边,转至步骤403;若不是,转至步骤412;
步骤412:分三种情况由被判断边生成次生边界边,将其两个端点存入边界边链表Edge_list中,转至步骤403;次生边界边是指参与组成表面边界外环或内环的面片边的一部分或几部分;设被判断边为AB、数组vec_Modu中元素存储的边为MN,边MN两端点M、N的投影系数分别为λM、λN,生成次生边界边的三种情况是:①若λN≤0<λM<1时,次生边界边为MB;②若0<λN<λM<1时,次生边界边为AN、MB;③若0<λN<1≤λM时,次生边界边为AN;
步骤413:分四种情况由被判断边生成次生边界边,将其两个端点存入边界边链表Edge_list中,转至步骤403;设被判断边为AB,数组vec_Modu中第i个元素(i=1,…,n)对应的边的端点分别为Mi、Ni,其投影系数满足生成次生边界边的四种情况是:①若且时,次生边界边为MiNi+1(i=1,…,n-1);②若且时,次生边界边为MiNi+1(i=1,…,n-1)、MnB;③若且时,次生边界边为AN1、MiNi+1(i=1,…,n-1);④若且时,次生边界边为AN1、MiNi+1(i=1,…,n-1)、MnB;
步骤414:被判断边为完全边界边,将其两个端点存入边界边链表Edge_list中,转至步骤403;完全边界边是指整条边都参与组成表面边界外环或内环的面片边;
步骤415:输出边界边链表Edge_list。
步骤106:将链表Edge_list中具有公共端点的边界边按顺序首尾相接连成单环,单环的所有边存入链表orderEdge_list中;以步骤105得到的链表Edge_list中存储的边界边为例,第一次循环到本步骤时,链表orderEdge_list中存储的边为GF、FE、ED、DⅥ、ⅥⅤ、ⅤⅣ、ⅣC、CB、BⅢ、ⅢⅡ、ⅡⅠ、IA、AH、HG;第二次循环到本步骤时,链表orderEdge_list中存储的边为JM、ML、LK、KJ;
步骤106中将链表Edge_list中具有公共端点的边界边按顺序首尾相接连成单环,单环的所有边存入链表orderEdge_list中,参照图5,包括以下步骤:
步骤501:将链表Edge_list中第一条边存入单环的边链表orderEdge_list中,并将其从链表Edge_list中删除;
步骤502:读取链表orderEdge_list中的边作为前驱边;
步骤503:判断链表Edge_list中是否为空,若为空,转至步骤507;若不为空,转至步骤504;
步骤504:将链表Edge_list中的边作为被查找边,遍历被查找边,判断被查找边的起始点的坐标与前驱边的终止点的坐标是否相等,若相等,则此被查找边作为后继边;
步骤505:判断链表Edge_list中是否存在后继边,若存在,转至步骤506;若不存在,转至步骤507;
步骤506:将后继边存入单环的边链表orderEdge_list的末尾,并将其从链表Edge_list中删除,转至步骤502;
步骤507:输出组成单环的所有边的链表orderEdge_list。
步骤107:按不共线的相邻两边的公共点即为环的顶点这一原则,从链表orderEdge_list中提取环顶点,将以点序表示的单环存入表面环链表loop_coFace_list中;以步骤106两次循环得到的结果为例,本步骤第一次循环完成后,链表loop_coFace_list中存储第一个环的顶点依次为F、E、D、C、B、A、H、G;本步骤第二次循环完成后,链表loop_coFace_list中存储第二个环的顶点依次为M、L、K、J;
步骤107中按不共线的相邻两边的公共点即为环的顶点这一原则,从链表orderEdge_list中提取环顶点,将以点序表示的单环存入表面环链表loop_coFace_list中,参照图6,包括以下步骤:
步骤601:将链表orderEdge_list中的第一条边的拷贝存入链表orderEdge_list的末尾;
步骤602:读取链表orderEdge_list中的第一条边作为前驱边;
步骤603:判断链表orderEdge_list是否遍历完成,若遍历完,转至步骤607;若未遍历完,转至步骤604;
步骤604:读取链表orderEdge_list中的下一条边作为后继边,将前一条边作为前驱边;
步骤605:判断前驱边和后继边是否不共线,若是,转至步骤606;若不是,转至步骤603;设前驱边为AB、后继边为BC,点A、B、C坐标为:A(x1,y1,z1)、B(x2,y2,z2)、C(x3,y3,z3),前驱边AB和后继BC不共线时须满足(Y1Z2-Y2Z1)2+(X2Z1-X1Z2)2+(X1Y2-X2Y1)2>ε2,X1=x2-x1,Y1=y2-y1,Z1=z2-z1,X2=x3-x1,Y2=y3-y1,Z2=z3-z1,ε为误差精度,取值为0.001;
步骤606:将前驱边和后继边的公共点存入表面环链表loop_coFace_list中,转至步骤603;表面环链表存储一个表面的各个环,每个环由环顶点按前后顺序组成;
步骤607:输出表面环链表loop_coFace_list。
步骤108:清空链表orderEdge_list;
步骤109:判断链表Edge_list是否为空,若不为空,转至步骤106;若为空,转至步骤110;
步骤110:遍历表面环链表loop_coFace_list,求各环的轴向包围盒,只有一个环或具有最大包围盒的环即为外环,并做外环标记,其他环为内环并做内环标记,将做标记的环按先外环后内环的顺序存入恢复边界后的模型环总链表loop_list中;以步骤107的结果为例,表面环链表loop_coFace_list存储了环F、E、D、C、B、A、H、G和环M、L、K、J,经过本步骤判断,环F、E、D、C、B、A、H、G具有最大轴向包围盒,判定为外环,而环M、L、K、J则为内环,这两个环就是图9右边表面的边界,将其按先外环后内环的顺序存入恢复边界后的模型环总链表loop_list中;
步骤110中遍历表面环链表loop_coFace_list,求各环的轴向包围盒,只有一个环或具有最大包围盒的环即为外环,并做外环标记,其他环为内环并做内环标记,将做标记的环按先外环后内环的顺序存入恢复边界后的模型环总链表loop_list中,参照图7,包括以下步骤:
步骤701:判断表面环链表loop_coFace_list中是否只有一个环,若是,转至步骤704;若不是,转至步骤702;
步骤702:依次计算链表loop_coFace_list中每个环的轴向包围盒坐标极值;假设环由m个顶点组成,从这m个顶点的x坐标中找出最小x坐标xmin、最大x坐标xmax,从这m个顶点的y坐标中找出最小y坐标ymin、最大y坐标ymax,从这m个顶点的z坐标中找出最小z坐标zmin、最大z坐标zmax,则xmin、xmax、ymin、ymax、zmin、zmax为环的轴向包围盒坐标极值;
步骤703:找出最大的包围盒,此包围盒对应的环为外环,并作外环标记,其他环则为内环,并作内环标记;假设表面有n个环,第i(i=1,…,n)个环的轴向包围盒坐标极值为ximin、ximax、yimin、yimax、zimin、zimax,若第j(j∈{1,…,n})个环的轴向包围盒坐标极值xjmin、xjmax、yjmin、yjmax、zjmin、zjmax同时满足:xjmax≥ximax,xjmin≤ximin,yjmax≥yimax,yjmin≤yimin,zjmax≥zimax,zjmin≤zimin时,则第j个环的包围盒为最大包围盒,第j个环即为外环,除第j个以外的其他n-1个环即为内环;
步骤704:此环为外环,作外环标记,转至步骤705;
步骤705:将做标记的环按先外环后内环的顺序存入模型环总链表loop_list中。
步骤111:清空链表coFace_list、loop_coFace_list;
步骤112:判断链表coPlane_list是否为空,若不为空,转至步骤104;若为空,转至步骤113;
步骤113:判断链表sorted_patch_list是否遍历完,若未遍历完,转至步骤103;若遍历完,转至步骤114;
步骤114:输出恢复边界后的模型环总链表loop_list;参照图10,经过步骤101~步骤114后,图8所示网格模型经边界恢复后的模型环总链表loop_list中存储了24个表面边界,其中对应图9右边的表面的边界含有一个外环、一个内环,其他23个表面的边界只含一个外环。