mirror of https://github.com/CGAL/cgal
Bug fix: fix AABB_tree doc and code about preconditions !empty()
The AABB_tree code had several assertions checkinng that the tree was not empty. Those preconditions were not documented. There was several places in the code were it was not really required that the tree is not empty. This patch rationalizes the preconditions: only the function `bbox()` and the queries about distances or closest things now require that the tree is not empty.
This commit is contained in:
parent
3b1ba8ba70
commit
fc3061c822
|
|
@ -169,7 +169,11 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
/// Returns the axis-aligned bounding box of the whole tree.
|
||||
const Bounding_box& bbox() const { return root_node()->bbox(); }
|
||||
/// \pre `!empty()`
|
||||
const Bounding_box& bbox() const {
|
||||
CGAL_precondition(!empty());
|
||||
return root_node()->bbox();
|
||||
}
|
||||
|
||||
/// Returns the number of primitives in the tree.
|
||||
size_type size() const { return m_primitives.size(); }
|
||||
|
|
@ -255,6 +259,7 @@ public:
|
|||
/// `accelerate_distance_queries()` should be called before the
|
||||
/// first distance query, so that an internal secondary search
|
||||
/// structure is build, for improving performance.
|
||||
/// \pre `!empty()`
|
||||
FT squared_distance(const Point& query) const;
|
||||
|
||||
/// Returns the point in the union of all input primitives which
|
||||
|
|
@ -264,6 +269,7 @@ public:
|
|||
/// called before the first distance query, so that an internal
|
||||
/// secondary search structure is build, for improving
|
||||
/// performance.
|
||||
/// \pre `!empty()`
|
||||
Point closest_point(const Point& query) const;
|
||||
|
||||
|
||||
|
|
@ -273,6 +279,7 @@ public:
|
|||
/// called before the first distance query, so that an internal
|
||||
/// secondary search structure is build, for improving
|
||||
/// performance.
|
||||
/// \pre `!empty()`
|
||||
Point_and_primitive_id closest_point_and_primitive(const Point& query) const;
|
||||
|
||||
|
||||
|
|
@ -357,17 +364,20 @@ public:
|
|||
|
||||
/// Returns the minimum squared distance between the query point
|
||||
/// and all input primitives. The internal KD-tree is not used.
|
||||
/// \pre `!empty()`
|
||||
FT squared_distance(const Point& query, const Point& hint) const;
|
||||
|
||||
/// Returns the point in the union of all input primitives which
|
||||
/// is closest to the query. In case there are several closest
|
||||
/// points, one arbitrarily chosen closest point is returned. The
|
||||
/// internal KD-tree is not used.
|
||||
/// \pre `!empty()`
|
||||
Point closest_point(const Point& query, const Point& hint) const;
|
||||
|
||||
/// Returns a `Point_and_primitive_id` which realizes the
|
||||
/// smallest distance between the query point and all input
|
||||
/// primitives. The internal KD-tree is not used.
|
||||
/// \pre `!empty()`
|
||||
Point_and_primitive_id closest_point_and_primitive(const Point& query, const Point_and_primitive_id& hint) const;
|
||||
|
||||
///@}
|
||||
|
|
@ -397,8 +407,6 @@ public:
|
|||
{
|
||||
if(!empty())
|
||||
root_node()->template traversal<Traversal_traits,Query>(query, traits, m_primitives.size());
|
||||
else
|
||||
std::cerr << "AABB tree traversal with empty tree" << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -526,21 +534,22 @@ public:
|
|||
{
|
||||
clear_nodes();
|
||||
|
||||
CGAL_assertion(m_primitives.size() > 1);
|
||||
if(m_primitives.size() > 1) {
|
||||
|
||||
// allocates tree nodes
|
||||
m_p_root_node = new Node[m_primitives.size()-1]();
|
||||
if(m_p_root_node == NULL)
|
||||
{
|
||||
std::cerr << "Unable to allocate memory for AABB tree" << std::endl;
|
||||
CGAL_assertion(m_p_root_node != NULL);
|
||||
m_primitives.clear();
|
||||
clear();
|
||||
// allocates tree nodes
|
||||
m_p_root_node = new Node[m_primitives.size()-1]();
|
||||
if(m_p_root_node == NULL)
|
||||
{
|
||||
std::cerr << "Unable to allocate memory for AABB tree" << std::endl;
|
||||
CGAL_assertion(m_p_root_node != NULL);
|
||||
m_primitives.clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
// constructs the tree
|
||||
m_p_root_node->expand(m_primitives.begin(), m_primitives.end(), m_primitives.size());
|
||||
}
|
||||
|
||||
// constructs the tree
|
||||
m_p_root_node->expand(m_primitives.begin(), m_primitives.end(), m_primitives.size());
|
||||
|
||||
// In case the users has switched on the acceletated distance query
|
||||
// data structure with the default arguments, then it has to be
|
||||
// rebuilt.
|
||||
|
|
@ -575,7 +584,7 @@ public:
|
|||
template<typename Tr>
|
||||
bool AABB_tree<Tr>::accelerate_distance_queries() const
|
||||
{
|
||||
CGAL_assertion(!m_primitives.empty());
|
||||
if(m_primitives.empty()) return true;
|
||||
#ifdef CGAL_HAS_THREADS
|
||||
//this ensures that this function will be done once
|
||||
boost::mutex::scoped_lock scoped_lock(kd_tree_mutex);
|
||||
|
|
@ -686,6 +695,7 @@ public:
|
|||
AABB_tree<Tr>::closest_point(const Point& query,
|
||||
const Point& hint) const
|
||||
{
|
||||
CGAL_precondition(!empty());
|
||||
typename Primitive::Id hint_primitive = m_primitives[0].id();
|
||||
using namespace CGAL::internal::AABB_tree;
|
||||
typedef typename AABB_tree<Tr>::AABB_traits AABBTraits;
|
||||
|
|
@ -700,6 +710,7 @@ public:
|
|||
typename AABB_tree<Tr>::Point
|
||||
AABB_tree<Tr>::closest_point(const Point& query) const
|
||||
{
|
||||
CGAL_precondition(!empty());
|
||||
const Point_and_primitive_id hint = best_hint(query);
|
||||
return closest_point(query,hint.first);
|
||||
}
|
||||
|
|
@ -710,6 +721,7 @@ public:
|
|||
AABB_tree<Tr>::squared_distance(const Point& query,
|
||||
const Point& hint) const
|
||||
{
|
||||
CGAL_precondition(!empty());
|
||||
const Point closest = this->closest_point(query, hint);
|
||||
return Tr().squared_distance_object()(query, closest);
|
||||
}
|
||||
|
|
@ -719,6 +731,7 @@ public:
|
|||
typename AABB_tree<Tr>::FT
|
||||
AABB_tree<Tr>::squared_distance(const Point& query) const
|
||||
{
|
||||
CGAL_precondition(!empty());
|
||||
const Point closest = this->closest_point(query);
|
||||
return Tr().squared_distance_object()(query, closest);
|
||||
}
|
||||
|
|
@ -728,6 +741,7 @@ public:
|
|||
typename AABB_tree<Tr>::Point_and_primitive_id
|
||||
AABB_tree<Tr>::closest_point_and_primitive(const Point& query) const
|
||||
{
|
||||
CGAL_precondition(!empty());
|
||||
return closest_point_and_primitive(query,best_hint(query));
|
||||
}
|
||||
|
||||
|
|
@ -737,6 +751,7 @@ public:
|
|||
AABB_tree<Tr>::closest_point_and_primitive(const Point& query,
|
||||
const Point_and_primitive_id& hint) const
|
||||
{
|
||||
CGAL_precondition(!empty());
|
||||
using namespace CGAL::internal::AABB_tree;
|
||||
typedef typename AABB_tree<Tr>::AABB_traits AABBTraits;
|
||||
Projection_traits<AABBTraits> projection_traits(hint.first,hint.second);
|
||||
|
|
@ -748,8 +763,8 @@ public:
|
|||
|
||||
#endif // CGAL_AABB_TREE_H
|
||||
|
||||
/***EMACS SETTINGS***/
|
||||
/* Local Variables: */
|
||||
/* tab-width: 2 */
|
||||
/* End: */
|
||||
|
||||
/***EMACS SETTINGS** */
|
||||
/* Local Variables: */
|
||||
/* tab-width: 2 */
|
||||
/* indent-tabs-mode: t */
|
||||
/* End: */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/AABB_segment_primitive.h>
|
||||
#include <cassert>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> K;
|
||||
|
||||
typedef K::FT FT;
|
||||
typedef K::Point_3 Point;
|
||||
typedef K::Plane_3 Plane;
|
||||
typedef K::Segment_3 Segment;
|
||||
typedef K::Triangle_3 Triangle;
|
||||
|
||||
typedef std::vector<Segment>::iterator Iterator;
|
||||
typedef CGAL::AABB_segment_primitive<K,Iterator> Primitive;
|
||||
typedef CGAL::AABB_traits<K, Primitive> Traits;
|
||||
typedef CGAL::AABB_tree<Traits> Tree;
|
||||
|
||||
int main()
|
||||
{
|
||||
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);
|
||||
|
||||
Tree tree;
|
||||
Plane plane_query(a,b,d);
|
||||
Triangle triangle_query(a,b,c);
|
||||
|
||||
// Test calls to all functions but those who have `!empty()` as
|
||||
// precondition.
|
||||
CGAL::Emptyset_iterator devnull;
|
||||
tree.accelerate_distance_queries();
|
||||
tree.all_intersections(triangle_query, devnull);
|
||||
tree.all_intersected_primitives(triangle_query, devnull);
|
||||
assert(!tree.any_intersected_primitive(triangle_query));
|
||||
assert(!tree.any_intersection(triangle_query));
|
||||
//Cannot call tree.bbox();
|
||||
tree.build();
|
||||
tree.clear();
|
||||
//Cannot call tree.closest_*(...)
|
||||
assert(tree.do_intersect(plane_query) == false);
|
||||
assert(tree.do_intersect(triangle_query) == false);
|
||||
assert(tree.empty());
|
||||
//Do not call tree.insert(...)
|
||||
assert(tree.number_of_intersected_primitives(plane_query) == 0);
|
||||
assert(tree.number_of_intersected_primitives(triangle_query) == 0);
|
||||
// Cannot call tree.rebuild(..)
|
||||
assert(tree.size() == 0);
|
||||
// Cannot call tree.squared_distance(..)
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
Reference in New Issue