文章目录

  • AABB Tree简介
  • 接口
    • 构造
      • 由Triangle构造
      • 由Polyhedron构造
    • 相交测试
    • 构造出结果(Constructions)
    • 距离计算
  • 简单例子
    • 三角形碰撞检测

更多CGAL文章,请看CGAL知识库
计算几何技术交流群:604668232

AABB Tree简介

「AABB Tree」AABB树组件提供了静态数据结构和算法,以支持对有限的3D对象集执行相交和距离查询。可以查询存储在数据结构中的一组几何对象,以进行相交检测、相交计算和距离计算。

  1. 如果在traits类中实现了相应的相交谓词和构造函数,则相交查询可以支持任何类型
  2. 距离查询仅限于点查询

「官方提供的例子」

  1. 相交查询:针对三角形集的线对象(射线、线、线段)查询、针对线段集的平面对象(平面、三角形)
  2. 距离查询:查找从点查询到一组三角形的最近点

「注意」此组件不适合在n个对象集中查找所有对象的交对。适用于dD lso定向盒的相交序列组件,它可以找到所有ISO定向盒的相交对

「工作原理」

  1. AABB树将几何数据的迭代器(例如,std::list<Triangle>的迭代器)作为输入,然后将其转换为基元(primitives)
  2. 根据这些原语(primitives),构建轴对齐边界框(AABB)的层次结构,并将其用于加快相交和距离查询。每个图元(primitive)可以访问一个输入几何对象(称之为基准)和该对象的一个参考标识。
  3. 每个相交查询可以返回相交图元的相交对象(例如,用于射线查询的3D点或线段)以及id(face的句柄)
  4. 同样,每个距离查询都可以返回点查询中最接近的点以及最接近的图元id

接口

构造

AABB Tree组件的主要入口点是AABB_tree,该类从几何数据集中构建一个静态的AABB树,该类实例化后,即可进行相交和距离查询等操作

由Triangle构造

#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_triangle_primitive.h>typedef CGAL::Simple_cartesian<double> K;typedef K::FT FT;
typedef K::Ray_3 Ray;
typedef K::Line_3 Line;
typedef K::Point_3 Point;
typedef K::Triangle_3 Triangle;typedef std::list<Triangle>::iterator Iterator;
typedef CGAL::AABB_triangle_primitive<K, Iterator> Primitive;
typedef CGAL::AABB_traits<K, Primitive> AABB_triangle_traits;
typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;Point a(1.0, 0.0, 0.0);
Point b(0.0, 1.0, 0.0);
Point c(0.0, 0.0, 1.0);
Point d(0.0, 0.0, 0.0);std::list<Triangle> triangles;
triangles.push_back(Triangle(a,b,c));
triangles.push_back(Triangle(a,b,d));
triangles.push_back(Triangle(a,d,c));Tree tree(triangles.begin(),triangles.end());

由Polyhedron构造

#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>typedef CGAL::Simple_cartesian<double> K;
typedef K::Point_3 Point;
typedef K::Plane_3 Plane;
typedef K::Vector_3 Vector;
typedef K::Segment_3 Segment;
typedef K::Ray_3 Ray;
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
typedef boost::optional< Tree::Intersection_and_primitive_id<Segment>::Type > Segment_intersection;
typedef boost::optional< Tree::Intersection_and_primitive_id<Plane>::Type > Plane_intersection;
typedef Tree::Primitive_id Primitive_id;Point p(1.0, 0.0, 0.0);
Point q(0.0, 1.0, 0.0);
Point r(0.0, 0.0, 1.0);
Point s(0.0, 0.0, 0.0);Polyhedron polyhedron;
polyhedron.make_tetrahedron(p, q, r, s);// constructs AABB tree
Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron);

相交测试

  1. AABB_tree::do_intersect():测试输入图形是否与AABB树相交。此函数之所以快速,是因为它仅涉及谓词,并在遇到第一个相交点后就停止
  2. AABB_tree::number_of_intersected_primitives():计算所有相交图元,返回个数
  3. AABB_tree::all_intersected_primitives():枚举出所有相交图元的id(所以无需构造相应的相交对象)
  4. AABB_tree::any_intersected_primitive():返回第一个相交的图元id(如果存在相交情况)
  5. AABB_tree::first_intersected_primitive():返回与射线最近的相交对象ID(如果存在)
// 与线段是否相交
Segment segment_query(a,b);
if(tree.do_intersect(segment_query))std::cout << "intersection(s)" << std::endl;
elsestd::cout << "no intersection" << std::endl;// 与射线相交的个数
Ray ray_query(a,b);
std::cout << tree.number_of_intersected_primitives(ray_query) << " intersections(s) with ray query" << std::endl;// 与线段相交的所有图元的ID
std::list<Primitive_id> primitives;
tree.all_intersected_primitives(segment_query, std::back_inserter(primitives));

构造出结果(Constructions)

  1. AABB_tree::all_intersections():与输入图元做相交检测,并构造出所有对象
  2. AABB_tree::any_intersection():检测并构造出第一个相交图元
  3. AABB_tree::first_intersection():检测并构造出与射线最近的相交对象
// 获得所有结果
std::list<Segment_intersection> intersections;
tree.all_intersections(segment_query, std::back_inserter(intersections));// 检测并构造出第一个相交图元
Vector vec(0.0,0.0,1.0);
Plane plane_query(a,vec);
Plane_intersection plane_intersection = tree.any_intersection(plane_query);
if(plane_intersection) {if(boost::get<Segment>(&(plane_intersection->first)))std::cout << "intersection object is a segment" << std::endl;
}

距离计算

  1. AABB_tree::closet_point():获得距离给定点最近的点
  2. AABB_tree::closest_point_and_primitive():获得距离给定点最近的图元ID

说明:AABB_tree使用辅助搜索结构来加快距离查询,但默认情况下并不会生成此数据结构,因为它仅用于距离计算。用户可在第一次计算距离之前,通过调用AABB_tree::accelerate_distance_queries()来请求二级结构的构造。

// 计算最近点
Point point_query(2.0, 2.0, 2.0);
Point closest_point = tree.closest_point(point_query);
std::cerr << "closest point is: " << closest_point << std::endl;// 最近的距离
FT sqd = tree.squared_distance(point_query);
std::cout << "squared distance: " << sqd << std::endl;// 计算最近点和最近点所在的图元ID
typedef Tree::Point_and_primitive_id Point_and_primitive_id;
Point_and_primitive_id pp = tree.closest_point_and_primitive(query);
Point closest_point = pp.first; // 最近点
Polyhedron::Face_handle f = pp.second; // 最近点所在的图元ID
std::cout << "closest point: " << closest_point << std::endl;
std::cout << "closest triangle: ( "<< f->halfedge()->vertex()->point() << " , " << f->halfedge()->next()->vertex()->point() << " , "<< f->halfedge()->next()->next()->vertex()->point()<< " )" << std::endl;

简单例子

三角形碰撞检测

// Author(s) : GeoDoer#include <iostream>
#include <list>#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_triangle_primitive.h>typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point3;
typedef Kernel::Triangle_3 Triangle_3;
typedef std::list<Triangle_3>::iterator Iterator;
typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
typedef Tree::Primitive_id Primitive_id;int main()
{三角网Point3 a(1.0, 0.0, 0.0);Point3 b(0.0, 1.0, 0.0);Point3 c(0.0, 0.0, 1.0);Point3 d(0.0, 0.0, 0.0);std::list<Triangle_3> triangles;triangles.push_back(Triangle_3(a, b, c));triangles.push_back(Triangle_3(a, b, d));triangles.push_back(Triangle_3(a, d, c));三角网的AABB_treeTree tree(triangles.begin(), triangles.end());用一个三角形与该三角网做相撞测试Triangle_3 tri_query(c, d, b);碰撞检测if(!tree.do_intersect(tri_query)){std::cout << "不相交" << std::endl;}相交个数std::cout << "相交个数" << tree.number_of_intersected_primitives(tri_query) << std::endl;获得与tri_query相交的所有图元std::list<Primitive_id> primitives;tree.all_intersected_primitives(tri_query, std::back_inserter(primitives));for(std::list<Primitive_id>::iterator it = primitives.begin(); it != primitives.end(); ++it){const Primitive_id& primitive_id = *it;int index = std::distance(primitives.begin(), it); //第几个std::cout << "第" << index << "个三角形:";std::cout << primitive_id->vertex(0) << ";" << primitive_id->vertex(1) << ";" << primitive_id->vertex(2) << std::endl;}第一个相交的图元auto first_intersection_id = tree.any_intersected_primitive(tri_query);return EXIT_SUCCESS;
}

三角网太复杂时,遇到这种问题:初判是精度问题,还不知道如何解决

[CGAL] 3D快速相交和距离计算(AABB_tree)- 三角形碰撞检测相关推荐

  1. ITK:计算两个3D点之间的距离

    ITK:计算两个3D点之间的距离 内容提要 输出结果 C++实现代码 内容提要 计算两个3D点之间的距离.可以通过更改常量Dimension轻松地将其扩展为ND. 输出结果 Dist: 1.73205 ...

  2. [原创]物探小宽线坐标快速生成(平行线坐标互算 、点到线距离计算、两线交点计算等)...

    界面如下: 下载地址:CSDN 功能简介: 主要是解决并简化各项目中坐标(特别是是斜测线坐标方程组)的重复脑残计算问题,降低脑残机率,为懒而生 1.对于斜线.规则线坐标理论快速生成等 2.两线交点的标 ...

  3. Bezier曲线快速相交计算(含代码)

    Bezier曲线快速相交计算 背景介绍 算法思路 解释和分析 示例 参考资料 背景介绍 很多时候,需要计算曲线段与曲线段是否有交点.常规的思路是直接联立方程求解.不过,直接求方程的解这种思路通常在计算 ...

  4. 调用百度api实现驾车路线和时间距离计算

    毕设篇:调用百度api实现驾车路线和时间距离计算 效果展示 html页面: <!DOCTYPE html> <html lang="en"><head ...

  5. GIS-Spatial4j经纬度距离计算(三)

    Spatial4j距离计算 借助于sptaial4j提供的接口,实现经纬度距离计算:并介绍度,弧度,距离(KM)之间的换算 spatial4j支持的距离计算三个公式: Law of Cosines(余 ...

  6. c语言欧几里德距离函数,C中的欧几里德距离计算

    我尝试使用以下代码计算PHP中的欧几里德距离,但花费的时间非常长.我想测试如果我在C中执行相同的操作,如果它会更快.输入数据应该从php传递,而其他所有数据都存储在mysql数据库中.如何快速操作,因 ...

  7. DirectX9 3D 快速上手 8

    DirectX9 3D 快速上手 8 By sssa2000 5/4/2005   上一次中途结束了本来应该讲到的控制Mesh的细节程度的方法的,这一次补上. 我们这里使用的是简单的方法,并没有涉及到 ...

  8. 小程序原生 详解实现腾讯地图标点和路线规划和距离计算

    一.开通腾讯位置服务 在微信公众平台开通腾讯位置服务 二.用开发者权限登录腾讯位置服务 在我的应用中找到在你用的小程序下的key 三.配置合法域名 在开发管理中配置腾讯位置信息的合理域名 四.代码详解 ...

  9. R语言dist函数距离计算实战(欧几里得距离、曼哈顿距离)

    R语言dist函数距离计算实战(欧几里得距离.曼哈顿距离) 目录 R语言dist函数距离计算实战(欧几里得距离.曼哈顿距离)

最新文章

  1. 姚期智担纲,清华今日成立量子信息本科班!“着眼学术尖端,致力国家战略需求“...
  2. 马鞍山职业计算机考试,2020年职业适应性(技能)测试纲要
  3. (一)、http原理
  4. 高效的SQLSERVER分页查询
  5. CPU缓存越大计算机的性能越好,CPU缓存真的越大越好?小心你的钱包
  6. HDU2040 亲和数【水题】
  7. 灵云语音识别(ASR)实现实时识别
  8. Fastjson解析嵌套Map例子
  9. 速达财务管理软件使用方法
  10. java 开源 cms_17个开源免费的Java CMS
  11. JDK7升级到JDK8
  12. 陈强教授《机器学习及R应用》课程 第十三章作业
  13. java程序cpu占用率高,分析具体线程
  14. 复现ReDet RTX 3090 pytorch1.8.1
  15. VMware 虚拟SCSI、SATA 和 NVMe 存储控制器条件、限制和兼容性
  16. 怎么样导包测试JavaWeb代码?
  17. Tomcat 支持的Java版本对照
  18. 单源最短路径的迪克斯特拉(Dijkstra)算法
  19. 【SQLite关系型数据库】SQLite语法
  20. Vmare horizon client 5.0安装过程中自动取消

热门文章

  1. c语言自动寻路打怪脚本,开个帖子分享一个带有自动寻路的贪吃蛇,快点进来盖楼...
  2. windows10 apache php7.4启用curl扩展
  3. 甘肃武警甘南高原严寒雪地炼特战技能
  4. html 错误页面 参数,讲解SEO中的2个参数:404错误页面和301重定向
  5. 【屏幕刷新】Android 屏幕刷新机制
  6. 快手申请开通直播为什么一直显示服务器忙,快手新人如何开通直播?直播没人气怎么办?...
  7. Jina AI 正式将 DocArray 捐赠给Linux基金会
  8. 如何编写linux批处理文件,Linux和Windows下的批处理文件编写
  9. 不用关键词 新AI搜索引擎火了 网友:刚用5分钟就设为默认
  10. 《Photoshop Lightroom5经典教程》—第1课1.2节 Lightroom工作区