CGAL的AABB tree

news2025/1/12 16:45:37

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.coloradmin.cn/o/1349256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024.1.1 hive_sql 题目练习,开窗,行列转换

重点知识: 在使用group by时&#xff0c;select之后的字段要么包含在聚合函数里&#xff0c;要么在group by 之后 进行行转列,行转列的核心就是使用concat_ws函数拼接(分隔符,内容), -- 以及collect_list函数进行收集,list不去重, set去重无序 列转行,核心就是使用炸裂函数把东…

DSL查询语法和RestClient查询文档

目录 DSL查询语法 DLS Query的分类 DSL Query基本语法 全文检索查询 精准查询 地理查询 复合查询 Function Score Query 复合查询 Boolean Query 搜索结果处理 排序 分页 分页 深度分页问题 深度分也解决方案 高亮 RestClient查询文档 快速入门 全文检索查…

将学习自动化测试时的医药管理信息系统项目用idea运行

将学习自动化测试时的医药管理信息系统项目用idea运行 背景 学习自动化测试的时候老师的运行方式是把医药管理信息系统项目打包成war包后再放到tomcat的webapp中去运行&#xff0c;于是我想着用idea运行会方便点&#xff0c;现在记录下步骤方便以后查找最开始没有查阅资料&am…

【心得】PHP反序列化高级利用(phar|session)个人笔记

目录 ①phar反序列化 ②session反序列化 ①phar反序列化 phar 认为是java的jar包 calc.exe phar能干什么 多个php合并为独立压缩包&#xff0c;不解压就能执行里面的php文件&#xff0c;支持web服务器和命令行 phar协议 phar://xxx.phar $phar->setmetadata($h); m…

LanceDB:在对抗数据复杂性战役中,您可信赖的坐骑

LanceDB 建立在 Lance&#xff08;一种开源列式数据格式&#xff09;之上&#xff0c;具有一些有趣的功能&#xff0c;使其对 AI/ML 具有吸引力。例如&#xff0c;LanceDB 支持显式和隐式矢量化&#xff0c;能够处理各种数据类型。LanceDB 与 PyTorch 和 TensorFlow 等领先的 M…

三菱人机交互GT Designer的使用(三,指示灯,数值显示与输入,字符串显示与输入,日期|时间的显示)

今天继续对GT进行学习&#xff0c;如有不妥&#xff0c;欢迎指正&#xff01;&#xff01;&#xff01; 目录 指示灯设置 设置指示灯 位指示灯 字指示灯 数值输入&#xff0c;输出&#xff08;二者差距不大&#xff09; 数值显示与输出 数值显示&#xff08;只能显示&…

【Maven】工程依赖下载失败错误解决

在使用 Maven 构建项目时&#xff0c;可能会发生依赖项下载错误的情况&#xff0c;主要原因有以下几种&#xff1a; 下载依赖时出现网络故障或仓库服务器宕机等原因&#xff0c;导致无法连接至 Maven 仓库&#xff0c;从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…

【计算机毕业设计】ssm+mysql+jsp实现的在线bbs论坛系统源码

项目介绍 jspssm&#xff08;springspringMVCmybatis&#xff09;MySQL实现的在线bbs论坛系统源码&#xff0c;本系统主要实现了前台用户注册登陆、浏览帖子、发布帖子、个人信息管理、消息通知管理&#xff0c;积分管理&#xff0c;后台管理功能有&#xff1a;友情链接管理、…

怎么设计一个简单又直观的接口?

文章目录 问题的开端为什么从问题开始&#xff1f;自然而来的接口 一个接口一件事情减少依赖关系使用方式要“傻” 小结 开放的接口规范是使用者和实现者之间的合约。既然是合约&#xff0c;就要成文、清楚、稳定。合约是好东西&#xff0c;它可以让代码之间的组合有规可依。但…

Stable Diffusion API入门:简明教程

Stable Diffusion 是一个先进的深度学习模型&#xff0c;用于创造和修改图像。这个模型能够基于文本描述来生成图像&#xff0c;让机器理解和实现用户的创意。使用这项技术的关键在于掌握其 API&#xff0c;通过编程来操控图像生成的过程。 在探索 Stable Diffusion API 的世界…

爱思唯尔的KBS——模板、投稿、返修、接收的总结

第二篇论文终于是接受了QAQ&#xff0c;被审稿人疯狂拖时间&#xff0c;KBS是真难绷啊 由于之前发布过关于爱思唯尔旗下的ESWA博客&#xff0c;KBS和ESWA是类似的&#xff0c;因此本篇博客主要说下区别以及期间碰到的各种情况&#xff0c;有疑问依然可以在评论区说&#xff0c;…

【C语言】函数

函数是什么&#xff1f; “函数”是我们早些年在学习数学的过程中常见的概念&#xff0c;简单回顾一下&#xff1a;比如下图中&#xff0c;你给函数 f(x)2*x3 一个具体的x,这个函数通过一系列的计算来返回给你一个结果(图示如下)。 这就是数学中函数的基本过程和作用。但是你…

48、激活函数 - 梯度消失和梯度爆炸

简单介绍下梯度消失和梯度爆炸,这个不是重点,但是我觉得有必要再深入了解这个概念,以及很多激活函数为什么是可以防止梯度消失的。 梯度消失和梯度爆炸实际上是在神经网络训练过程中经常会遇到的两类问题,这两类问题都与梯度有关。 什么是梯度 在神经网络训练中,梯度是指…

Final Cut 视频剪辑快速入门,小白上手视频课的制作

本文是一个快速入门教程&#xff0c;如果您是0视频处理基础&#xff0c;又想录制网课或是一些对效果要求不高的视频那么这篇教程足够使用了。 本文主要用Final Cut处理视频课&#xff0c;本文是笔者在制作视频课过程中逐渐摸索的&#xff0c;如果您想制作一些比较专业的视频&a…

mysql原理--Explain详解

1.概述 一条查询语句在经过 MySQL 查询优化器的各种基于成本和规则的优化会后生成一个所谓的 执行计划 &#xff0c;这个执行计划展示了接下来具体执行查询的方式&#xff0c;比如多表连接的顺序是什么&#xff0c;对于每个表采用什么访问方法来具体执行查询等等。设计 MySQL 的…

【LMM 003】生物医学领域的垂直类大型多模态模型 LLaVA-Med

论文标题&#xff1a;LLaVA-Med: Training a Large Language-and-Vision Assistant for Biomedicine in One Day 论文作者&#xff1a;Chunyuan Li∗, Cliff Wong∗, Sheng Zhang∗, Naoto Usuyama, Haotian Liu, Jianwei Yang Tristan Naumann, Hoifung Poon, Jianfeng Gao 作…

uni-app 前后端调用实例 基于Springboot 下拉刷新实现

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

UDS诊断(ISO14229-1) 11服务

文章目录 功能简介应用场景请求和响应1、请求2、子功能3、肯定响应4、否定响应 报文示例UDS中常用 NRC参考 功能简介 11服务&#xff0c;即 ECUReset&#xff08;ECU重置&#xff09;服务&#xff0c;用来控制MCU进行重启&#xff0c;重启分为硬件重启和软件重启。 应用场景…

事件循环的理解

1.单线程 Js是一个单线程的语言,代码只能一行一行去执行,遇到同步的代码就直接执行了,如果遇到异步的代码怎么办&#xff1f; 不可能等到异步的代码执行完&#xff0c;在去执行后面同步的代码。 2.主线程 遇到同步的代码,就在主线程里面直接执行了。 3.任务队列 遇到异步的…

Vue中使用JavaScript中的requestAnimationFrame动画循环实现循环滚动效果-demo

效果 requestAnimationFrame是一个由浏览器提供的 JavaScript 方法&#xff0c;用于在下一次浏览器重绘之前执行指定的回调函数。它接受一个回调函数作为参数&#xff0c;并返回一个整数值&#xff0c;可以用于取消动画循环。 使用 requestAnimationFrame 可以创建平滑的动画效…