官方文档:3D Fast Intersection and Distance Computation (AABB Tree)
原文链接,不定时更新,此文档为第一版,之后不再同步。
QQ交流群:1097346536
「AABB Tree」AABB树组件提供了静态数据结构和算法,以支持对有限的3D对象集执行相交和距离查询。可以查询存储在数据结构中的一组几何对象,以进行相交检测、相交计算和距离计算。
「官方提供的例子」
「注意」此组件不适合在n个对象集中查找所有对象的交对。适用于dD lso定向盒的相交序列组件,它可以找到所有ISO定向盒的相交对
「工作原理」
std::list
的迭代器)作为输入,然后将其转换为基元(primitives)AABB Tree组件的主要入口点是AABB_tree
,该类从几何数据集中构建一个静态的AABB树,该类实例化后,即可进行相交和距离查询等操作。
#include
#include
#include
#include
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());
#include
#include
#include
#include
#include
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;
else
std::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));
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
#include
#include
#include
#include
#include
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_tree
Tree 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;
}
三角网太复杂时,遇到这种问题:初判是精度问题,还不知道如何解决