一种三维平面实体的布尔并运算方法与流程

文档序号:13423191阅读:973来源:国知局
一种三维平面实体的布尔并运算方法与流程

本发明属于计算机图形学技术领域,涉及一种三维平面实体的布尔并运算方法,具体地说是两个三维平面实体通过布尔并运算以得到新的三维实体的方法。



背景技术:

布尔并运算是三维平面实体布尔运算的核心算法之一,可用于cad、cam、cae、计算机动画、虚拟现实、3d打印等领域的三维实体建模。

随着计算机图形学的不断发展,特别是三维可视化、虚拟现实技术、3d打印技术等的迅猛发展,具有自主知识产权的三维建模技术已成为诸多领域的迫切需求,而基于布尔运算的三维实体建模技术是重中之重。三维实体的布尔运算包括并运算、差运算和交运算。在建模实践中,交运算使用很少,并运算和差运算使用较多。实体布尔并运算作为一种构造实体模型的主要手段,在模型主体形状形成、模型无缝连接以及模型的拼接等方面有着广泛的应用。而且,由于二维布尔运算是三维布尔运算的基础,考虑到两个二维图形a和b的差运算(-)可以转换为并运算(+),即a-b=a+(-b),因此,并运算又是差运算的基础。从理论和实践方面看,对于三维实体布尔并运算的研究,具有重要的学术意义和应用价值。

三维实体布尔运算在商用软件中已很成熟,但其实现方法在公开文献上很少见到。从实用角度上讲,brep(边界表示)法是三维布尔运算的主要实现方式。brep方法是用点、边、面、环以及它们之间相互的邻接关系定义三维实体,实体表面、边界线、交线等都显式给出,参与布尔运算的实体、运算中几何元素处理以及运算得到的实体都采用brep形式。由于曲面可以由平面逼近,因此平面实体之间的布尔运算是实现包括曲面在内的复杂实体建模的基础。

目前研究基于brep形式的三维实体布尔运算的公开文献较少。文献“计算机图形学”(清华大学出版社,1995年8月,作者:孙家广)介绍了muuss和butler于1991年提出的“求交共享、分类、归并”的非正则三维形体布尔运算方法,即先面面求交,以交线为界利用欧拉算子对两个面环进行拓扑重构,然后把每个形体上的点、边、环几何元素与另一个形体进行比较分类,以决定这些几何元素在另一形体之内、之外还是边界上,最后根据并、交、差运算类型对几何元素分类结果进行取舍,以决定哪些元素作为结果保留,哪些元素被丢弃;论文“基于实体模型的布尔运算算法与实现”(山东科技大学硕士学位论文,2007年5月,作者:陈辉)针对两个简单三维形体,采用类似于muuss和butler的“求交共享、分类、归并”的布尔运算思想实现了交运算,基于交运算结果和差运算与交运算的转换关系来实现差运算,再基于两个形体相互差运算结果合并得到两个形体的并运算,即运算之间相互依赖,差运算依赖交运算,并运算依赖交运算和两个差运算;论文“基于降维的三维布尔运算算法与实现”(上海交通大学硕士学位论文,2008年2月,作者:周志超)提出三维布尔运算的结果由保留面和修改面组成,其修改面由截切平面与剖面通过传统的二维布尔运算得到,且保留面和修改面的获取方法依三维布尔运算的类型(并、交、差)不同而不同,该文的三维布尔运算、二维布尔运算都是一种运算类型对应一种算法;专利“一种三维平面实体的布尔运算方法”(zl201410369841.x,2017年1月,发明人:许社教等)提出了基于形体内外关系判断和二维内裁剪和外裁剪运算的三维实体布尔运算方法。其基本思想是认为两个三维平面实体a和b布尔运算的结果是由保留面和修改面组成的,先通过形体内外关系判断和内裁剪、外裁剪运算产生两个实体布尔运算所用的四个共享信息链表a_out_b、a_in_b、b_out_a、b_in_a,然后按照布尔运算类型由共享信息链表形成布尔运算结果。该专利存在以下问题:一是未考虑两个平面实体表面同向共面情况,这会导致两个实体求并时出错,致使工程中经常使用的贴并建模不能进行;二是算法有冗余计算,如求并运算用不到a_in_b、b_in_a,求交运算用不到a_out_b、b_out_a,求差运算a-b用不到a_in_b、b_out_a,求差运算b-a用不到a_out_b、b_in_a。可以看出,已有研究成果存在以下问题:(1)算法完备性缺乏强有力的理论支撑;(2)算法复杂,实现难度较大;(3)算法效率不高,运算量较大。



技术实现要素:

本发明的目的在于克服上述已有技术的不足,针对三维平面实体布尔运算中的并运算,提供一种算法简单、算法完备且算法运算量小的三维平面实体的布尔并运算方法。

本发明的目的是这样实现的:一种三维平面实体的布尔并运算方法,其特征是:至少包括如下步骤:

步骤101:依次读入参与运算的两个实体a和b的面数据,其中实体a的面、环、边和点的信息分别保存在a_face_list、a_loop_list、a_line_list、a_point_list链表中,实体b的面、环、边和点的信息分别保存在b_face_list、b_loop_list、b_line_list、b_point_list链表中;实体的面为平面多边形,它可以只有一个外环,也可以有一个外环和一个或多个内环;

步骤102:设置实体a和实体b的交换标志swap及布尔差运算标志sub_flag,定义并运算结果存储链表body_list,并置swap=false,sub_flag=false;

步骤103:给实体a和实体b的面做标记,如果是内环面则标记为非0,如果是非内环面则标记为0;内环面是指外环上的一条边是其他面的内环上的一条边的面;

步骤104:遍历链表a_point_list、a_line_list、a_loop_list、a_face_list,求取实体a的包围盒值a.min.x.、a.min.y、a.min.z、a.max.x、a.max.y、a.max.z;遍历链表b_point_list、b_line_list、b_loop_list、b_face_list,求取实体b的包围盒值b.min.x.、b.min.y、b.min.z、b.max.x、b.max.y、b.max.z;

步骤105:判断实体a的包围盒与实体b的包围盒是否相离,若不相离则转至步骤106,若相离则转至步骤117;

步骤106:遍历实体a的链表a_point_list、a_line_list、a_loop_list、a_face_list,取实体a的一个面fa;

步骤107:判断面fa是否在实体b的外面,如果面fa在实体b的外面则转至步骤118,否则转至步骤108;

步骤108:遍历实体b的链表b_point_list、b_line_list、b_loop_list、b_face_list,取实体b的一个面fb;

步骤109:判断面fa和面fb是否同向共面且都不是内环面,如果条件成立,转至步骤115,如果条件不成立,转至步骤110;同向共面是指几何上处在一个平面上且外法线矢量方向相同的两个或多个面;

步骤110:用面fa的扩大面与面fb求交,交线段保存在链表a_inter_b中;面fa的扩大面是指与fa在一个平面上且边长足够大(取106)的正方形面;

步骤111:判断实体b的面是否处理完,如果没有处理完,转至步骤108,如果处理完,转至步骤112;

步骤112:将链表a_inter_b中的线段进行首尾相连构造环,将构造的环存入链表loop_list中;用loop_list中各环的法向量和面fa的法向量方向进行比较,若方向相同则环的顶点顺序不变,否则将环的顶点顺序反向排列;在loop_list中找出内环,将内环顶点顺序反向排列;最后得到的环链表loop_list即是用面fa的扩大面切实体b得到的剖面多边形f的数据;清空链表a_inter_b;

步骤113:置布尔差运算标志sub_flag=true;

步骤114:将剖面多边形f赋给面fb;

步骤115:对面fa和面fb进行二维多边形的并运算,将运算结果保存在链表_out_中;链表_out_保存的是实体a和实体b三维并运算的部分结果;

步骤116:判断实体a的面是否处理完,如果处理完,转至步骤119,如果没有处理完,转至步骤106;

步骤117:令链表a_out_b=a_face_list,链表b_out_a=b_face_list,合并两个链表a_out_b、b_out_a到链表body_list中,输出并运算结果链表body_list;

步骤118:保存实体a的面fa到链表_out_中,转至步骤116;

步骤119:判断交换标志swap是否为true,如果是,转至步骤122,如果不是,则转至步骤120;

步骤120:将链表_out_中的数据拷贝到链表a_out_b中,并清空链表_out_;

步骤121:交换实体a和实体b的数据,即将实体b的面、环、边和点的信息拷贝给实体a,将实体a的面、环、边和点的信息拷贝给实体b,并置swap=true,转至步骤103;

步骤122:将链表_out_中的数据拷贝到链表b_out_a中,并清空链表_out_;

步骤123:合并链表a_out_b和链表b_out_a的数据到body_list中,进行后处理,删除重复面和悬挂面;

步骤124:合并同向共面且有重合线段的两个或多个面为一个面;

步骤125:输出并运算结果链表body_list。

所示的步骤103中给实体a和实体b的面做标记,如果是内环面则标记为非零,如果是非内环面则标记为零,包括以下步骤:

步骤201:从链表a_plane_list中读取实体a的面信息,定义标记面的变量count,count的初值为0,并将所有的面初始标记为count;

步骤202:令变量count=count+1;

步骤203:按实体a中面的存储顺序,读取一个面;

步骤204:判断该面是否存在内环,如果该面存在内环,转至步骤205,如果该面不存在内环,转至步骤213;

步骤205:按存储顺序取出一个内环,将内环的顶点数据压入链表pt_list中;

步骤206:按实体a中面的存储顺序,读取一个面;

步骤207:判断该面标记值是否不为0,如果条件成立,转至步骤210,如果条件不成立,转至步骤208;

步骤208:判断该面的外环顶点是否在链表pt_list中,如果不在,转至步骤210,否则转至步骤209;

步骤209:令该面标记值为count;

步骤210:判断实体a的面是否遍历完,如果遍历完,转至步骤211,如果未遍历完,转至步骤206;

步骤211:清空链表pt_list,对标记值count进行加1操作;

步骤212:判断该面的内环是否遍历完,如果遍历完,转至步骤213,如果没有遍历完,转至步骤205;

步骤213:判断实体a的面是否遍历完,如果遍历完,转至步骤214,如果未遍历完,转至步骤203;

步骤214:对实体b执行步骤201~步骤213,将步骤中的实体a的数据换成实体b的数据,对实体b的面进行标记。

所示的步骤107中,判断面fa是否在实体b的外面,包括以下步骤:

步骤301:求取实体b的轴向包围盒b.max.x、b.max.y、b.max.z、b.min.x、b.min.y、b.min.z;求取面fa的轴向包围盒fa.max.x、fa.max.y、fa.max.z、fa.min.x、fa.min.y、fa.min.z;

步骤302:判断fa.max.x是否小于b.min.x,如果不成立,转至步骤303,如果成立,转至步骤309;

步骤303:判断fa.min.x是否大于b.max.x,如果不成立,转至步骤304,如果成立,转至步骤309;

步骤304:判断fa.max.y是否小于b.min.y,如果不成立,转至步骤305,如果成立,转至步骤309;

步骤305:判断fa.min.y是否大于b.max.y,如果不成立,转至步骤306,如果成立,转至步骤309;

步骤306:判断fa.max.z是否小于b.min.z,如果不成立,转至步骤307,如果成立,转至步骤309;

步骤307:判断fa.min.z是否大于b.max.z,如果不成立,转至步骤308,如果成立,转至步骤309;

步骤308:面fa不一定在实体b的外部;

步骤309:面fa在实体b的外部。

所示的步骤109中,判断面fa和面fb是否同向共面且都不是内环面,包括以下步骤:

步骤401:读取已做标记的面fa和面fb数据;

步骤402:判断面fa和面fb的标记值是否都为零,如果条件成立,则转至步骤403,否则转至步骤409;

步骤403:分别求取面fa和面fb的单位法向量和;

步骤404:判断和是否相等,如果相等,转至步骤405,如果不相等,则转至步骤409;

步骤405:从面fa和面fb中分别取其外环上的一个顶点,且保证这两个点不是同一个点,所取点分别记作点pota和点potb;

步骤406:用点pota和点potb作一条直线,求出其方向向量;

步骤407:判断面fa的单位法向量和方向向量是否垂直,如果垂直,转至步骤408,否则转至步骤409;

步骤408:面fa和面fb同向共面且都不是内环面;

步骤409:面fa和面fb不满足同向共面且都不是内环面。

所示的步骤115中,对面fa和面fb进行二维多边形的并运算,将运算结果保存在链表_out_中,包括以下步骤:

步骤501:读取面fa和面fb的数据;

步骤502:判断面fa和面fb的外环的位置关系是否相交,如果相交,转至步骤503,如果不相交,转至步骤517;

步骤503:定义标记面fa和面fb的内环上是否有交点的两个数组minner_label[]和cinner_label[],数组大小分别为面fa和面fb的内环个数,初始化数组minner_label[]和cinner_label[]的所有标记值为0;经相交关系判断,若内环上有交点,则令两个面相应的内环的标记值为1;

步骤504:分别定义保存面fa和面fb的顶点、交点信息以及交点出入属性的数组datap[]和dataq[],定义面fa的出点数组out_point[];先将面fa和面fb的顶点分别存入数组datap[]和dataq[]中,并令其属性值为0,然后求出两个面环的交点,并判断交点的出入属性,若交点为入点,则其属性值为1,若交点为出点,则其属性值为-1,将交点及其属性值按照交点在环上的位置分别插入到数组datap[]和dataq[]中;同时将面fa的出点存入到数组out_point[]中;交点为“入点”是指在该点处面fa的边进入了面fb,交点为“出点”是指在该点处面fa的边离开了面fb;

步骤505:判断布尔差运算标志sub_flag是否为true,若为true,转至步骤516,若不为true,则转至步骤506;

步骤506:判断面fa和面fb是否有内环,如果有内环,转至步骤515,如果没有内环,转至步骤507;

步骤507:从出点数组out_point[]中取出一个出点,并赋值给点变量pottmp;

步骤508:在面fa的数组data_p[]中按顺序查找到对应的出点;

步骤509:将该点保存在临时结果环链表looptmp.point_list中,在datap[]中从该点向后继续遍历,遇到顶点则保存在链表looptmp.point_list中,遇到入点则进入面fb的数组dataq[]中找到对应的点,并保存在链表looptmp.point_list中,接着在dataq[]中从该点向后继续遍历,遇到顶点保存在链表looptmp.point_list中,遇到针对面fb的入点则进入面fa的数组datap[]中找到对应的点;

步骤510:判断该点是否和点pottmp为同一点,如果是同一点,转至步骤511,如果不是同一点,转至步骤509;

步骤511:将链表looptmp.point_list中的点保存在环链表tmpface_list中,并清空链表looptmp.point_list;

步骤512:判断面fa的出点数组out_point[]是否遍历完,如果遍历完,转至步骤513,如果没有遍历完,转至步骤507;

步骤513:求取环链表tmpface_list中各环的法向量,判断其和面fa的外法向量的方向是否相同,方向相同者则是外环,方向不同者则是内环;

步骤514:按照先外环后内环的存储顺序构造面链表,将结果保存到并运算结果链表_out_中;

步骤515:根据数组minner_label[]和cinner_label[]中的标记值判断面fa对应的无交点内环和面fb对应的无交点内环的去留问题,分为以下两种情况:第一种情况,如果面fa的内环在面fb的外环的外面,则该内环保留,如果面fa的内环在面fb的外环里面且在面fb的内环外面,则该内环不保留,如果面fa的内环在面fb的内环里面,则该内环保留;第二种情况,如果面fb的内环在面fa的外环的外面,则该内环保留,如果面fb内环在面fa的外环的里面且在面fa的内环外面,则该内环不保留,如果面fb的内环在面fa的内环里面,则该内环保留;将保留的环保存在环链表tmpface_list中;

步骤516:将面fb的dataq[]中的顶点和交点反向排列,置sub_flag=false,转到步骤506;

步骤517:判断面fa和面fb的外环位置关系是否相离,如果相离,转至步骤518,如果不相离,转至步骤519;

步骤518:将面fa的内、外环和面fb的内、外环都保存在并运算结果链表_out_中;

步骤519:若面fa的外环在面fb外环的内部,则保存面fb的外环到并运算结果链表_out_中,若面fa的外环在面fb外环的外部,则保存面fa的外环到并运算结果链表_out_中,转至步骤503。

所示的步骤123中,进行后处理,删除重复面和悬挂面,包括以下步骤:

步骤601:从链表body_list中取出一个面f;

步骤602:遍历链表body_list中除面f之外的其余的面,若有与面f重复的面f1,则删除面f1;

步骤603:判断body_list中的面是否遍历完,如果遍历完,转至步骤604,如果没有遍历完,转至步骤601;

步骤604:将body_list中的面遍历一遍,将所有面的顶点保存到点链表pt_list中;

步骤605:按顺序取body_list中的一个面ff,设置布尔标志label,并置label=false;

步骤606:定义变量count为面ff外环的每个顶点在链表pt_list中出现的次数;

步骤607:取面ff外环上一个顶点,统计其在pt_list中出现的次数count,当count=1时,令label=true;

步骤608:判断是否取完面ff外环上所有的顶点;如果取完,转至步骤609,如果没有取完,转至步骤607;

步骤609:判断label是否等于true,如果条件成立,转至步骤612,如果条件不成立,转至步骤610;

步骤610:判断是否取完body_list中的面,如果取完,则算法结束,如果没有取完,转至步骤611;

步骤611:令label=false,从body_list中顺序取出一个面,赋给面ff,转至步骤607;

步骤612:面ff为悬挂面,从body_list中删除面ff,同时令label=false,清空链表pt_list;悬挂面是指环上至少有一条边没有相邻面的面;

步骤613:将body_list中的面遍历一遍,将所有面的顶点保存到点链表pt_list中;

步骤614:重新遍历body_list,按顺序取其中的一个面赋给面ff,转至步骤607。

所示的步骤124中,合并同向共面且有重合线段的两个或多个面为一个面,包括以下步骤:

步骤701:定义存储满足同向共面条件的所有面的链表plane_list,定义存储面合并后的结果链表tmpplane_list,定义边链表line_list;

步骤702:取body_list中的一个面f,求取面f的单位法向量;

步骤703:按存储顺序取f面的下一个面记作f1,求取面f1的单位法向量;

步骤704:判断面f和面f1是否同向共面,如果同向共面,转至步骤705,否则转至步骤706;

步骤705:将面f1存入链表plane_list中,同时在body_list中删除该面f1;

步骤706:判断body_list中的面是否取完,如果取完,转至步骤708,如果没有取完,转至步骤707;

步骤707:从面f1向后取一个面,赋给面f1,求取面f1的单位法向量,转至步骤704;

步骤708:判断plane_list中存储的面的个数是否大于或等于1,如果条件成立,转至步骤709,如果条件不成立,转至步骤714;

步骤709:将面f存入链表plane_list中,并删除body_list中的该面f;

步骤710:将plane_list中所有面的边都存储到边链表line_list中,在链表line_list中删除所有的重合线段,同时清空链表plane_list;

步骤711:将line_list中的线段首尾相连构造面环;

步骤712:将line_list中构造的面环中共线且有重复点的短线段合并成长线段;

步骤713:将line_list中的构造面环存储到链表tmpplane_list中;

步骤714:在body_list中取面f之后的下一个面,赋给面f,求取面f的单位法向量;

步骤715:判断body_list中的面是否取完,如果取完,转至步骤716,如果没有取完,转至步骤717;

步骤716:将面链表tmpplane_list中的面添加到body_list中;

步骤717:取当前面f的下一个面赋给面f1,求取面f1的单位法向量,转至步骤704。

本发明有如下优点:

(1)所提出的三维实体布尔并运算算法思路清晰、简便,算法模块化程度高,易于实现;

(2)所提出的布尔并运算算法逻辑严密、算法鲁棒性高;

(3)所提出的布尔并运算算法效率高、运算量较小。

附图说明

图1是本发明的总流程图;

图2是给实体a和实体b的面进行标记的流程图;

图3是判断实体a的一个面是否在实体b的外面的流程图;

图4是判断实体a和实体b的面是同向共面且都不是内环面的流程图;

图5是两个面进行二维多边形并运算的流程图;

图6是对两个实体求并结果中存在的重复面和悬挂面进行删除的流程图;

图7是对两个实体求并结果中存在的共面且有重合线段的面进行合并的流程图;

图8(a)是实体a和实体b进行布尔并运算的示例图;

图8(b)是实体a的一个面截切实体b时求取剖面多边形的示例图;

图9(a)是实体a的内环面和实体b的非内环面异向共面情况下的求并示例图;

图9(b)是实体a的内环面去截切实体b求取的剖面示例图;

图9(c)是图9(b)实体a的内环面去截切实体b求得的剖面及该内环面图;

图9(d)是实体b的非内环面去截切实体a的剖面示例图;

图9(e)是图9(d)实体b的非内环面去截切实体a求得的剖面及该非内环面图;

图10(a)是实体a的内环面和实体b的非内环面同向共面情况下的求并示例图;

图10(b)是实体a的内环面去截切实体b求取的剖面示例图;

图10(c)是图10(b)实体a的内环面去截切实体b求取的剖面及该内环面图;

图10(d)实体b的非内环面去截切实体a求取的剖面示例图;

图10(e)是图10(d)实体b的非内环面去截切实体a求取的剖面及该非内环面图。

具体实施方式

本发明的三维平面实体采用brep表示形式,即用点、边、面、环以及它们之间相互的邻接关系定义三维平面实体,其中面的外环顶点顺序规定为逆时针方向、内环顶点顺序规定为顺时针方向。实体的面为平面多边形,它可以只有一个外环,也可以有一个外环和一个或多个内环。实体的面分为内环面和非内环面两种,内环面是指外环上的一条边是其他面的内环上的一条边的面。

本发明中的同向共面是指几何上处在一个平面上且外法线矢量方向相同的两个或多个面,异向共面是指几何上处在一个平面上且外法线矢量方向相反的两个或多个面;重复面是指满足下面三个条件的两个面:一是两个面的单位法向量相同,二是两个面在几何上处在一个平面上,三是两个面所有的顶点分别相同;悬挂面是指环上至少有一条边没有相邻面的面。

参照图1,本发明的两个三维平面实体的布尔并运算包括如下步骤:

步骤101:依次读入参与运算的两个实体a和b的面数据,其中实体a的面、环、边和点的信息分别保存在a_face_list、a_loop_list、a_line_list、a_point_list链表中,实体b的面、环、边和点的信息分别保存在b_face_list、b_loop_list、b_line_list、b_point_list链表中,参照图8(a),实体a有10个面,其中非内环面6个、内环面4个,6个非内环面分别为{1-2-6-5-1、9-10-11-12-9}、{3-4-8-7-3、13-16-15-14-13}、{2-3-7-6-2}、{1-5-8-4-1}、{1-4-3-2-1}、{5-6-7-8-5},4个内环面分别为{12-11-15-16-12}、{9-13-14-10-9}、{9-12-16-13-9}、{10-14-15-11-10},实体b有6个非内环面,分别为{1'-2'-6'-5'-1'}、{3'-4'-8'-7'-3'}、{2'-3'-7'-6'-2'}、{1'-5'-8'-4'-1'}、{1'-4'-3'-2'-1'}、{5'-6'-7'-8'-5'};

步骤102:设置实体a和实体b的交换标志swap及布尔差运算标志sub_flag,定义并运算结果存储链表body_list,并置swap=false,sub_flag=false;

步骤103:给实体a和实体b的面做标记,如果是内环面则标记为非0,如果是非内环面则标记为0;

步骤103中,给实体a和实体b的面做标记的方法,参照图2,包括以下步骤:

步骤201:从链表a_plane_list中读取实体a的面信息,定义标记面的变量count,count的初值为0,并将所有的面初始标记为count;

步骤202:令变量count=count+1;

步骤203:按实体a中面的存储顺序,读取一个面;

步骤204:判断该面是否存在内环,如果该面存在内环,转至步骤205,如果该面不存在内环,转至步骤213;

步骤205:按存储顺序取出一个内环,将内环的顶点数据压入链表pt_list中,参照图8(a),实体a的上底面内环为{9-10-11-12-9},将其压入链表pt_list中;

步骤206:按实体a中面的存储顺序,读取一个面;

步骤207:判断该面标记值是否不为0,如果条件成立,转至步骤210,如果条件不成立,转至步骤208;

步骤208:判断该面的外环顶点是否在链表pt_list中,如果不在,转至步骤210,否则转至步骤209;

步骤209:令该面标记值为count;

步骤210:判断实体a的面是否遍历完,如果遍历完,转至步骤211,如果未遍历完,转至步骤206;

步骤211:清空链表pt_list,对标记值count进行加1操作;

步骤212:判断该面的内环是否遍历完,如果遍历完,转至步骤213,如果没有遍历完,转至步骤205;

步骤213:判断实体a的面是否遍历完,如果遍历完,转至步骤214,如果未遍历完,转至步骤203;经过上述步骤,参照图8(a),实体a的四个内环面{12-11-15-16-12}、{9-13-14-10-9}、{9-12-16-13-9}、{10-14-15-11-10}被标记为1;判断的结果是若实体有n个内环,则相应的标记值count递增地标记到n,属于同一个内环的所有内环面的标记值是相同的;

步骤214:对实体b执行步骤201~步骤213,将步骤中的实体a的数据换成实体b的数据,对实体b的面进行标记。参照图8(a),实体b的面都是非内环面,其所有面的标记值都为0。

步骤104:遍历链表a_point_list、a_line_list、a_loop_list、a_face_list求取实体a的包围盒值a.min.x.、a.min.y、a.min.z、a.max.x、a.max.y、a.max.z;遍历链表b_point_list、b_line_list、b_loop_list、b_face_list求取实体b的包围盒值b.min.x.、b.min.y、b.min.z、b.max.x、b.max.y、b.max.z;参照图8(a),实体a的包围盒值a.min.x.、a.min.y、a.min.z分别为顶点4的x、y、z坐标值,a.max.x、a.max.y、a.max.z分别为顶点6的x、y、z坐标值;实体b的包围盒值b.min.x.、b.min.y、b.min.z分别为顶点4’的x、y、z坐标值,b.max.x、b.max.y、b.max.z分别为顶点6’的x、y、z坐标值;

步骤105:判断实体a的包围盒与实体b的包围盒是否相离,若不相离则转至步骤106,若相离则转至步骤117;

步骤106:遍历实体a的链表a_point_list、a_line_list、a_loop_list、a_face_list,取实体a的一个面fa;

步骤107:判断面fa是否在实体b的外面,如果面fa在实体b的外面则转至步骤118,否则转至步骤108;

步骤107中,判断面fa是否在实体b的外面的方法,参照图3,包括以下步骤:

步骤301:求取实体b的轴向包围盒b.max.x、b.max.y、b.max.z、b.min.x、b.min.y、b.min.z;求取面fa的轴向包围盒fa.max.x、fa.max.y、fa.max.z、fa.min.x、fa.min.y、fa.min.z;

步骤302:判断fa.max.x是否小于b.min.x,如果不成立,转至步骤303,如果成立,转至步骤309;

步骤303:判断fa.min.x是否大于b.max.x,如果不成立,转至步骤304,如果成立,转至步骤309;

步骤304:判断fa.max.y是否小于b.min.y,如果不成立,转至步骤305,如果成立,转至步骤309;

步骤305:判断fa.min.y是否大于b.max.y,如果不成立,转至步骤306,如果成立,转至步骤309;

步骤306:判断fa.max.z是否小于b.min.z,如果不成立,转至步骤307,如果成立,转至步骤309;

步骤307:判断fa.min.z是否大于b.max.z,如果不成立,转至步骤308,如果成立,转至步骤309;

步骤308:面fa不一定在实体b的外部;

步骤309:面fa在实体b的外部。参照图8(a)中,经判断,面{1-4-3-2-1},{1-5-8-4-1}在实体b的外面。

步骤108:遍历实体b的链表b_point_list、b_line_list、b_loop_list、b_face_list,取实体b的一个面fb;

步骤109:判断面fa和面fb是否同向共面且都不是内环面,如果条件成立,转至步骤115,如果条件不成立,转至步骤110;

步骤109中,判断面fa和面fb是否同向共面且都不是内环面的方法,参照图4,包括以下步骤:

步骤401:读取已做标记的面fa和面fb数据;

步骤402:判断面fa和面fb的标记值是否都为零,如果条件成立,则转至步骤403,否则转至步骤409;

步骤403:分别求取面fa和面fb的单位法向量和;

步骤404:判断和是否相等,如果相等,转至步骤405,如果不相等,则转至步骤409;

步骤405:从面fa和面fb中分别取其外环上的一个顶点,且保证这两个点不是同一个点,所取点分别记作点pota和点potb;

步骤406:用点pota和点potb作一条直线,求出其方向向量;

步骤407:判断面fa的单位法向量和方向向量是否垂直,即判断·是否等于0,如果垂直,转至步骤408,否则转至步骤409;

步骤408:面fa和面fb同向共面且都不是内环面;参照图8(a),经判断,实体a的顶面{1-2-6-5-1、9-10-11-12-9}和实体b的顶面{1'-2'-6'-5'-1'}属于同向共面且都不是内环面;

步骤409:面fa和面fb不满足同向共面且都不是内环面。

步骤110:用面fa的扩大面与面fb求交,交线段保存在链表a_inter_b中,面fa的扩大面是指与fa在一个平面上且边长足够大(取106)的正方形面;参照图8(b),用实体a的面{2-3-7-6-2}去截切实体b的交线段为{9-10}、{10-11'}、{11'-10'}和{10'-9};

步骤111:判断实体b的面是否处理完,如果没有处理完,转至步骤108,如果处理完,转至步骤112;

步骤112:将链表a_inter_b中的线段进行首尾相连构造环,将构造的环存入链表loop_list中;用loop_list中各环的法向量和面fa的法向量方向进行比较,若方向相同则环的顶点顺序不变,否则将环的顶点顺序反向排列;在loop_list中找出内环,将内环顶点顺序反向排列;最后得到的环链表loop_list即是用面fa的扩大面切实体b得到的剖面多边形f的数据;清空链表a_inter_b;参照图8(b),a_inter_b中的线段首尾相连构成的环是{9-10-11'-10'-9};loop_list中保存的剖面多边形f为{9-10-11'-10'-9};

步骤113:置布尔差运算标志sub_flag=true;

步骤114:将剖面多边形f赋给面fb;

步骤115:对面fa和面fb进行二维多边形的并运算,将运算结果保存在链表_out_中;链表_out_保存的是实体a和实体b三维并运算的部分结果;

步骤115中,对面fa和面fb进行二维多边形的并运算的方法,参照图5,包括以下步骤:

步骤501:读取面fa和面fb的数据;

步骤502:判断面fa和面fb的外环的位置关系是否相交,如果相交,转至步骤503,如果不相交,转至步骤517;

步骤503:定义标记面fa和面fb的内环上是否有交点的两个数组minner_label[]和cinner_label[],数组大小分别为面fa和面fb的内环个数,初始化数组minner_label[]和cinner_label[]的所有标记值为0;经相交关系判断,若内环上有交点,则令两个面相应的内环的标记值为1;参照图8(a),面{1-2-6-5-1、9-10-11-12-9}的内环{9-10-11-12-9}标记为0,参照图9(a),面{1-2-6-5-1、9-10-11-12-9}的内环{9-10-11-12-9}标记为1;

步骤504:分别定义保存面fa和面fb的顶点、交点信息以及交点出入属性的数组datap[]和dataq[],定义面fa的出点数组out_point[];先将面fa和面fb的顶点分别存入数组datap[]和dataq[]中,并令其属性值为0,然后求出两个面环的交点,并判断交点的出入属性,若交点为入点,则其属性值为1,若交点为出点,则其属性值为-1,将交点及其属性值按照交点在环上的位置分别插入到数组datap[]和dataq[]中;同时将面fa的出点存入到数组out_point[]中;交点为“入点”是指在该点处面fa的边进入了面fb,交点为“出点”是指在该点处面fa的边离开了面fb;参照图8(a),实体a的顶面fa{1-2-6-5-1、9-10-11-12-9}和实体b的顶面fb{1'-2'-6'-5'-1'}进行二维布尔并运算时,面环交点为9、11,针对面fa,交点9为入点,其属性值为1,交点11为出点,其属性值为-1,插入出入点之后的面fa的数组datap[]为{1-2-9-6-11-5、9-10-11-12},面fb的数组dataq[]为{1'-9-2'-6'-5'-11},面fa的出点数组out_point[]为{11};

步骤505:判断布尔差运算标志sub_flag是否为true,若为true,转至步骤516,若不为true,则转至步骤506;

步骤506:判断面fa和面fb是否有内环,如果有内环,转至步骤515,如果没有内环,转至步骤507;

步骤507:从出点数组out_point[]中取出一个出点,并赋值给点变量pottmp;

步骤508:在面fa的数组data_p[]中按顺序查找到对应的出点;

步骤509:将该点保存在临时结果环链表looptmp.point_list中,在datap[]中从该点向后继续遍历,遇到顶点则保存在链表looptmp.point_list中,遇到入点则进入面fb的数组dataq[]中找到对应的点,并保存在链表looptmp.point_list中,接着在dataq[]中从该点向后继续遍历,遇到顶点保存在链表looptmp.point_list中,遇到针对面fb的入点则进入面fa的数组datap[]中找到对应的点;

步骤510:判断该点是否和点pottmp为同一点,如果是同一点,转至步骤511,如果不是同一点,转至步骤509;

步骤511:将链表looptmp.point_list中的点保存在环链表tmpface_list中,并清空链表looptmp.point_list;

步骤512:判断面fa的出点数组out_point[]是否遍历完,如果遍历完,转至步骤513,如果没有遍历完,转至步骤507;参照图8(a),面fa{1-2-6-5-1、9-10-11-12-9}和面fb{1'-2'-6'-5'-1'}经过步骤507到步骤512的结果{11-5-1-2-9-2'-6'-5'-11}保存在环链表tmpface_list中;

步骤513:求取环链表tmpface_list中各环的法向量,判断其和面fa的外法向量的方向是否相同,方向相同者则是外环,方向不同者则是内环;参照图8(a),面fa{1-2-6-5-1、9-10-11-12-9}和面fb{1'-2'-6'-5'-1'}进行并运算时,经过步骤512和步骤515之后,环链表tmpface_list中存储的环为{9-10-11-12-9}、{11-5-1-2-9-2'-6'-5'-11},经过本步骤环的法向量判断,外环为{11-5-1-2-9-2'-6'-5'-11},内环为{9-10-11-12-9};

步骤514:按照先外环后内环的存储顺序构造面链表,将结果保存到并运算结果链表_out_中;参照图8(a),面fa{1-2-6-5-1、9-10-11-12-9}和面fb{1'-2'-6'-5'-1'}进行并运算的结果{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}保存在并运算结果链表_out_中;

步骤515:根据数组minner_label[]和cinner_label[]中的标记值判断面fa对应的无交点内环和面fb对应的无交点内环的去留问题,分为以下两种情况:第一种情况,如果面fa的内环在面fb的外环的外面,则该内环保留,如果面fa的内环在面fb的外环里面且在面fb的内环外面,则该内环不保留,如果面fa的内环在面fb的内环里面,则该内环保留;第二种情况,如果面fb的内环在面fa的外环的外面,则该内环保留,如果面fb内环在面fa的外环的里面且在面fa的内环外面,则该内环不保留,如果面fb的内环在面fa的内环里面,则该内环保留;将保留的环保存在环链表tmpface_list中;参照图8(a)中,实体a的面fa{1-2-6-5-1、9-10-11-12-9}中的内环{9-10-11-12-9}在实体b的面fb{1'-2'-6'-5'-1'}的外环的外面,则保存环{9-10-11-12-9}在环链表tmpface_list中;

步骤516:将面fb的dataq[]中的顶点和交点反向排列,置sub_flag=false,转到步骤506;参照图8(b),实体a的面fa{2-3-7-6-2}截切实体b,经过步骤110、步骤112得到的剖面多边形f为{9-10-11'-10'-9},再经过步骤113、步骤114,面fb为{9-10-11'-10'-9},进入步骤115后,面fa{2-3-7-6-2}和面fb{9-10-11'-10'-9}进行二维布尔并运算时,面环交点为9、10(点6、7不计入交点),针对面fa,交点10为入点,其属性值为1,交点9为出点,其属性值为-1,插入出入点之后的面fa的数组datap[]为{2-3-10-7-6-9},面fb的数组dataq[]为{9-9(交点)-10(交点)-10-11'-10'},面fa的出点数组out_point[]为{9},执行步骤516后,面fb的数组dataq[]为{10'-11'-10-10(交点)-9(交点)-9};经过步骤506到步骤511后,环链表tmpface_list中存储的环为{9-2-3-10-9};经过步骤512、步骤513和步骤514之后,本次并运算结果{9-2-3-10-9}保存在链表_out_中;

步骤517:判断面fa和面fb的外环位置关系是否相离,如果相离,转至步骤518,如果不相离,转至步骤519;

步骤518:将面fa的内、外环和面fb的内、外环都保存在并运算结果链表_out_中;

步骤519:若面fa的外环在面fb外环的内部,则保存面fb的外环到并运算结果链表_out_中,若面fa的外环在面fb外环的外部,则保存面fa的外环到并运算结果链表_out_中,转至步骤503。

步骤116:判断实体a的面是否处理完,如果处理完,转至步骤119,如果没有处理完,转至步骤106;

步骤117:令链表a_out_b=a_face_list,链表b_out_a=b_face_list,合并两个链表a_out_b、b_out_a到链表body_list中,输出并运算结果链表body_list;

步骤118:保存实体a的面fa到链表_out_中,转至步骤116;

步骤119:判断交换标志swap是否为true,如果是,转至步骤122,如果不是,则转至步骤120;

步骤120:将链表_out_中的数据拷贝到链表a_out_b中,并清空链表_out_;参照图8(a)和表1,表1是图8(a)所示的实体a和实体b进行布尔并运算时生成的两个链表a_out_b和b_out_a的结果。链表a_out_b中存储的面为{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}、{10-3-4-8-12-8'-7'-3'-10、13-16-15-14-13}、{9-2-3-10-9}、{1-5-8-4-1}、{1-4-3-2-1}、{12-8-5-11-12}、{12-11-15-16-12}、{9-13-14-10-9}、{9-12-16-13-9}、{10-14-15-11-10};

表1如下:

步骤121:交换实体a和实体b的数据,即将实体b的面、环、边和点的信息拷贝给实体a,将实体a的面、环、边和点的信息拷贝给实体b,并置swap=true,转至步骤103;

步骤122:将链表_out_中的数据拷贝到链表b_out_a中,并清空链表_out_;参照图8(a)和表1,链表b_out_a中存储的面为{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}、{10-3-4-8-12-8'-7'-3'-10、13-16-15-14-13}、{2'-3'-7'-6'-2'}、{11-5'-8'-12-11}、{10-3'-2'-9-10}、{5'-6'-7'-8'-5'};

步骤123:合并链表a_out_b和链表b_out_a的数据到body_list中,进行后处理,删除重复面和悬挂面;参照图8(a)和表1,合并链表a_out_b和链表b_out_a得到的body_list存储的面为{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}、{10-3-4-8-12-8'-7'-3'-10、13-16-15-14-13}、{9-2-3-10-9}、{1-5-8-4-1}、{1-4-3-2-1}、{12-8-5-11-12}、{12-11-15-16-12}、{9-13-14-10-9}、{9-12-16-13-9}、{10-14-15-11-10}、{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}、{10-3-4-8-12-8'-7'-3'-10、13-16-15-14-13}、{2'-3'-7'-6'-2'}、{11-5'-8'-12-11}、{10-3'-2'-9-10}、{5'-6'-7'-8'-5'};

步骤123中,进行后处理,删除重复面和悬挂面的方法,参照图6,包括以下步骤:

步骤601:从链表body_list中取出一个面f;

步骤602:遍历链表body_list中除面f之外的其余的面,若有与面f的重复面f1,则删除面f1;参照图8(a)和表1,body_list存储的面{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}、{10-3-4-8-12-8'-7'-3'-10、13-16-15-14-13}各重复了一次,进行删除,删除重复面之后的body_list存储的面为{11-5-1-2-9-2'-6'-5'-11、9-10-11-12-9}、{10-3-4-8-12-8'-7'-3'-10、13-16-15-14-13}、{9-2-3-10-9}、{1-5-8-4-1}、{1-4-3-2-1}、{12-8-5-11-12}、{12-11-15-16-12}、{9-13-14-10-9}、{9-12-16-13-9}、{10-14-15-11-10}、{2'-3'-7'-6'-2'}、{11-5'-8'-12-11}、{10-3'-2'-9-10}、{5'-6'-7'-8'-5'};

步骤603:判断body_list中的面是否遍历完,如果遍历完,转至步骤604,如果没有遍历完,转至步骤601;

步骤604:将body_list中的面遍历一遍,将所有面的顶点保存到点链表pt_list中;

步骤605:按顺序取body_list中的一个面ff,设置布尔标志label,并置label=false;

步骤606:定义变量count为面ff外环的每个顶点在链表pt_list中出现的次数;

步骤607:取面ff外环上一个顶点,统计其在pt_list中出现的次数count,当count=1时,令label=true;参照图9(a)、图9(b),实体a的内环面{9-9'-10'-10-9}和实体b的面{1'-5'-8'-4'-1'}是异向共面,用内环面fa{9-9'-10'-10-9}去截切实体b,得到的剖面f是{1'-4'-8'-5'-1'},把剖面f赋给面fb,用面fa{9-9'-10'-10-9}和面fb{1'-4'-8'-5'-1'}做二维布尔差运算,参照图9(c),运算得到的面为{1'-9-9'-4'-1'};交换实体a和实体b之后,用实体b(即为交换后的实体a)的面fa{1'-5'-8'-4'-1'}去截切实体a(即为交换后的实体b)得到的剖面f,参照图9(d)和图9(e),剖面f为{10-13-14-10'-10}、{17-9-9'-18-17},把剖面f赋给面fb,用面fa{1'-5'-8'-4'-1'}和面fb{10-13-14-10'-10}、{17-9-9'-18-17}做二维布尔差运算,运算得到的面为{1'-10-10'-4'-1'}、{13-5'-8'-14-13};参照图9(c)和图9(e),两次差运算结果中,面{1'-10-10'-4'-1'}为悬挂面,这是因为实体a的面{9-9'-10'-10-9}和实体b的面{1'-5'-8'-4'-1'}是异向共面,所以会产生悬挂面,该悬挂面顶点1'、10、10'、4'的count值分别是3、1、1、3,悬挂面中的各顶点count值中必有count=1;对于首尾相连的连续悬挂面,需要首先判断并删除body_list中有count值为1的悬挂面,然后清空链表pt_list,重新将body_list中剩余的面的所有顶点压入链表pt_list中,再重新统计各面顶点的count值,再判断并删除body_list中有count值为1的悬挂面,直至body_list中没有悬挂面为止;

步骤608:判断是否取完面ff外环上所有的顶点;如果取完,转至步骤609,如果没有取完,转至步骤607;

步骤609:判断label是否等于true,如果条件成立,转至步骤612,如果条件不成立,转至步骤610;

步骤610:判断是否取完body_list中的面,如果取完,则算法结束,如果没有取完,转至步骤611;

步骤611:令label=false,从body_list中顺序取出一个面,赋给面ff,转至步骤607;

步骤612:面ff为悬挂面,从body_list中删除面ff,同时令label=false,清空链表pt_list;

步骤613:将body_list中的面遍历一遍,将所有面的顶点保存到点链表pt_list中;

步骤614:重新遍历body_list,按顺序取其中的一个面赋给面ff,转至步骤607。

步骤124:合并同向共面且有重合线段的两个或多个面为一个面;

步骤124中,合并同向共面且有重合线段的两个或多个面为一个面的方法,包括以下步骤:

如图7所示,步骤701:定义存储满足同向共面条件的所有面的链表plane_list,定义存储面合并后的结果链表tmpplane_list,定义边链表line_list;参照图10(a)和图10(b),实体a的内环面{9-9'-10'-10-9}和实体b的面{2'-3'-7'-6'-2'}属于同向共面,求并结果会产生重合线段的面,需要合并成大面;用实体a的面fa{9-9'-10'-10-9}去截切实体b得到剖面f{2'-3'-7'-6'-2'},将剖面f{2'-3'-7'-6'-2'}赋给面fb,用面fa{9-9'-10'-10-9}和面fb{2'-3'-7'-6'-2'}进行二维布尔差运算,参照图10(c),运算得到面{9-9'-3'-2'-9};交换实体a和实体b之后,用实体b(即为交换后的实体a)的面fa{2'-3'-7'-6'-2'}去截切实体a(即为交换后的实体b)得到剖面f,参照图10(d)和图10(e),剖面f为{15-16-9'-9-15}、{10-10'-14-13-10},把剖面f赋给面fb,用面fa{2'-3'-7'-6'-2'}和面fb{15-16-9'-9-15}、{10-10'-14-13-10}做二维布尔差运算,运算得到的面为{2'-3'-10'-10-2'}、{13-14-7'-6'-13};参照图10(c)和图10(e),两次差运算结果的三个面{9-9'-3'-2'-9}、{2'-3'-10'-10-2'}、{13-14-7'-6'-13}存储在body_list中,其中面{9-9'-3'-2'-9}和面{2'-3'-10'-10-2'}有重合线段{2'-3'};

步骤702:取body_list中的一个面f,求取面f的单位法向量;

步骤703:按存储顺序取f面的下一个面记作f1,求取面f1的单位法向量;

步骤704:判断面f和面f1是否同向共面,如果同向共面,转至步骤705,否则转至步骤706;

步骤705:将面f1存入链表plane_list中,同时在body_list中删除该面f1;参照图10(c)和图10(e),body_list中的面{9-9'-3'-2'-9}、{2'-3'-10'-10-2'}和{13-14-7'-6'-13}属于同向共面的面,需要存入链表plane_list中;

步骤706:判断body_list中的面是否取完,如果取完,转至步骤708,如果没有取完,转至步骤707;

步骤707:从面f1向后取一个面,赋给面f1,求取面f1的单位法向量,转至步骤704;

步骤708:判断plane_list中存储的面的个数是否大于或等于1,如果条件成立,转至步骤709,如果条件不成立,转至步骤714;

步骤709:将面f存入链表plane_list中,并删除body_list中的该面f;

步骤710:将plane_list中所有面的边都存储到边链表line_list中,在链表line_list中删除所有的重合线段,同时清空链表plane_list;

步骤711:将line_list中的线段首尾相连构造面环;

步骤712:将line_list中构造的面环中共线且有重复点的短线段合并成长线段;

步骤713:将line_list中的构造面环存储到链表tmpplane_list中;参照图10(c)和(e),经过步骤710到步骤712,删除重合线段{2'-3'},合并后得到的面{9-9'-10'-10-9}、{13-14-7'-6'-13}存储到链表tmpplane_list中;

步骤714:在body_list中取面f之后的下一个面,赋给面f,求取面f的单位法向量;

步骤715:判断body_list中的面是否取完,如果取完,转至步骤716,如果没有取完,转至步骤717;

步骤716:将面链表tmpplane_list中的面添加到body_list中;

步骤717:取当前面f的下一个面赋给面f1,求取面f1的单位法向量,转至步骤704。

步骤125:输出并运算结果链表body_list。

本实施例没有详细叙述的部分和英文缩写属本行业的公知常识,在网上可以搜索到,这里不一一叙述。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1