CGAL的AABB tree

1、介绍

        AABB树组件提供了一种静态数据结构和算法,用于对有限的三维几何对象集进行高效的交集和距离查询。可以查询数据结构中存储的几何对象集,以进行交集检测、交集计算和距离计算。

        交集查询可以是任何类型的,只要在traits类中实现了相应的交集谓词和构造函数。距离查询仅限于点查询。交集查询的例子包括针对三角形集的线对象(射线、线、线段),或针对线段集的平面对象(平面、三角形)。距离查询的一个例子包括从点查询中找到最接近三角形集的点。

        请注意,该组件不适合查找所有相交对象对的问题。我们参考了组件“dD等向性盒的相交序列”,它可以找到所有相交的等向性盒。

        AABB树数据结构将几何数据的迭代器范围作为输入,然后将其转换为基元。从这些基元中构建轴对齐边界框(AABB)的层次结构,并用于加速交集和距离查询。每个基元都可以访问一个输入几何对象(所谓的基准)和一个该对象的参考id。一个典型的基元将一个3D三角形作为基准,将多面体的面柄作为id。每个交集查询都可以返回交集对象(例如,用于射线查询的3D点或线段)以及交集基元的id(这里为面柄)。同样,每个距离查询可以返回点查询的最接近点以及最接近基元的id。

左图:机械零件的曲面三角形网格。右图:建造了AABB树。 

2、接口

        该组件的主要入口点是AABB_tree类,它表示一个静态的AABB树,由一个迭代器范围的几何数据构建而成。一旦实例化,就可以对AABB树进行交集和距离查询。

        交点。例如,假设树中包含三角形图元。可以以各种方式查询树与线对象(射线、线段或直线)的交点。我们将不构造任何交点对象的交点测试与构造交点对象的交点测试区分开来。

        测试:

        函数AABB_tree::do_intersect()测试输入基元是否与查询相交。此函数很快,因为它只涉及谓词,并在第一次遇到交集后停止。

        函数AABB_tree::number_of_intersected_ primitives() 计算所有相交图元的数量。

        函数AABB_tree::all_intersected_ primitives()枚举所有相交的基元id,而不构造相应的相交对象。

        函数AABB_tree::any_intersected_primitive() 返回第一个遇到的相交基本体 ID(如果有的话),而不构造相应的相交对象,并在第一次遇到相交后停止。请注意,树的遍历顺序是这样的,首先并不指查询中相交的任何特定顺序。

        函数AABB_tree::first_intersected_primitive() 返回最接近射线源的相应相交对象的相交基本体 ID(如果有)。

        数据结构结构:

        函数AABB_tree::all_intersections() 检测并构造与输入图元相交的所有对象。

        函数AABB_tree::any_intersection()检测并构造第一个遇到的交点,并构造相应的对象。这个函数很快,因为它在第一次遇到交点后就会停止。

        函数AABB_tree::first_intersection()检测并构造最接近射线源的交点对象。

        距离AABB树通过函数AABB_tree::closest_point()计算给定点查询与输入图元的最近点。

        此外,它还可以通过函数AABB_tree::closest_point_and_primitive()计算给定点查询与最接近图元的id,即实现与点查询最小距离的图元的id。

        AABB树使用二级搜索结构来加速距离查询。在第一次距离计算之前,用户应通过调用AABB_tree::accelerate_distance_queries()来请求构建该二级结构。默认情况下不生成此数据结构,因为它仅用于距离计算。

        警告:不建议在AABB树中使用退化基元,因为特征类的底层谓词和构造可能无法处理它们。例如,如果使用CGAL库中的CGAL::AABB_traits和CGAL::Kernel,则在AABB树中使用退化三角形或线段会导致未定义的行为或崩溃。

3、性能

        我们提供了一些AABB树包含一组多面体三角形面的性能数据。我们测量了树构造时间、内存占用和各种交集和距离查询的每秒查询次数。使用的机器是运行Windows XP64的PC,配有英特尔CPU酷睿2至尊版,频率为3.06 GHz,内存为4GB。默认使用的内核是Simple_cartesian<double>(我们实验中最快的)。该程序已使用Visual C ++ 2005编译器编译,并使用了O2选项,以最大限度地提高速度。

3.1、构造

        为基准测试树构造而选择的表面三角形网格是图2所示的结点模型(14,400个三角形)。我们测量了该模型以及通过循环细分方案细分的三个更密集版本的树构造时间(AABB树单独和AABB树与内部KD树),该方案将三角形数量乘以四。

Number of trianglesConstruction (in ms)Construction with internal KD-tree (in ms)
14,400156157
57,600328328
230,4001,1411,437
921,6004,8135,953

3.2、内存

        当使用多面体三角面片基元(在AABB_polyhedron_triangle_primitive.h中定义)时,AABB树每基元占用大约61个字节(不构建内部KD树)。当使用每个基元一个参考点构建内部KD树时(调用函数AABB_tree::accelerate_distance_queries()时的默认模式),每基元增加到大约150个字节。请注意,多面体三角面片基元仅存储一个面句柄作为基元id,并从内部存储的面句柄动态计算3D三角形。当在基元中显式存储3D三角形时,树每基元占用大约140个字节而不是60个字节(不构建内部KD树)。

        下表提供了三角形数量增加时内存占用量的顺序(单位为 MB)。由于用于加速距离查询的内部 KD 树占据了大部分内存,我们建议为大型模型指定更少的参考点(均匀分布),以通过函数 AABB_tree::accelerate_distance_queries() 构建内部 KD 树,该函数将迭代器范围作为输入。

Number of trianglesAABB tree (in MBytes)AABB tree with internal KD-tree (in MBytes)
18,4001.102.76
102,4006.3314.73
1,022,40059.56151.31
1,822,400108.34291.84

3.3、交点

        下表测量了结点网格模型的 14400 个三角形版本上每秒的相交查询数量,用于射线、线、线段和平面查询。每个射线查询是通过在网格边界框内选择一个随机源点和随机向量生成的。线或线段查询是通过在边界框内选择两个随机点生成的。平面查询是通过在边界框内选择一个随机点和随机法向量生成的。请注意,平面查询通常会与输入曲面网格的许多三角形相交。这解释了枚举所有交点的相交函数的低性能数字。

FunctionSegmentRayLinePlane
AABB_tree::do_intersect()187,868185,649206,096377,969
AABB_tree::any_intersected_primitive()190,684190,027208,941360,337
AABB_tree::any_intersection()147,468143,230148,235229,336
AABB_tree::number_of_intersected_primitives()64,38952,94354,5597,906
AABB_tree::all_intersected_primitives()65,55354,83853,1835,693
AABB_tree::all_intersections()46,50738,47136,3742,644

       下图的曲线绘制了每秒查询次数(此处为具有随机分段查询的AABB_tree::all_interctions()函数)与节点三角形曲面网格的输入三角形数量的关系图。 

        每秒针对14K(显示)、57K、230K和921K三角形的结模型的三角形数的查询数。我们使用在边界框内随机选择的分段查询来调用all_interactions()函数。 

        下表测量了每秒针对几个内核的AABB_tree::all_interactions()查询数。我们使用节点网格模型的14400三角形版本进行随机分段查询。请注意Simple_cartesian内核是如何比笛卡尔内核快得多的。

KernelQueries/s (all_intersections() with segment queries)
Simple_cartesian<double>46,507
Simple_cartesian<float>43,187
Cartesian<double>5,335
Cartesian<float>5,522
Exact_predicates_inexact_constructions_kernel18,411

3.4、距离

        为基准距离选择的曲面三角形网格再次是通过循环细分获得的四个递增分辨率的结模型。在下表中,我们首先测量了树的构建时间(包括在我们的实验中用于将距离查询加速高达一个数量级的内部KD树数据结构的构建)。然后,我们测量三种类型的距离查询(AABB_tree::closest_point()、AABB_tee::squared_distance()和AABB_tree::closest_proint_and_pritive())每秒从边界框内随机选择的点查询中的查询数。

Nb trianglesConstruction (ms)Closest_point()Squared_distance()Closest_point_and_primitive()
14,400157.00045,13245,62645,770
57,600328.00021,58921,31221,137
230,4001.43711,06310,96211,086
921,6005.9535,6365,7225,703

3.5、总结 

        上述实验既不详尽,也不具有决定性,因为我们选择了一个特定案例,其中输入基元是三角形表面多面体的面。然而,我们现在提供了一些关于如何使用AABB树并获得满意性能的一般观察和建议。虽然树构造时间和内存占用在我们的实验中根据输入表面三角形网格没有太大波动,但查询数量的性能根据标准的复杂组合而变化很大:内核类型、输入基元数量、基元在空间中的分布、查询函数类型、查询类型和查询空间位置。

        内核:事实证明,CGAL内核的类型主导了最终的执行时间使用用双精度数字类型参数化的Simple_cartesian内核可以获得最佳性能。在交集和距离执行时间至关重要的应用中,可以将该内核用于AABB树,并结合更健壮的内核用于主要数据结构。

        基元:虽然输入基元的数量在最终性能中起着明显的作用,但为了获得平衡良好的AABB树,它们在空间中的分布至少同样重要。理想情况下,基元必须在空间中均匀分布,并且必须尽可能避免跨越树根节点边界的长基元。在构建树之前,将这些长基元分割成更小的基元通常是有益的,例如,通过递归最长边二等分三角形曲面网格。

        函数:查询的函数类型起着另一个重要作用。显然,列出所有交点的穷举函数比在第一个交点后停止的函数慢。在这些函数中,只调用交点测试的函数(AABB_tree::do_intersect()、AABB_tree::number_of_intersected_ primitives()、AABB_tree::any_intersected_primitive()、AABB_tree::all_intersected_ primitives())比显式构造交点的函数(AABB_tree::any_intersection()和AABB_tree::all_intersections())快。

        查询:查询:查询的类型(例如,上面使用的线、射线、线段或平面)起着另一个作用,与函数类型(详尽与否,以及是否构造交点)密切相关。当需要所有交点构造时,最终的执行时间在很大程度上取决于一般交点对象的复杂性。例如,平面查询通常将曲面三角形网格分割成许多线段,而线段查询通常将曲面三角形网格分割成少数点。最后,查询在空间中的位置在性能上起着明显的作用,特别是对于距离查询。假设通过函数AABB_tree::accelerate_distance_queries()构建内部KD树,最好指定一个已经接近曲面三角形网格的查询点,以便查询只遍历树的少数AABB。然而,对于大量原始数据(在我们的实验中大于2M个面),我们注意到在构建KD树时使用所有参考点是不必要的(有时甚至更慢)。在这些情况下,我们建议通过函数AABB_tree::accelerate_distance_queries()指定更少的参考点(通常不超过100K),均匀分布在输入图元上。

4、实施

        AABB树构建是通过计算整个输入图元的AABB来初始化的。然后,所有图元沿着这个长方体的最长坐标轴进行排序,并将图元分为两个大小相等的集合。这个过程被递归应用,直到AABB包含单个图元。该树是无叶的,如OPCODE 所示。交集查询通过在遍历过程中仅计算AABB的交集测试,并在遍历结束时(在树的叶子中)计算输入图元的交集测试来遍历树。

        参考ID在内部不使用,仅供AABB树在提供给用户的结果中引用基本体。因此,虽然在大多数情况下,每个参考ID对应一个唯一的基元,但这并不是组件的要求。这样,用户可以将这些参考ID用作标签,每个标签由多个几何对象共享。

        查询点q和输入图元之间的距离查询被转化为以q为中心的球查询。球穿过树,同时递归查询与AABB的交点,并计算树叶上查询点与输入图元的最接近点p。然后,在树的其余递归遍历中,球半径缩小到p和q之间的距离。通过将初始球半径设置为一个小值,仍然保证与输入图元的交集,从而实现效率。这是通过构造内部次级数据结构来实现的,该结构在遍历开始时为算法提供了很好的提示(默认情况下完成)。调用do_not_accelerate_distance_queries()将禁用此内部次级数据结构的构造和使用。

5、其他

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/312374.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cargo(rust包管理) 常见命令、包检索 (windows+linux)

rust环境和开发环境配置&#xff1a;rust开发环境配置 winlinux Cargo是Rust的构建系统和包管理器。 如果你的能力足够强也愿意&#xff0c;可以不用cargo进行rust开发&#xff0c;即从头开始敲代码 一、cargo包相关查询 1.查找包 查找cargo包链接&#xff1a;crates.io …

挥别2023,喜迎2024,我在CSDN赚了15000+F

Hello小伙伴们&#xff0c;大家好&#xff0c;我是 还是大剑师兰特&#xff0c; 今天是2024年的1月1日&#xff0c;首先祝大家元旦快乐&#xff01; 文章目录 不平凡的20232023博客之星&#xff0c;年度第63名6月份城市之星&#xff0c;北京第11名2023年末&#xff0c;互动总成…

Vue2 - Vue.observable 介绍

目录 1&#xff0c;介绍2&#xff0c;使用场景和 Vue 实例的区别 1&#xff0c;介绍 官网参考 可以让一个对象变成响应式数据。在 Vue 内部就是用它来处理传递给 Vue 的 data 对象&#xff0c;或是在单文件组件中 data() 返回的对象。 var vm new Vue({data: {count: 0} })…

缓存和数据库,1+1如何大于2?

一、缓存的本质 缓存&#xff0c;简单说就是为了节约对原始资源重复获取的开销&#xff0c;而将结果数据副本存放起来以供获取的方式。 首先&#xff0c;缓存往往针对的是“资源”。我们前面已经多次提到过&#xff0c;当某一个操作是"幂等"的和“安全"的&#…

10TB海量JSON数据从OSS迁移至MaxCompute

前提条件 开通MaxCompute。 在DataWorks上完成创建业务流程&#xff0c;本例使用DataWorks简单模式。详情请参见创建业务流程。 将JSON文件重命名为后缀为.txt的文件&#xff0c;并上传至OSS。本文中OSS Bucket地域为华东2&#xff08;上海&#xff09;。示例文件如下。 {&qu…

【SD】一致性角色 - 同一人物 不同姿势 - 2

首先生成4张不同姿势的图片 masterpiece,high quality,(white background:1.6),(simple background:1.4),1gril,solo,black footwear,black hair,brown eyes,closed mouth,full body,glasses,jacket,long hair,long sleeves,lookig at viewer,plaid,plaid skirt,pleated shirt,…

QT上位机开发(抽奖软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 用抽奖软件抽奖&#xff0c;是一种很常见的抽奖方式。特别是写这篇文章的时候&#xff0c;正好处于2023年12月31日&#xff0c;也是一年中最后一天…

《深入理解JAVA虚拟机笔记》并发与线程安全原理

除了增加高速缓存之外&#xff0c;为了使处理器内部的运算单元能尽量被充分利用&#xff0c;处理器可能对输入代码进行乱序执行&#xff08;Out-Of-Order Execution&#xff09;优化。处理器会在计算之后将乱序执行的结果重组&#xff0c;保证该结果与顺序执行的结果一致&#…

vue3-13

token可以是后端api的访问依据&#xff0c;一般绝大多数时候&#xff0c;前端要访问后端的api,后端都要求前端请求需要携带一个有效的token,这个token用于用户的身份校验&#xff0c;通过了校验&#xff0c;后端才会向前端返回数据&#xff0c;进行相应的操作&#xff0c;如果没…

【基础】【Python网络爬虫】【2.请求与响应】常用请求报头和常用响应方法

Python网络爬虫基础 爬虫基础请求与相应HTTP/HTTPS 协议HTTP/HTTPS的优缺点HTTP 的缺点HTTPS的优点 请求与响应概述请求请求目标&#xff08;url&#xff09;请求体&#xff08;response&#xff09;常用的请求报头查看请求体&#xff08;requests 模块&#xff09; 响应HTTP响…

[2024区块链开发入门指引] - 比特币运行原理

一份为小白用户准备的免费区块链基础教程 工欲善其事,必先利其器 Web3开发中&#xff0c;各种工具、教程、社区、语言框架.。。。 种类繁多&#xff0c;是否有一个包罗万象的工具专注与Web3开发和相关资讯能毕其功于一役&#xff1f; 参见另一篇博文&#x1f449; 2024最全面…

【Leetcode】1599. 经营摩天轮的最大利润

文章目录 题目思路代码 题目 1599. 经营摩天轮的最大利润题目链接 思路 这道题要求计算在一座摩天轮中最大化利润所需的最小轮转次数。有四个座舱&#xff0c;每个座舱最多容纳四位游客。摩天轮的运转需要支付一定的运行成本 runningCost&#xff0c;同时每位游客登舱需要…