// Copyright (c) 2008 INRIA Sophia-Antipolis (France), ETHZ (Suisse). // Copyrigth (c) 2009 GeometryFactory (France) // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Camille Wormser, Pierre Alliez, Laurent Rineau, Stephane Tayeb #ifndef CGAL_AABB_TREE_H #define CGAL_AABB_TREE_H #include #include #include #include #include #include namespace CGAL { /** * @class AABB_tree * * */ template class AABB_tree { public: /// Traits types typedef typename AABBTraits::Primitive Primitive; typedef typename AABBTraits::Bounding_box Bounding_box; typedef typename AABBTraits::Projection_query Projection_query; typedef typename AABBTraits::Projection_type Projection_type; typedef typename AABBTraits::Intersection_type Intersection_type; /** * @brief Constructor * @param first iterator over first primitive to insert * @param beyond past-the-end iterator * * Builds the datastructure. Type ConstPrimitiveIterator can be any const * iterator on a container of Primitive::id_type such that Primitive has * a constructor taking a ConstPrimitiveIterator as argument. */ template AABB_tree(ConstPrimitiveIterator first, ConstPrimitiveIterator beyond); /// Non virtual destructor ~AABB_tree(); template bool do_intersect(const Query& q) const; template int number_of_intersections(const Query& q) const; template OutputIterator all_intersected_primitives(const Query& q, OutputIterator out) const; template OutputIterator all_intersections(const Query& q, OutputIterator out) const; template bool any_intersection(const Query& q, Intersection_type& intersection) const; template bool any_intersected_primitive(const Query& q, Primitive& pr) const; Projection_type closest_point(const Projection_query& q, const Projection_type& hint) const; ////////////////////////////////////////////// //TODO: document this Bounding_box root_bbox() const { return p_root_->bounding_box(); } bool is_empty() const { return data_.empty(); } size_t size() const { return data_.size(); } /// generic traversal of tree template void traversal(const Query& q, Traversal_traits& traits) const { p_root_->template traversal(q, traits, data_.size()); } ////////////////////////////////////////////// private: typedef AABB_node Node; typedef typename AABBTraits::Sphere Sphere; //------------------------------------------------------- // Traits classes for traversal computation //------------------------------------------------------- /** * @class First_intersection_traits */ template class First_intersection_traits { public: First_intersection_traits() : is_found_(false) , result_() {} bool go_further() const { return !is_found_; } void intersection(const Query& q, const Primitive& primitive) { is_found_ = AABBTraits().intersection(q, primitive, result_); } bool do_intersect(const Query& q, const Node& node) const { return AABBTraits().do_intersect(q, node.bounding_box()); } Intersection_type result() const { return result_; } bool is_intersection_found() const { return is_found_; } private: bool is_found_; Intersection_type result_; }; /** * @class Counting_traits */ template class Counting_traits { public: Counting_traits() : intersection_() , intersection_nb_(0) {} bool go_further() const { return true; } void intersection(const Query& q, const Primitive& primitive) { if( AABBTraits().intersection(q, primitive, intersection_) ) { ++intersection_nb_; } } bool do_intersect(const Query& q, const Node& node) const { return AABBTraits().do_intersect(q, node.bounding_box()); } int intersection_number() const { return intersection_nb_; } private: Intersection_type intersection_; int intersection_nb_; }; /** * @class Listing_intersection_traits */ template class Listing_intersection_traits { public: Listing_intersection_traits(Output_iterator out_it) : intersection_() , out_it_(out_it) {} bool go_further() const { return true; } void intersection(const Query& q, const Primitive& primitive) { if( AABBTraits().intersection(q, primitive, intersection_) ) { *out_it_++ = intersection_; } } bool do_intersect(const Query& q, const Node& node) const { return AABBTraits().do_intersect(q, node.bounding_box()); } private: Intersection_type intersection_; Output_iterator out_it_; }; /** * @class Listing_primitive_traits */ template class Listing_primitive_traits { public: Listing_primitive_traits(Output_iterator out_it) : intersection_() , out_it_(out_it) {} bool go_further() const { return true; } void intersection(const Query& q, const Primitive& primitive) { if( AABBTraits().intersection(q, primitive, intersection_) ) { *out_it_++ = primitive; } } bool do_intersect(const Query& q, const Node& node) const { return AABBTraits().do_intersect(q, node.bounding_box()); } private: Intersection_type intersection_; Output_iterator out_it_; }; /** * @class Projection_traits */ class Projecting_traits { public: Projecting_traits(const Projection_query& query, const Projection_type& hint) : projection_(hint) , center_(query) , sphere_(AABBTraits().sphere(query,hint)) { } bool go_further() const { return true; } void intersection(const Projection_query& q, const Primitive& primitive) { // We don't use q here because it is embedded in sphere_ and we don't // want to compute sphere everytime Projection_type projection; if ( AABBTraits().intersection(sphere_, primitive, projection) ) { const Sphere sphere = AABBTraits().sphere(center_, projection); if ( AABBTraits().is_smaller(sphere, sphere_) ) { projection_ = projection; sphere_ = sphere; } } } bool do_intersect(const Projection_query& q, const Node& node) const { return AABBTraits().do_intersect(sphere_, node.bounding_box()); } Projection_type projection() const { return projection_; } private: Projection_type projection_; Projection_query center_; Sphere sphere_; }; private: // set of input primitives (halfedge or face handles) std::vector data_; // single root node Node* p_root_; private: // Disabled copy constructor & assignment operator typedef AABB_tree Self; AABB_tree(const Self& src); Self& operator=(const Self& src); }; // end class AABB_tree template template AABB_tree::AABB_tree(ConstPrimitiveIterator first, ConstPrimitiveIterator beyond) : data_() , p_root_(NULL) { // Insert each primitive into tree // TODO: get number of elements to reserve space ? while ( first != beyond ) { data_.push_back(Primitive(first)); ++first; } p_root_ = new Node[data_.size()-1](); p_root_->expand(data_.begin(), data_.end(), data_.size()); } template AABB_tree::~AABB_tree() { delete[] p_root_; } template template bool AABB_tree::do_intersect(const Query& query) const { typedef First_intersection_traits Traversal_traits; Traversal_traits traversal_traits; this->traversal(query, traversal_traits); return traversal_traits.is_intersection_found(); } template template int AABB_tree::number_of_intersections(const Query& query) const { typedef Counting_traits Traversal_traits; Traversal_traits traversal_traits; this->traversal(query, traversal_traits); return traversal_traits.intersection_number(); } template template OutputIterator AABB_tree::intersected_primitives(const Query& query, OutputIterator out) const { typedef Listing_primitive_traits Traversal_traits; Traversal_traits traversal_traits(out); this->traversal(query, traversal_traits); return out; } template template OutputIterator AABB_tree::all_intersections(const Query& query, OutputIterator out) const { typedef Listing_intersection_traits Traversal_traits; Traversal_traits traversal_traits(out); this->traversal(query, traversal_traits); return out; } template template bool AABB_tree::any_intersection(const Query& query, Intersection_type& intersection) const { typedef First_intersection_traits Traversal_traits; Traversal_traits traversal_traits; this->traversal(query, traversal_traits); intersection = traversal_traits.result(); return traversal_traits.is_intersection_found(); } template typename AABB_tree::Projection_type AABB_tree::closest_point(const Projection_query& query, const Projection_type& hint) const { Projecting_traits traversal_traits(query,hint); this->traversal(query, traversal_traits); return traversal_traits.projection(); } } // end namespace CGAL #endif // CGAL_AABB_TREE_H