CGAL的多边形网格处理

1、介绍

        该包实现了一组用于多边形网格处理的方法和类,从简单化的基本操作到复杂的几何处理算法。该软件包的实现主要遵循Botsch等人关于多边形网格处理的书中给出的算法和参考文献。

1.1、多边形网格

        多边形网格是一个一致且可定向的曲面网格,可以有多个边界。面是简单的多边形。边是线段。每条边连接两个顶点,并由两个面(包括边界边的零面)共享。多边形网格可以有任何数量的连接组件,也可以有一些自交点。在这个包中,多边形网格被认为具有2-流形的拓扑结构。

1.2、API

        该软件包遵循CGAL和Boost图库中描述的BGL API。因此,它可以与Polyhedron_3、 Surface_mesh或FaceGraph概念的任何类模型一起使用。该包的每个函数或类都详细说明了对输入多边形网格的要求。

1.3、概述

        本手册中描述的算法按章节组织:

        网格化:网格化算法,包括非三角网格的三角剖分、细化、通过光顺进行优化、对三角网格表面的重新网格化和平滑算法。

        核心细化与布尔运算:对三角形网格进行核心细化的方法和从核心细化的封闭三角形网格中计算布尔运算的方法。

        孔填充:可用的孔填充算法,可能与细化和光顺相结合。

        谓词:对已处理的多边形网格进行谓词评估,包括点定位和自交测试。

        方向:检查或修复多边形汤的方向。

        组合修复:修复多边形网格和多边形汤。

        几何修复:修复多边形网格的几何形状。

        计算法向量:在多边形网格的顶点和面上计算法向量。

        计算曲率:在多边形网格上计算曲率(平均值、高斯、主)。

        切片器:能够计算多边形网格与任意平面交点的函数(切片器)。

        连接组件:处理多边形网格连接组件的方法(提取、标记、移除等)。

1.4、多边形网格的读写

        在该包的所有功能中,多边形网格都需要是包CGAL和Boost graph Library Reference中定义的图形概念的模型。使用公共图概念使得能够为这些概念的所有模型具有公共输入/输出函数。I/O功能页提供了可用I/O功能的详尽描述。

        此外,该包还提供了函数CGAL::Polygon_mesh_production::IO::read_Polygon_mesh(),如果输入数据不表示流形曲面,则可以执行一些修复。

2、网格

        通过插入新顶点和翻转边可以得到一个三角剖分来细化曲面片。使用XX准则,通过细化函数近似得到靠近曲面片边界的三角形密度。通过翻转边强制网格的有效性。只有在对面的边在原始网格中不存在,并且不产生退化三角形时,才会翻转边。

        可以对表面网格的一个区域(例如细化区域)进行光顺处理,以获得切线连续和平滑的曲面片。要光顺的区域被定义为重新定位的顶点的范围。光顺步骤最小化一个带有边界约束的线性双拉普拉斯系统。

2.1、API

2.1.1、网格生成

        改进和光顺函数可应用于三角形网格上的任意区域,使用:

        CGAL::Polygon_mesh_processing::refine():给定网格上一组面,改进该区域。

        GAL::Polygon_mesh_processing::fair():给定网格上一组顶点,光顺该区域。

        光顺需要一个稀疏线性求解器,我们建议使用Eigen 3.2或更高版本。请注意,如果用作边界条件的光滑固定顶点不足以求解所构建的线性系统,则光顺可能会失败。

        许多算法要求输入网格中所有面的度相同,甚至是三角形。因此,可能需要将网格的所有多边形面进行三角剖分。

        此软件包提供了函数CGAL::Polygon_mesh_processing::triangulate_faces(),可以对输入多边形网格的所有面进行三角剖分。为每个面选择一个近似支撑平面,与CGAL::Polygon_mesh_processing::compute_face_normal()计算出的法向量正交。然后,每个面的三角剖分是在该平面上构建CGAL::Constrained_Delaunay_triangulation_2所获得的。之所以做出这样的选择,是因为约束Delaunay三角剖分是在给定要三角剖分的面的边的情况下,最大化三角剖分中所有三角形最小角的最大值。

2.1.2、网格重新生成

 各向同性增量网格重划分

        Botsch等人提出的增量式基于三角形的各向同性网格重分算法在此软件包中实现。该算法增量式执行简单的操作,如边缘分裂、边缘折叠、边缘翻转和拉普拉斯平滑。重分网格的所有顶点都重新投影到原始曲面,以保持对输入的良好近似。

        可以使用函数CGAL::Polygon_mesh_processing::isotropic_remeshing()对多边形网格的三角形区域进行网格重排,如下图所示。该算法只有两个参数:重排曲面片的目标边长,以及上述操作序列的迭代次数。该数字越大,网格越平滑,越接近目标边长。

        添加了一个额外的选项来保护(即不修改)一些给定的折线。在某些情况下,这些折线太长,在保护它们的同时达到所需的目标边长是不可能的,并导致事件面中的边分裂无限循环。为了避免这个陷阱,在重新网格化之前,应在受约束的边列表上调用函数 CGAL::Polygon_mesh_processing::split_long_edges()。

        各向同性再网格。(a) 三角形输入曲面网格。(b) 表面均匀且完全重熔。(c) 选择要重新曲面化的面范围。(d) 选择的曲面网格均匀地重新划分。 

曲面重新网格化

        在3D网格生成包中实现的网格生成算法可用于对给定的三角表面网格进行重新网格化。该算法基于限制性Delaunay三角剖分的Delaunay细化,生成三角形表面网格,该网格在单形大小、表面近似、面形状和表面拓扑方面具有所需的特性。可以给定一组来自输入网格的边作为约束,以构建和保护一组折线特征,这些特征在保持输入特征图的拓扑的同时进行重新采样。

        此软件包中提供了三角形表面网格重分的解决方案,该解决方案具有 CGAL::Polygon_mesh_processing::surface_Delaunay_remeshing() 函数。为 CGAL::make_mesh_3() 定义的所有网格标准可以直接用于单形的大小、面的形状、表面近似、拓扑和一维特征采样。

        Polygon_mesh_processing/delaunay_remeshing_example.cpp中给出了一个例子,说明如何使用Delaunay细化算法对给定的三角表面网格进行重新网格化,同时保留检测到的锐边。

(几乎)平面补片的重划

        当使用许多三角形来描述模型的平面区域时,人们可能希望简化该区域中的网格,使用少量元素,甚至当该区域构成一个简单连接的补丁时使用单个大型多边形面。这可以通过使用函数CGAL::Polygon_mesh_processing::remesh_planar_patches()来实现。该函数用于检测平面区域,使用几何断言进行共面性和共线性检查。

        如果这些测试准确执行,由于输入实际上不是完全平面的,平面区域可能会意外地小。为了缓解这种情况,可以指定相邻面(或线段)之间角度的容差,以便它们被视为共面(或共线性)。

        然而,此容差阈值仅是局部的,没有全局控制,这可能会导致不希望的效果,例如在密集采样的圆弧上的经典示例,其中所有点最终都被发现几乎共线性。为了避免这种情况,我们提供了函数CGAL::Polygon_mesh_processing::remesh_almost_planar_patches(),它期望用户提供平面补丁和拐角的分割。

        这种分割可以通过使用函数GAL::Polygon_mesh_processing::region_growing_of_planes_on_faces()获得,该函数使用区域增长算法在具有全局和局部准则的网格中检测平面区域。同样,函数cgal::Polygon_mesh_processing::detect_corners_of_regions()可用于检测由运行在补丁边界段上的区域增长算法检测到的平面区域的边界拐角点。

        在两个模型中对平面面片进行重新划分:(a)奶酪模型中的平面面片进行了重新划分(b)该模型的重新划分版本包含14个顶点,但尚未进行重新划分,面片ID已分配给输入和输出网格,从而允许相同的配色方案。 

        使用区域生长来检测平面补片的平面补片重划。从左到右:输入网格、重新划分版本、使用相同角度阈值但近似误差较大的重新划分版本。 

2.1.3、平滑

        三角网格区域的平滑可以通过旨在实现网格平滑或形状平滑的算法来实现。网格平滑是通过基于角度和面积等标准提高三角形的质量来实现的,而形状平滑则被设计为内在的,尽可能少地依赖于离散化,仅对形状进行平滑,而不优化三角形的形状。

        通过角度和面积优化进行网格平滑:CGAL::Polygon_mesh_processing::angle_and_area_smoothing() 会移动顶点以优化每个顶点周围的几何形状:它可以尝试平衡入射边之间的角度,或者(和)移动顶点,使相邻三角形的面积趋于平衡。边界顶点被视为受约束的,在程序的任何步骤都不会移动。任何时候都不会插入顶点。角度和面积平滑算法基于Surazhsky和Gotsman。由于面积平滑仅将面积作为平滑标准,因此可能会导致长而细的三角形。为了缓解这种现象,在面积平滑之后,会进行一个基于Delaunay的边翻转的(可选)步骤。在任何情况下,面积平滑都能保证改善被平滑区域上顶点的空间分布。一个简单的例子可以在Polygon_mesh_processing/mesh_smoothing_example.cpp中找到。

        切线松弛网格平滑:CGAL::Polygon_mesh_processing::tangential_relaxation() 根据基于面积的拉普拉斯平滑方案移动顶点,在估计的切线平面的每个顶点处执行。示例Polygon_mesh_processing/tangential_relaxation_example.cpp显示了如何使用此网格松弛函数。
        形状平滑: CGAL::Polygon_mesh_processing::smooth_shape() 会沿着平均曲率流将顶点向其邻居的加权重心移动。形状平滑的曲率流算法基于 Desbrun 等人和 Kazhdan 等人。该算法使用平均曲率流来计算沿着表面法线的顶点平移,速度等于被平滑区域的平均曲率。这意味着尖角上的顶点滑动速度更快。如果顶点周围的区域是平坦的,则该顶点不会移动(曲率为零)。为了避免形成不希望的颈部收缩(形成奇点的圆柱形表面区域),该算法会减缓圆柱形区域的演化。平滑后的形状收敛到球体,同时保持与其原始形状的保形等效。一个简单的例子可以在Polygon_mesh_processing/shape_smoothing_example.cpp中找到。

         闭合曲面滴状的网格平滑,包含自相交(用红色圈出)。对于每个平滑组合,应用10次迭代。从左到右:(a)输入网格;(b) 基于区域进行平滑,而不使用Delaunay翻转;(c) 基于Delaunay翻转区域的平滑;(d) 基于角度的平滑;(e) 基于角度和面积的平滑,使用Delaunay翻转。 

 网格平滑的各种组合的统计信息。

        使用时间步长等于0.05的平均曲率流和约束边界顶点(位于颈部,网格打开的位置),对魔鬼模型进行形状平滑。 

2.1.4、挤压

        此程序包提供了两个功能,用于挤出具有边界的三角形网格。第一种是通过将每个顶点偏移用户提供的向量来挤出。第二个更一般:它使用两个用户提供的函数,分别挤出“向上”和“向下”。在这两种情况下,边界都通过三角形条带连接。请注意,拉伸可能会生成自相交曲面。

3、核心定义与布尔运算

3.1、定义

        核心细化给定两个三角曲面网格,核心细化操作包括细化两个网格,使它们的相交多段线是两个细化网格中的边的子集。

      

        两个三角曲面网格的合并。(左)输入网格;(右)两个输入网格取芯。两个网格的公共边以绿色绘制。 

        由三角表面网格界定的体积 给定一个封闭的三角表面网格,每个连通分量将3D空间分为两个子空间。从这两个子空间来看,每个分量的面的顶点序列是顺时针或逆时针的。看到序列顺时针(逆时针)的子空间在分量的负(正)侧。给定一个没有自交的封闭三角表面网格tm,tm的连通分量将3D空间分为子空间。如果每个子空间都只位于tm的所有入射连通分量的正(或负)侧,则称tm界定了体积。tm界定的体积是tm的入射连通分量负侧的所有子空间的并集。

        由三角曲面网格界定的体积:图中显示了表示三个嵌套球体(三个连接的组件)的网格。图片的左侧显示了一个剪裁的三角曲面网格,其中有两个可能的面方向,其中体积由网格界定。每个连接组件的正极和负极分别显示为浅蓝色和深蓝色。图片的右侧部分显示了相应有界体积的剪裁四面体网格。

3.2、精细化

        可以使用函数CGAL::Polygon_mesh_processing::corefine()对两个三角表面网格进行核心细化。它以两个三角表面网格作为输入进行核心细化。如果提供了约束边图,则属于输入网格交点的边将被标记为约束。此外,如果标记为约束的边在核心细化过程中被分割,则子边也将被标记为约束。

3.3、布尔运算

        假设C和S分别是立方体和球体的三角表面网格所包围的体积。从左到右,图片显示了包围C和S的并集、C减去S、C和S的交集以及S减去C的三角表面网格。 

        两个三角表面网格的核细化可以自然地用于计算体积上的布尔操作。考虑两个三角表面网格,每个网格都包围一个体积,函数CGAL::Polygon_mesh_processing::corefine_and_compute_union()、CGAL::Polygon_mesh_processing::corefine_and_compute_intersection()和CGAL::Polygon_mesh_processing::corefine_and_compute_difference()分别计算两个体积的并集、交集和差集。如果必须同时计算多个布尔操作,则应使用函数corefine_and_compute_boolean_operations()。

        对输入体的拓扑没有限制。但是,对输入有一些要求,以确保操作是可能的。首先,输入网格不能自相交。其次,只有当输出可以由流形三角曲面网格约束时,操作才可能。特别地,这意味着输出体没有厚度为零的部分。从数学上讲,与以输出体为中心的无限小球的交集是一个拓扑球。在表面层,这意味着输出中不允许有非流形顶点或边缘。例如,不可能计算两个不相交但共享一条边的立方体的并集。如果你必须处理这种情况,你应该考虑使用Nef多面体上的3D布尔操作包。

        可以更新输入,使其包含结果(原地操作)。在这种情况下,不会复制整个网格,只会修改相交多段线周围的区域。如果布尔运算不可行,则仍将对输入网格进行精化。

3.4、输出的核与有效性

        如果输入网格的点属性映射中使用的点类型来自具有精确谓词的CGAL内核,则核心细化操作(在三个布尔操作中也内部使用)将正确地改变输入表面网格的拓扑。如果该内核没有精确的结构,则输出表面网格的嵌入可能具有自交点。在连续操作的情况下,建议使用具有来自具有精确谓词和精确结构的内核的点的点属性映射(如CGAL::Exact_predicates_exact_constructions_kernel)。

        在实践中,这意味着对于精确谓词和不精确构造,边缘将在每个与三角形的交点处被分割,但由于浮点数的有限精度,交点的位置可能会产生自交点。

3.5、剪裁

        作为自然扩展,提供了一些由封闭网格和半空间(由平面的负侧定义,与向外法线约定一致)界定的体积裁剪功能。函数CGAL::Polygon_mesh_processing::clip()和CGAL::Polygon_mesh_processing::split()有一些选项,可以选择是在体积还是表面级别进行裁剪,以及裁剪器是否应被视为紧凑。

        用半空间剪裁立方体。从左到右:(i)初始立方体和定义剪裁半空间的平面;(ii)clip_volume=false:剪裁表面网格(红色描绘的边界边缘);(iii)clip_volume=true:剪裁由表面网格界定的体积。 

        使用半空间剪切立方体:剪切器的压缩能力(两种情况下 clip_volume=false)。从左到右:(i)初始立方体和定义剪切半空间的平面,注意立方体的整个面(2个三角形)完全包含在平面中;(ii)use_compact_clipper=true:使用压缩半空间剪切曲面网格:共面面是输出的一部分;(iii)use_compact_clipper=false:使用非压缩半空间剪切曲面网格:共面面不是输出的一部分。  

4、孔修复

        此程序包提供了一种算法,用于填充三角表面网格中或由描述折线的点序列定义的封闭孔。可以概括如下。

        首先,在不引入任何新顶点的情况下生成了三角剖分孔边界的最大面片。选择面片是为了最小化对所有可能的三角形面片评估的质量函数。质量函数首先最小化面片三角形之间的最差二面角,然后最小化面片的总表面积作为决胜因素。通过将搜索空间缩小到孔边界顶点的3D Delaunay三角剖分的面,同时根据上述质量标准搜索最佳面片,算法的性能得到了显着提高。

        对于一些复杂的输入孔边界,生成的贴片可能具有自交点。在孔填充后,可以使用网格划分功能CGAL::Polygon_mesh_processing::refine()和CGAL::Polygon_mesh_processing::fair()对生成的贴片进行细化和公平化。

        算法的主要步骤的结果。从左到右:(a)孔,(b)三角测量后的孔,(c)三角测量和精化后的孔(d)三角测量、精化和光顺后的孔。 

4.1、API

        此包提供了四个用于孔填充的函数:triangulate_hole_polyline():给定一个定义孔的点序列,对孔进行三角剖分。triangulate_hole():给定网格上孔边界上的边界半边,对孔进行三角剖分。
triangulate_and_refine_hole():除了triangulate_hole()外,生成的补丁也会被细化。triangulate_refine_and_fair_hole():除了triangulate_and_refine_hole(),生成的补丁也是公平的。

4.2、性能 

        孔填充算法的复杂度取决于顶点的数量。虽然特殊情况的运行时间为O(n3),但在大多数情况下的运行时间为O(nlogn)。

        我们为以下两个网格(以及另外两个具有较小孔的网格)测试了函数triangulate_refine_and_fair_hole()。

        左边/右边的大象有一个有963/7657个顶点的洞。 

# vertices without Delaunay (sec.) with Delaunay (sec.)
565 8.5 0.03
774 21 0.035
967 43 0.06
7657 na 0.4

5、谓词

5.1、交叉检测

        可以使用CGAL::Polygon_mesh_processing::do_intersect() 执行三角形网格和/或多段线之间的相交测试。此外,函数CGAL::Polygon_mesh_processing::intersecting_meshes() 会记录一个范围内的所有相交网格对。

        可以通过调用函数CGAL::Polygon_mesh_production::doe_Self_interact()来检测三角形网格内的自相交。此外,函数CGAL::Polygon_mesh_producing::self_interctions()报告所有相交三角形对。

5.2、三角形网格的边

        类 CGAL::Side_of_triangle_mesh提供了一个函子,用于测试查询点是否在给定的闭合三角形网格所包围的域内、域外或域边界上。

        如果从点走到无穷远时穿过奇数个曲面,则该点被认为位于由输入三角形网格界定的域的有界侧。输入三角形网格应不含自交点,且无自包含。

        该算法可以处理具有多个连接组件的三角形网格的情况,并返回正确的结果。在自包含的情况下,执行射线交叉奇偶性测试,并且执行不会失败。但是,用户应该意识到谓词交替考虑子体积在输入三角形网格的有界和无界侧。

5.3、多面体外壳安全壳检查

        类CGAL::Polyhedral_envelope提供了函子来检查查询点、线段或三角形是否完全包含在三角形网格或多边形汤的多面体包络中。在下文中,输入三角形将指网格或汤中的三角形。

        多面体包络是对一组具有半径为 ϵ 的球体的三角形的闵可夫斯基和包络的保守近似。后者在输入三角形的凸边和顶点处具有圆柱形和球形斑块。

        给定距离δ=ε/(√3),我们可以通过将平行于三角形的两个半空间、垂直于三角形且平行于边的三个半空间以及用于剪裁钝角的半空间相交,将每个三角形与一个棱柱相关联,其中面法线对应于角的平分线。这些半空间距离δ,并且它们包含三角形。

        一组三角形的多面体包络,公差为 ϵ,则其棱柱为所有面的棱柱的并集,δ=ε/(√3)。

        单个三角形的棱柱、多面体包络以及三角形网格的Minkowski和包络。 

        保证多面体包络在Minkowski和包络内。这个包含性测试对于多面体包络是精确的,对于Minkowski和包络是保守的:如果查询在多面体包络内,我们可以确定它也在Minkowsky和包络内,但如果它在多面体包络外,我们不知道它相对于Minkows基和包络在哪里。

        王等人的多面体包络包容度检查算法可总结如下。输入三角形的面的棱镜存储在AABB树中,用于快速识别边界框与查询重叠的棱镜。

        对于查询点,算法会检查它是否在其中一个棱镜内。对于查询段或三角形,算法会检查查询是否被完全覆盖。有关如何检查此封面的详细信息,请参阅本文。

        多面体包络包含检查由包“三角形曲面网格简化”的类Surface_mesh_simplification::polyhedral_envelope_filter使用,以便在给定公差内简化三角形网格。

5.4、形状谓词

        多边形网格的形状不佳,甚至更糟糕的是,网格中完全退化的元素在许多算法中都有问题,人们可能希望在网格中使用这些算法。此软件包提供了一个函数工具包来检测这些不想要的元素。

        CGAL::Polygon_mesh_processing::is_degenerate_edge(),用于检测边是否退化(即,如果它的两个顶点共享相同的几何位置)。
        CGAL::Polygon_mesh_processing::is_degenerate_triangle_face(),用于检测面是否退化(即,它的三个顶点是否共线)。
        CGAL::Polygon_mesh_processing::degenerate_edges(),用于收集一定范围内的退化边缘。
        CGAL::Polygon_mesh_processing::degenerate_faces(),用于收集一定范围内的退化面。
        CGAL::Polygon_mesh_processing::is_cap_triangle_face()
        CGAL::多边形网Polygon_mesh_processing处理::is_needle_triangle_face()

5.5、曲面定位函数

        为了简化对曲面上的点的操作,CGAL 图形库基于多边形网格上点的不同表示提供了大量函数:点表示为多边形网格的一个面和重心坐标的三元组。这个定义使得可以稳健地处理同一面上的点之间的折线:例如,由同一面内的四个点创建的两个 3D 段可能由于不精确的计算而不会实际相交。然而,通过它们的重心坐标来操作这些相同的点是可以的,并且在重心空间中计算的交点不会遇到同样的问题。此外,这个定义只依赖于表面的内在维度,而不依赖于表面嵌入的环境维度。

        组位置函数的功能提供以下功能:给定一个点,位置计算(CGAL:Polygon_mesh_processing::locate()和类似)给定一个点或射线,在网格上找到最近的点(CGAL:Polygon_mesh_processing::locate_with_AABB_tree()和类似),以及基于位置的谓词(例如CGAL:Polygon_mesh_processing::is_on_face_border())。

        Polygon_mesh_processing/locate_example.cpp 示例展示了其中一些函数。

6、方向

        此包提供了多个功能,用于计算面集(截面多边形Soups)和多边形网格(截面多边形网格)的一致面方向。

6.1、多边形Soups

        当给定多边形网格的面但连通性未知时,这组面被称为多边形汤。

        在多边形汤上运行任何算法之前,应该确保多边形方向一致。为此,此软件包提供了函数CGAL::Polygon_mesh_processing::orient_polygon_soup()。

        为了处理无法转换为组合流形曲面的多边形汤,必须复制一些点。由于多边形汤没有任何连通性(每个点的出现次数与其所属的多边形的数量相同),复制一个点(或一对点)就相当于复制它所属的多边形。复制的点要么是两个以上多边形相交的边的端点,要么是两个方向不兼容的多边形之间的边的端点(在重新定向过程中),或者更一般地,是点p,在点p处,以p为中心的无限小球与多边形的交点不是一个拓扑圆盘。

        一旦多边形汤具有一致的方向,并且可能包含重复(或更多)的点,就可以恢复连通性并使其保持一致,以构建有效的多边形网格。函数CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh()执行此网格构建步骤。

        相反,可以使用函数CGAL::Polygon_mesh_processing::polygon_mesh_to_polygon_soup()从多边形网格构造多边形汤。

6.2、多边形网格

        此包提供了处理闭合多边形网格中面的方向的函数。

        函数CGAL::Polygon_mesh_production::orientation()使闭合多边形网格的每个连接组件向外或向内定向。

        函数CGAL::Polygon_mesh_production::orient_to_bound_a_volume()确定闭合多边形网格的连接组件的方向,使其界定体积(有关精确定义,请参见定义)。

        函数CGAL::Polygon_mesh_production::is_outward_oriented()检查定向的多边形网格是否定向为使所有面的法线都指向由输入多边形网格限定的域的外部。

        函数CGAL::Polygon_mesh_production::reverse_face_orientations()反转面周围半边的方向。因此,为每个面计算的法线也会反转。

        函数CGAL::Polygon_mesh_production::volume_connected_components()提供了有关给定三角形网格中曲面连接组件的三维排列的信息。它带有许多命名参数选项,使其成为is_outward_oriented()的更通用版本。

        函数CGAL::Polygon_mesh_production::replicae_non_manifold_edges_in_Polygon_sgroup()复制点和边,以使汤可定向,而不更改面的方向。

        函数CGAL::Polygon_mesh_production::orient_triangle_soup_with_reference_triangle_mesh()将输入网格作为参考,并根据它确定汤的三角形方向。

        函数CGAL::Polygon_mesh_production::merge_reversible_connected_components()在可能的情况下合并多边形网格的连接组件。

7、组合修复

7.1、多边形汤修复

        为了确保多边形汤可以定向(请参见“多边形汤”一节)并转换为可行的多边形网格,可能需要对数据进行预处理,以消除组合和几何误差。此软件包提供以下功能:

        CGAL::Polygon_mesh_processing::merge_duplicate_points_in_Polygon_sgroup(),

        CGAL::Polygon_mesh_processing::merge_duplicate_polygons_in_polygon_soup(),

        CGAL::Polygon_mesh_processing::remove_isolated_points_in_Polygon_sgroup(),

        以及函数CGAL::Polygon_mesh_production::repair_Polygon_sgroup(),它将前面的函数和其他一些修复技术捆绑在一起,以获得尽可能干净的多边形汤。

7.2、缝合

        处理多边形网格时,可能会出现网格中有多个重复的边和顶点的情况。对于这些边和顶点,如果不认为是错误的,网格的连通性是不完整的。

        缝合多边形网格的边界可以修复一些重复。它包括两个主要步骤。首先,检测并配对几何上相同但重复的边界边缘。然后,将它们“缝合”在一起,以便从网格中删除重复的边缘和顶点,并且每个剩余的边缘恰好与两个面相交。

        函数CGAL::Polygon_mesh_processing::stitch_boundary_cycle()、CGAL::Polygon_mesh_processing::stitch_boundary_cycles()和CGAL::Polygon_mesh_processing::stitch_borders()可以执行此类修复操作:前两个函数可用于缝合属于同一边界的半边,而第三个函数更通用,也可以缝合位于不同边界的半边。

        输入网格应该是流形的;否则,缝合不能保证成功。

7.3、多边形网格流形

        可以使用函数CGAL::Polygon_mesh_processing::is_non_manifold_vertex()检测非流形顶点。函数 CGAL::Polygon_mesh_processing::duplicate_non_manifold_vertices()可用于尝试通过将任何非流形顶点拆分为与该几何位置处的流形片数相同的顶点来创建组合流形曲面网格。但是请注意,从几何角度来看,网格仍然不是流形的,因为在非流形顶点处引入的新顶点的位置与输入的非流形顶点相同。

7.4、边界循环中的重复顶点

        与上一节描述的有问题的配置类似,多边形网格中可能存在的另一个问题是出现“挤压”孔,即从边界半边开始,沿着该边界的半边行走时,在再次到达初始边界半边之前,几何位置多次出现(尽管具有不同的顶点)。合并相同位置的顶点的函数CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycle()和 CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycle()可用于修复此配置。

8、几何修复

        去除几乎退化的三角形面

        由几乎共线点组成的网格的三角形面是形状很差的元素,在网格中可能不希望有这样的元素。CGAL::Polygon_mesh_processing::remove_almost_degenerate_faces() 允许删除这样的元素,用户定义的参数可以限定几乎意味着什么(cap_threshold 和 needle_threshold)。

        由于一些形状很差的元素是不可避免的(例如,仅在顶部和底部圆上具有顶点的长圆柱体的三角剖分),可以传递额外的参数来防止删除这样的元素(collapse_length_threshold 和 flip_triangle_height_threshold)。

9、计算法线

        此包提供了计算多边形网格上法线的方法。可以为每个单个面计算法线,也可以为每个顶点估计法线,作为其入射面法线的平均值。这些计算是通过以下方式执行的:

        CGAL::Polygon_mesh_processing::compute_face_normal()

        CGAL::Polygon_mesh_processing::compute_vertex_normal()

        此外,我们提供了计算面、顶点或两者的所有法线的函数:

        CGAL::Polygon_mesh_processing::compute_face_normals()

        CGAL::Polygon_mesh_processing::compute_vertex_normals()

        CGAL::Polygon_mesh_processing::compute_normals()。特性贴图用于记录计算的法线。

10、计算曲率

11、分割

        Polygonslicer是一个将三角形曲面网格与平面相交的运算符。它把相交部分记录为一组折线,因为相交部分可能由多个连通分量组成。对相交部分为单个点的退化情况进行了处理。

        下图显示了三角形网格和一组平行平面切片操作返回的多段线。

         剪切网格。三角形网格(左)和网格切片器通过与一组平行平面相交计算的多段线(右)。

12、连接的组件

        此包提供了枚举和存储多边形网格的连接组件的功能。连接的零部件可以是闭合的和几何分离的,也可以通过边界或用户指定的约束边来分离。

        首先,函数CGAL::Polygon_mesh_production::connected_component()收集与作为参数给定的面属于同一连接组件的所有面。

        然后,CGAL::Polygon_mesh_production::connected_contensions()收集所有连接的组件,并用不同连接组件的索引填充特性映射。

        函数 CGAL::Polygon_mesh_processing::keep_connected_components() 和 CGAL::Polygon_mesh_processing::remove_connected_components() 允许用户仅保留和删除所选的连接组件,这些组件可以作为属于所需连接组件的面范围,也可以作为连接组件 id 范围(每个连接组件一个或多个)。

        当三角形网格没有边界时,它会将三维空间划分为不同的体积。函数CGAL::Polygon_mesh_production::volume_connected_components()可用于为每个面指定由曲面连接的组件定义的每个体积的id。

        最后,快速删除一些连接的组件是有用的,例如,对于有噪声的数据,应该丢弃小的连接组件,转而使用大的连接组件。函数CGAL::Polygon_mesh_production::keep_largest_connected_components()允许用户只保留最大连接组件中的给定数字。

        连接构件的大小由其包含的面的大小之和给出;默认情况下,面的大小为1,因此连接零部件的大小等于其包含的面数。然而,也可以传递面部大小映射,例如,面部的大小就是其区域。与上一个函数类似,函数CGAL::Polygon_mesh_production::keep_large_connected_contensions()可用于丢弃大小低于用户定义阈值的所有连接组件。

        此外,函数CGAL::Polygon_mesh_production::split_connected_components()允许用户将多边形网格的连接组件拆分为尽可能多的多边形网格。

13、豪斯多夫距离

        此包提供了计算网格和点集之间(近似)距离的方法。

13.1、近似豪斯多夫距离

        函数 approximate_Hausdorff_distance() 计算从网格 tm1 到网格 tm2 的豪斯多夫距离的近似值。给定 tm1 的采样,它计算最远采样点到 tm2 的距离。

        对称版本 (approximate_symmetric_Hausdorff_distance()) 是两个非对称距离的最大值。内部使用 sample_triangle_mesh() 对点进行采样,使用 max_distance_to_triangle_mesh() 计算到每个采样点的距离。近似值的质量取决于采样的质量,运行时间取决于采样点的数量。提供了三种具有不同参数的采样方法(见图)。

        使用不同采样方法对三角形网格进行采样。从左至右:(a)网格采样,(b)每个面和每个边具有固定点数的蒙特卡洛采样,(c)具有与面积/长度成比例的点数的蒙特卡罗采样,以及(d)均匀随机采样。这四张图片表示在网格的同一部分上进行采样,调整了参数,以便在面(蓝色点)和边(红色点)上采样的点的总数大致相同。请注意,当使用随机均匀采样时,某些面/边可能不包含任何点,但这种方法是唯一允许精确匹配给定数量点的方法。 

        函数approximate_max_dance_to_point_set()计算从网格到点集的豪斯多夫距离的近似值。对于每个三角形,计算到点集的豪斯多夫距离的下界和上界。细化三角形,直到边界之间的差低于用户定义的精度阈值。

13.2、有界豪斯多夫距离

        函数CGAL::Polygon_mesh_processing::bounded_error_Hausdorff_distance()计算两个三角网格的豪斯多夫距离的估计值,该距离由用户给定的误差界限限定。给定两个网格tm1和tm2。

        即,分别在tm1和tm2上构建有界体积层次结构(BVH)。tm1上的BVH用于迭代tm1中的所有三角形。在整个遍历过程中,该过程分别跟踪豪斯多夫距离的全局下限和上限。对于tm1中的每个三角形t,通过遍历tm2上的BVH,通过全局界限估计t是否仍然对实际豪斯多夫距离有贡献。从这个过程中,选择了一组候选三角形。

        随后对候选三角形进行细分,对于每个较小的三角形,再次遍历tm2上的BVH。重复此过程,直到三角形小于用户给定的误差范围,三角形的所有顶点投影到tm2中的同一个三角形上,或者三角形的上限低于全局下限。创建后,将细分的三角形添加到候选三角形列表中。从而,对所有候选三角形进行处理,直到找到一个Hausdorff距离达到或保证在用户给定的误差范围内达到的三角形。

        在当前的实现中,使用的BVH是AABB树,而不是原始实现中使用的扫掠球体体积。这应该解释了原始实现中观察到的运行时差异。

        函数 CGAL::Polygon_mesh_processing::bounded_error_Hausdorff_distance() 计算tm1到tm2的单侧豪斯多夫距离。该组件还提供了对称距离 CGAL::Polygon_mesh_processing::bounded_error_symmetric_Hausdorff_distance() 和一个名为 CGAL::Polygon_mesh_processing::is_Hausdorff_distance_larger() 的实用函数,如果豪斯多夫距离大于零,则返回true。

14、特征检测

        此包提供了检测多边形网格的某些特征的方法。
函数CGAL::Polygon_mesh_production::sharp_edges_segmentation()检测多边形网格的锐边,并推导曲面面片和顶点的关联。它可以分为三个函数:CGAL::Polygon_mesh_production::detect_sharp_edges()、CGAL::Polygon_mash_productions::connected_contentss()和CGAL::Polygon_mash_productions::detect_verte_incident_pages(),分别检测锐边,计算面片索引,并为每个pmesh顶点提供其入射面的面片索引。

15、其他

        豪斯多夫距离的计算方法如下:对于两个集合A和B,先对集合A中的每一个元素计算它到集合B中元素的最小距离,然后取最大值,得到d(A,B)。对集合B中的每一个元素计算它到集合A中元素的最小距离,然后取最大值,得到d(B,A)。两个距离的最大值的最大值就是豪斯多夫距离。

        光顺网格(smoothing)是一种通过改变结点坐标的方式来提高网格整体质量的技术。在光顺过程中,需要调整内部结点的位置,而固定边界结点。

        光顺网格的常用方法包括Laplacian光顺和直接法。Laplacian光顺是将某一结点移动到与之相邻结点的中心,这种方法算法简单,程序实现容易,但计算量大。直接法则通过移动结点使每个三角形都尽可能地趋近于正三角形,从而达到优化网格的效果。

        在FLUENT中,网格光顺主要采用弹簧光顺与扩散光顺两种方法。弹簧光顺包含有弹簧光顺、边界层光顺、拉普拉斯光顺,其中参数设置包括弹簧常数因子、边界节点松弛、收敛精度和迭代次数。

        直接光顺和拉普拉斯光顺在原理和应用上存在一些区别。

        原理:拉普拉斯光顺是通过计算网格中每个顶点的拉普拉斯坐标,并根据这些坐标进行网格重建来实现光顺效果的。具体而言,它将源网格模型的拉普拉斯坐标的模长缩小,但保持方向不变,然后进行拉普拉斯网格重建,从而实现简单的光顺效果。而直接光顺则是通过直接移动网格中的结点来使每个三角形尽可能接近正三角形,以达到优化网格的目的。

        应用:拉普拉斯光顺通常用于处理比较规则的网格模型,其特点是当网格曲面上任意顶点的局部片中包含的所有三角面片都为等腰三角形时,该顶点的同一拉普拉斯坐标和余切拉普拉斯坐标相等。而直接光顺则更多地被应用于实际工程中的网格优化,它可以有效提高网格的整体质量。

在计算机图形学中,多面体外壳安全壳检查通常用于检测三维模型或场景中的多面体(通常称为网格)的外壳是否安全或有效。这涉及到检查多面体的顶点、边和面是否符合规范或期望的标准。

        以下是计算机图形学中多面体外壳安全壳检查的一般步骤:

        顶点检查:检查多面体顶点的位置是否正确,是否满足特定的位置或距离要求。顶点位置的偏差可能导致模型外观的扭曲或异常。

        边检查:对多面体的边进行检测,确保没有缺失或重复的边。同时,需要检查边的连接是否正确,即边的两个顶点是否正确连接。

        面检查:对面进行检测,确保没有缺失或重复的面。同时,需要检查面的连接是否正确,即面的顶点是否正确连接。

        拓扑结构检查:检查多面体的拓扑结构是否正确,例如是否存在环路或未连接的顶点等。

        完整性检查:对多面体进行完整性检查,包括顶点、边和面的数量、连接关系等是否正确。

        边界条件检查:根据具体应用场景和要求,对多面体的边界条件进行检查,例如是否满足特定的大小、形状、位置等条件。

        碰撞检测:如果需要对多面体进行碰撞检测,还需要进行相应的碰撞检测算法实现。

        这些步骤是计算机图形学中多面体外壳安全壳检查的一般流程,具体实现过程中可能需要根据具体应用场景和要求进行调整和优化。

  fair函数是Polygon_mesh_processing模块中的一个函数,用于对多边形网格进行“公平”处理。在计算机图形学中,多边形网格的“公平”处理是一种优化技术,旨在通过重新分配顶点的位置,使得网格的各个面更加接近于平面,从而减少表面的扭曲和变形。

  triangulate_faces函数是Polygon_mesh_processing模块中的一个函数,用于将给定的多边形网格进行三角剖分。三角剖分是一种将多边形网格转换为三角形网格的几何形状近似方法。通过三角剖分,可以将复杂的几何形状简化为简单的三角形网格,从而方便进行渲染、计算等操作。

  split_long_edges函数是Polygon_mesh_processing模块中的一个函数,用于将长边拆分为更短的两段。在计算机图形学中,拆分长边可以有助于改善多边形网格的质量,从而更好地模拟物体的表面。

  border_halfedges函数是Polygon_mesh_processing模块中的一个函数,用于获取多边形网格的边界半边。在计算机图形学中,多边形网格是由顶点和半边组成的,其中每个半边连接两个顶点。而边界半边是指属于网格边界的半边,它们是网格的边缘部分。

        各向同性重网格化是一种对多边形网格进行修改和优化的技术,旨在生成更加均匀和平滑的网格。它可以在保持原始网格形状和拓扑结构的同时,通过调整网格中顶点的位置和连接关系,改善网格的质量和外观。

   CGAL::Polygon_mesh_processing::isotropic_remeshing函数接受一个多边形网格作为输入,并应用各向同性重网格化算法对其进行处理。该函数可以根据用户指定的参数和选项进行控制,以实现不同的重网格化效果。

        CGAL::Polygon_mesh_processing::sharp_edges_segmentation是一个用于对三维多边形网格进行尖锐边缘分割的函数。这个函数可以根据网格中尖锐边缘的几何特征,将它们分割成更小的子网格,从而更精确地表示模型的真实结构。

相关推荐

  1. CGALSTL扩展

    2023-12-18 11:20:02       26 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-18 11:20:02       17 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-18 11:20:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-18 11:20:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-18 11:20:02       18 阅读

热门阅读

  1. C语言中的结构体成员赋值与访问详解

    2023-12-18 11:20:02       43 阅读
  2. unity中实现Edge浏览器鼠标手势的功能

    2023-12-18 11:20:02       45 阅读
  3. Android Studio导出Excel的一些感悟

    2023-12-18 11:20:02       33 阅读
  4. 什么是计算机网络?计算机网络基础知识

    2023-12-18 11:20:02       39 阅读
  5. LeetCode第376场周赛

    2023-12-18 11:20:02       40 阅读
  6. 技术面试斗智斗勇II

    2023-12-18 11:20:02       44 阅读
  7. Joysticks

    2023-12-18 11:20:02       50 阅读
  8. VIM ——Vimtutor 个人总结【从入门到精通】

    2023-12-18 11:20:02       44 阅读