[CGAL] 3D快速相交和距离计算(AABB_tree)- 三角形碰撞检测
文章目录
- AABB Tree简介
- 接口
- 构造
- 由Triangle构造
- 由Polyhedron构造
- 相交测试
- 构造出结果(Constructions)
- 距离计算
- 简单例子
- 三角形碰撞检测
更多CGAL文章,请看CGAL知识库
计算几何技术交流群:604668232
AABB Tree简介
「AABB Tree」AABB树组件提供了静态数据结构和算法,以支持对有限的3D对象集执行相交和距离查询。可以查询存储在数据结构中的一组几何对象,以进行相交检测、相交计算和距离计算。
- 如果在traits类中实现了相应的相交谓词和构造函数,则相交查询可以支持任何类型
- 距离查询仅限于点查询
「官方提供的例子」
- 相交查询:针对三角形集的线对象(射线、线、线段)查询、针对线段集的平面对象(平面、三角形)
- 距离查询:查找从点查询到一组三角形的最近点
「注意」此组件不适合在n个对象集中查找所有对象的交对。适用于dD lso定向盒的相交序列组件,它可以找到所有ISO定向盒的相交对
「工作原理」
- AABB树将几何数据的迭代器(例如,
std::list<Triangle>
的迭代器)作为输入,然后将其转换为基元(primitives) - 根据这些原语(primitives),构建轴对齐边界框(AABB)的层次结构,并将其用于加快相交和距离查询。每个图元(primitive)可以访问一个输入几何对象(称之为基准)和该对象的一个参考标识。
- 每个相交查询可以返回相交图元的相交对象(例如,用于射线查询的3D点或线段)以及id(face的句柄)
- 同样,每个距离查询都可以返回点查询中最接近的点以及最接近的图元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);
相交测试
AABB_tree::do_intersect()
:测试输入图形是否与AABB树相交。此函数之所以快速,是因为它仅涉及谓词,并在遇到第一个相交点后就停止AABB_tree::number_of_intersected_primitives()
:计算所有相交图元,返回个数AABB_tree::all_intersected_primitives()
:枚举出所有相交图元的id(所以无需构造相应的相交对象)AABB_tree::any_intersected_primitive()
:返回第一个相交的图元id(如果存在相交情况)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)
AABB_tree::all_intersections()
:与输入图元做相交检测,并构造出所有对象AABB_tree::any_intersection()
:检测并构造出第一个相交图元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;
}
距离计算
AABB_tree::closet_point()
:获得距离给定点最近的点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)- 三角形碰撞检测相关推荐
- ITK:计算两个3D点之间的距离
ITK:计算两个3D点之间的距离 内容提要 输出结果 C++实现代码 内容提要 计算两个3D点之间的距离.可以通过更改常量Dimension轻松地将其扩展为ND. 输出结果 Dist: 1.73205 ...
- [原创]物探小宽线坐标快速生成(平行线坐标互算 、点到线距离计算、两线交点计算等)...
界面如下: 下载地址:CSDN 功能简介: 主要是解决并简化各项目中坐标(特别是是斜测线坐标方程组)的重复脑残计算问题,降低脑残机率,为懒而生 1.对于斜线.规则线坐标理论快速生成等 2.两线交点的标 ...
- Bezier曲线快速相交计算(含代码)
Bezier曲线快速相交计算 背景介绍 算法思路 解释和分析 示例 参考资料 背景介绍 很多时候,需要计算曲线段与曲线段是否有交点.常规的思路是直接联立方程求解.不过,直接求方程的解这种思路通常在计算 ...
- 调用百度api实现驾车路线和时间距离计算
毕设篇:调用百度api实现驾车路线和时间距离计算 效果展示 html页面: <!DOCTYPE html> <html lang="en"><head ...
- GIS-Spatial4j经纬度距离计算(三)
Spatial4j距离计算 借助于sptaial4j提供的接口,实现经纬度距离计算:并介绍度,弧度,距离(KM)之间的换算 spatial4j支持的距离计算三个公式: Law of Cosines(余 ...
- c语言欧几里德距离函数,C中的欧几里德距离计算
我尝试使用以下代码计算PHP中的欧几里德距离,但花费的时间非常长.我想测试如果我在C中执行相同的操作,如果它会更快.输入数据应该从php传递,而其他所有数据都存储在mysql数据库中.如何快速操作,因 ...
- DirectX9 3D 快速上手 8
DirectX9 3D 快速上手 8 By sssa2000 5/4/2005 上一次中途结束了本来应该讲到的控制Mesh的细节程度的方法的,这一次补上. 我们这里使用的是简单的方法,并没有涉及到 ...
- 小程序原生 详解实现腾讯地图标点和路线规划和距离计算
一.开通腾讯位置服务 在微信公众平台开通腾讯位置服务 二.用开发者权限登录腾讯位置服务 在我的应用中找到在你用的小程序下的key 三.配置合法域名 在开发管理中配置腾讯位置信息的合理域名 四.代码详解 ...
- R语言dist函数距离计算实战(欧几里得距离、曼哈顿距离)
R语言dist函数距离计算实战(欧几里得距离.曼哈顿距离) 目录 R语言dist函数距离计算实战(欧几里得距离.曼哈顿距离)
最新文章
- 姚期智担纲,清华今日成立量子信息本科班!“着眼学术尖端,致力国家战略需求“...
- 马鞍山职业计算机考试,2020年职业适应性(技能)测试纲要
- (一)、http原理
- 高效的SQLSERVER分页查询
- CPU缓存越大计算机的性能越好,CPU缓存真的越大越好?小心你的钱包
- HDU2040 亲和数【水题】
- 灵云语音识别(ASR)实现实时识别
- Fastjson解析嵌套Map例子
- 速达财务管理软件使用方法
- java 开源 cms_17个开源免费的Java CMS
- JDK7升级到JDK8
- 陈强教授《机器学习及R应用》课程 第十三章作业
- java程序cpu占用率高,分析具体线程
- 复现ReDet RTX 3090 pytorch1.8.1
- VMware 虚拟SCSI、SATA 和 NVMe 存储控制器条件、限制和兼容性
- 怎么样导包测试JavaWeb代码?
- Tomcat 支持的Java版本对照
- 单源最短路径的迪克斯特拉(Dijkstra)算法
- 【SQLite关系型数据库】SQLite语法
- Vmare horizon client 5.0安装过程中自动取消
热门文章
- c语言自动寻路打怪脚本,开个帖子分享一个带有自动寻路的贪吃蛇,快点进来盖楼...
- windows10 apache php7.4启用curl扩展
- 甘肃武警甘南高原严寒雪地炼特战技能
- html 错误页面 参数,讲解SEO中的2个参数:404错误页面和301重定向
- 【屏幕刷新】Android 屏幕刷新机制
- 快手申请开通直播为什么一直显示服务器忙,快手新人如何开通直播?直播没人气怎么办?...
- Jina AI 正式将 DocArray 捐赠给Linux基金会
- 如何编写linux批处理文件,Linux和Windows下的批处理文件编写
- 不用关键词 新AI搜索引擎火了 网友:刚用5分钟就设为默认
- 《Photoshop Lightroom5经典教程》—第1课1.2节 Lightroom工作区