AABB tree: test all intersection types for triangles

This commit is contained in:
Pierre Alliez 2009-04-26 21:29:47 +00:00
parent 2421c82abe
commit a8188eb668
3 changed files with 133 additions and 85 deletions

View File

@ -15,7 +15,7 @@
// $Id: AABB_tree.h 48894 2009-04-24 14:11:17Z palliez $ // $Id: AABB_tree.h 48894 2009-04-24 14:11:17Z palliez $
// //
// //
// Author(s) : Pierre Alliez // Author(s) : Pierre Alliez
#ifndef CGAL_AABB_SEARCH_TREE_H #ifndef CGAL_AABB_SEARCH_TREE_H
#define CGAL_AABB_SEARCH_TREE_H #define CGAL_AABB_SEARCH_TREE_H
@ -25,7 +25,6 @@
namespace CGAL namespace CGAL
{ {
template <class Traits> template <class Traits>
class AABB_search_tree class AABB_search_tree
{ {
@ -35,10 +34,8 @@ namespace CGAL
typedef typename CGAL::Search_traits_3<Traits> TreeTraits; typedef typename CGAL::Search_traits_3<Traits> TreeTraits;
typedef typename CGAL::Orthogonal_k_neighbor_search<TreeTraits> Neighbor_search; typedef typename CGAL::Orthogonal_k_neighbor_search<TreeTraits> Neighbor_search;
typedef typename Neighbor_search::Tree Tree; typedef typename Neighbor_search::Tree Tree;
private: private:
Tree m_tree; Tree m_tree;
public: public:
AABB_search_tree() {} AABB_search_tree() {}
~AABB_search_tree() {} ~AABB_search_tree() {}
@ -51,7 +48,6 @@ namespace CGAL
Point nearest_point(const Point& query) Point nearest_point(const Point& query)
{ {
// queries first nearest neighbor
Neighbor_search search(m_tree, query, 1); Neighbor_search search(m_tree, query, 1);
return search.begin()->first; return search.begin()->first;
} }

View File

@ -16,7 +16,7 @@
// $Id$ // $Id$
// //
// //
// Author(s) : Camille Wormser, Pierre Alliez, Laurent Rineau, Stephane Tayeb // Author(s) : Camille Wormser, Pierre Alliez, Laurent Rineau, Stephane Tayeb
#ifndef CGAL_AABB_TREE_H #ifndef CGAL_AABB_TREE_H
#define CGAL_AABB_TREE_H #define CGAL_AABB_TREE_H
@ -42,10 +42,10 @@ namespace CGAL {
public: public:
/// Traits types /// Traits types
typedef typename AABBTraits::Primitive Primitive; typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Projection_query Projection_query;
typedef typename AABBTraits::Projection Projection; typedef typename AABBTraits::Projection Projection;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Intersection Intersection; typedef typename AABBTraits::Intersection Intersection;
typedef typename AABBTraits::Projection_query Projection_query;
private: private:
typedef typename AABB_search_tree<AABBTraits> Search_tree; typedef typename AABB_search_tree<AABBTraits> Search_tree;
@ -69,9 +69,8 @@ namespace CGAL {
template<typename ConstPointIterator> template<typename ConstPointIterator>
void construct_search_tree(ConstPointIterator first, ConstPointIterator beyond); void construct_search_tree(ConstPointIterator first, ConstPointIterator beyond);
/// Construct internal search tree from a point set taken on /// Construct internal search tree from a point set taken on the internal primitives
// the internal primitives void construct_search_tree(void);
void construct_search_tree();
template<typename Query> template<typename Query>
bool do_intersect(const Query& q) const; bool do_intersect(const Query& q) const;
@ -295,17 +294,13 @@ namespace CGAL {
private: private:
// member data // set of input primitives
// set of input primitives (halfedge or face handles)
std::vector<Primitive> m_data; std::vector<Primitive> m_data;
// single root node // single root node
Node* m_p_root; Node* m_p_root;
// single root node // search KD-tree
bool m_search_tree_constructed;
public:
Search_tree m_search_tree; Search_tree m_search_tree;
bool m_search_tree_constructed;
private: private:
// Disabled copy constructor & assignment operator // Disabled copy constructor & assignment operator
@ -332,9 +327,11 @@ namespace CGAL {
} }
m_p_root = new Node[m_data.size()-1](); m_p_root = new Node[m_data.size()-1]();
CGAL_assertion(m_p_root != NULL);
m_p_root->expand(m_data.begin(), m_data.end(), m_data.size()); m_p_root->expand(m_data.begin(), m_data.end(), m_data.size());
} }
// constructs the search KD tree from given points
template<typename Tr> template<typename Tr>
template<typename ConstPointIterator> template<typename ConstPointIterator>
void void
@ -345,13 +342,14 @@ namespace CGAL {
m_search_tree_constructed = true; m_search_tree_constructed = true;
} }
// constructs the search KD tree from interal primitives
template<typename Tr> template<typename Tr>
void AABB_tree<Tr>::construct_search_tree() void AABB_tree<Tr>::construct_search_tree(void)
{ {
// iterate over primitives to get points on them // iterate over primitives to get points on them
std::list<Projection_query> points; std::list<Projection_query> points;
std::vector<Primitive>::const_iterator it; std::vector<Primitive>::const_iterator it;
for(it = m_data.begin();it != m_data.end();it++) for(it = m_data.begin(); it != m_data.end(); it++)
{ {
const Primitive& pr = *it; const Primitive& pr = *it;
points.push_back(pr.point_on()); points.push_back(pr.point_on());
@ -378,8 +376,6 @@ namespace CGAL {
return traversal_traits.is_intersection_found(); return traversal_traits.is_intersection_found();
} }
template<typename Tr> template<typename Tr>
template<typename Query> template<typename Query>
int int
@ -435,7 +431,6 @@ namespace CGAL {
return traversal_traits.is_intersection_found(); return traversal_traits.is_intersection_found();
} }
// closest point with user-specified hint // closest point with user-specified hint
template<typename Tr> template<typename Tr>
typename AABB_tree<Tr>::Projection typename AABB_tree<Tr>::Projection
@ -448,12 +443,13 @@ namespace CGAL {
return traversal_traits.projection(); return traversal_traits.projection();
} }
// closest point without hint // closest point without hint, the search KD-tree is queried for the
// first nearest neighbor point to get a hint
template<typename Tr> template<typename Tr>
typename AABB_tree<Tr>::Projection typename AABB_tree<Tr>::Projection
AABB_tree<Tr>::closest_point(const Projection_query& query) AABB_tree<Tr>::closest_point(const Projection_query& query)
{ {
// construct search tree if needed // construct search KD-tree if needed
if(!m_search_tree_constructed) if(!m_search_tree_constructed)
construct_search_tree(); construct_search_tree();

View File

@ -22,93 +22,149 @@
// //
//****************************************************************************** //******************************************************************************
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
#include <CGAL/Timer.h> #include <CGAL/Timer.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h> #include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h> #include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h> #include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_polyhedron_triangle_primitive.h> #include <CGAL/AABB_polyhedron_triangle_primitive.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
template <class Tree, class K>
void test_all_query_types(Tree& tree)
{
std::cout << "Test all query types" << std::endl;
typedef K::FT FT;
typedef K::Ray_3 Ray;
typedef K::Line_3 Line;
typedef K::Point_3 Point;
typedef K::Vector_3 Vector;
typedef K::Segment_3 Segment;
typedef Tree::Primitive Primitive;
typedef Tree::Intersection Intersection;
Point p((FT)-0.5, (FT)-0.5, (FT)-0.5);
Point q((FT) 0.5, (FT) 0.5, (FT) 0.5);
Ray ray(p,q);
Ray line(p,q);
Ray segment(p,q);
bool success = false;
// do_intersect
success = tree.do_intersect(ray);
success = tree.do_intersect(line);
success = tree.do_intersect(segment);
// number_of_intersections
tree.number_of_intersections(ray);
tree.number_of_intersections(line);
tree.number_of_intersections(segment);
// all_intersected_primitives
std::list<Primitive> primitives;
tree.all_intersected_primitives(ray,std::back_inserter(primitives));
tree.all_intersected_primitives(line,std::back_inserter(primitives));
tree.all_intersected_primitives(segment,std::back_inserter(primitives));
// any_intersection
Intersection intersection;
success = tree.any_intersection(ray,intersection);
success = tree.any_intersection(line,intersection);
success = tree.any_intersection(segment,intersection);
// all_intersections
std::list<Intersection> intersections;
tree.all_intersections(ray,std::back_inserter(intersections));
tree.all_intersections(line,std::back_inserter(intersections));
tree.all_intersections(segment,std::back_inserter(intersections));
}
template <class Tree, class Polyhedron, class K> template <class Tree, class Polyhedron, class K>
void test_speed(Tree& tree, void test_speed(Tree& tree,
Polyhedron& polyhedron) Polyhedron& polyhedron)
{ {
typedef K::FT FT; std::cout << "Test for speed" << std::endl;
typedef K::Ray_3 Ray; typedef K::FT FT;
typedef K::Point_3 Point; typedef K::Ray_3 Ray;
typedef K::Vector_3 Vector; typedef K::Point_3 Point;
typedef K::Vector_3 Vector;
CGAL::Timer timer; CGAL::Timer timer;
unsigned int nb = 0; unsigned int nb = 0;
timer.start(); timer.start();
Point source((FT)0.0, (FT)0.0, (FT)0.0); Point source((FT)0.0, (FT)0.0, (FT)0.0);
Vector vec((FT)0.1, (FT)0.2, (FT)0.3); Vector vec((FT)0.1, (FT)0.2, (FT)0.3);
Ray ray(source, vec); Ray ray(source, vec);
while(timer.time() < 1.0) while(timer.time() < 1.0)
{ {
tree.do_intersect(ray); tree.do_intersect(ray);
nb++; nb++;
} }
double speed = (double)nb / timer.time(); double speed = (double)nb / timer.time();
std::cout << speed << " intersections/s" << std::endl; std::cout << speed << " intersections/s" << std::endl;
timer.stop(); timer.stop();
} }
template <class K> template <class K>
void test(const char *filename) void test(const char *filename)
{ {
typedef K::FT FT; typedef K::FT FT;
typedef K::Ray_3 Ray; typedef K::Ray_3 Ray;
typedef K::Point_3 Point; typedef K::Point_3 Point;
typedef K::Vector_3 Vector; typedef K::Vector_3 Vector;
typedef CGAL::Polyhedron_3<K> Polyhedron; typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef CGAL::AABB_polyhedron_triangle_primitive<K,Polyhedron> Primitive; typedef CGAL::AABB_polyhedron_triangle_primitive<K,Polyhedron> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits; typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree; typedef CGAL::AABB_tree<Traits> Tree;
Polyhedron polyhedron; // load (triangle) polyhedral surface
std::ifstream ifs(filename); Polyhedron polyhedron;
ifs >> polyhedron; std::ifstream ifs(filename);
ifs >> polyhedron;
// construct tree without internal KD-tree as we do not query // construct tree (without internal KD-tree as we do not query any projection).
// any projection. Tree tree(polyhedron.facets_begin(),polyhedron.facets_end());
Tree tree(polyhedron.facets_begin(),polyhedron.facets_end());
// TODO // call tests
// - compare tree tests with exhaustive ones test_all_query_types<Tree,K>(tree);
// - query with ray/line/segment test_speed<Tree,Polyhedron,K>(tree,polyhedron);
Point source((FT)0.5, (FT)0.5, (FT)0.5);
Ray ray(source, Vector((FT)0.1, (FT)0.2, (FT)0.3));
std::cout << tree.number_of_intersections(ray)
<< " intersections(s) with ray" << std::endl;
test_speed<Tree,Polyhedron,K>(tree,polyhedron);
} }
void test_kernels(const char *filename) void test_several_kernels(const char *filename)
{ {
std::cout << std::endl; std::cout << std::endl;
std::cout << "Polyhedron " << filename << std::endl; std::cout << "Polyhedron " << filename << std::endl;
std::cout << "Simple cartesian float kernel" << std::endl; std::cout << "Simple cartesian float kernel" << std::endl;
test<CGAL::Simple_cartesian<float> >(filename); test<CGAL::Simple_cartesian<float> >(filename);
std::cout << "Simple cartesian double kernel" << std::endl; std::cout << "Cartesian float kernel" << std::endl;
test<CGAL::Simple_cartesian<double> >(filename); test<CGAL::Cartesian<float> >(filename);
std::cout << "Epic kernel" << std::endl; std::cout << "Simple cartesian double kernel" << std::endl;
test<CGAL::Exact_predicates_inexact_constructions_kernel>(filename); test<CGAL::Simple_cartesian<double> >(filename);
std::cout << "Cartesian double kernel" << std::endl;
test<CGAL::Cartesian<double> >(filename);
std::cout << "Epic kernel" << std::endl;
test<CGAL::Exact_predicates_inexact_constructions_kernel>(filename);
} }
int main(void) int main(void)
{ {
std::cout << "AABB intersection tests" << std::endl; std::cout << "AABB intersection tests" << std::endl;
test_kernels("../data/cube.off"); test_several_kernels("../data/cube.off");
test_kernels("../data/coverrear.off"); test_several_kernels("../data/coverrear.off");
test_kernels("../data/nested_spheres.off"); test_several_kernels("../data/nested_spheres.off");
return 0; return 0;
} }