Code is now almost up to the specification: Primitive::Id everywhere,

the KD-tree uses decorated points to return the Id too. 

There are just a few boost::optional to add in the traits, where we still
use the old bool intersection(..., Result&) approach, and some modernization 
to do in the distance computation things.

Everything compiles.

I have removed the funtion closest_primitive from the code and documentation, 
since it would not be consistent with the rest of the interface, and would not
be faster than closest_point_and_primitive.

I think we are almost done, not only for the documentation, but for the code too.
This commit is contained in:
Camille Wormser 2009-05-08 12:59:22 +00:00
parent 811f08256b
commit 01d0293bc5
5 changed files with 78 additions and 57 deletions

View File

@ -24,6 +24,6 @@ Intersections:
\item Function \ccc{any_intersection} detects and constructs the first encountered intersection and constructs the corresponding object. This function is fast as it stops at the first encountered intersection. \item Function \ccc{any_intersection} detects and constructs the first encountered intersection and constructs the corresponding object. This function is fast as it stops at the first encountered intersection.
\end{itemize} \end{itemize}
\paragraph{Distance.} An AABB tree computes the closest point from a given point query to the input primitives through the function \ccc{closest_point(query,hint)}. In addition, it can compute the id of the closest primitive from a given point query through the functions \ccc{closest_point_and_primitive(query,hint)} and \ccc{closest_primitive(query,hint)}, i.e., the id of the primitive which realizes the minimum distance from the point query. The latter function is a loose version of the former in the sense that it does not return the point on this primitive which is the closest. This is often sufficient in some applications to know which primitive is closer. The hint parameter, which can be omitted, provides a way to indicate an initial first guess. Although this hint can be chosen arbitrarily, the closer from the query the faster. The hint has the same type as the return type. In case a point is provided as a hint (or a point and a primitive), the point must lie on some primitive. Note that this is not always possible without an exact constructions kernel, if the hint is not a vertex. It may then happen that the hint is closer to the query than any of the primitives. In such a case, the hint is returned.\\ \paragraph{Distance.} An AABB tree computes the closest point from a given point query to the input primitives through the function \ccc{closest_point(query,hint)}. In addition, it can compute the id of the closest primitive from a given point query through the function \ccc{closest_point_and_primitive(query,hint)}, i.e., the id of the primitive which realizes the minimum distance from the point query. The hint parameter, which can be omitted, provides a way to indicate an initial first guess. Although this hint can be chosen arbitrarily, the closer from the query the faster. The hint has the same type as the return type. In case a point is provided as a hint (or a point and a primitive), the point must lie on some primitive. Note that this is not always possible without an exact constructions kernel, if the hint is not a vertex. It may then happen that the hint is closer to the query than any of the primitives. In such a case, the hint is returned.\\
In case the hint is omitted, the AABB tree provides the option to compute one closest hint point by using an internal KD-tree which contains a point sampling of the primitives. This option, which increases the performances is activated if, and only if the construction of the KD-tree has been requested by a call to one of the two \ccc{accelerate_distance_queries} methods. Note that, by default, the method \ccc{reference_point} of the primitives is used to generate the point sampling. However, the user may prefer to provide the point sampling with \ccc{accelerate_distance_queries(InputIterator begin, InputIterator beyond)} rather than relying on the default one which takes one reference point per primitive. If some triangles are very large, it helps inserting more than one sample on these large triangles. Conversely, a sparser sampling with less than one point per primitive is relevant in some cases. For the case where the primitives are the faces of a triangle surface mesh the specified point sampling may be provided as the vertex points of the mesh vertices. In case the hint is omitted, the AABB tree provides the option to compute one closest hint point by using an internal KD-tree which contains a point sampling of the primitives. This option, which increases the performances is activated if, and only if the construction of the KD-tree has been requested by a call to one of the two \ccc{accelerate_distance_queries} methods. Note that, by default, the method \ccc{reference_point} of the primitives is used to generate the point sampling. However, the user may prefer to provide the point sampling with \ccc{accelerate_distance_queries(InputIterator begin, InputIterator beyond)} rather than relying on the default one which takes one reference point per primitive. If some triangles are very large, it helps inserting more than one sample on these large triangles. Conversely, a sparser sampling with less than one point per primitive is relevant in some cases. For the case where the primitives are the faces of a triangle surface mesh the specified point sampling may be provided as the vertex points of the mesh vertices.

View File

@ -130,11 +130,6 @@ closest_point(const Point& query,
const Point& hint);} const Point& hint);}
{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. ÊParameter \ccc{hint} is assumed to be any point located on the input primitives (the closer \ccc{hint} to \ccc{query}, the faster). If \ccc{hint} is closer to \ccc{query} than any of the primitives, \ccc{hint} is returned. Parameter \ccc{hint} can be omitted. If the internal KD-tree data structure has been constructed using function \ccc{accelerate_distance_queries} (see below), it is used to efficiently query the nearest hint point from the query, among a set of hint points stored in the internal KD-tree. Otherwise, the first primitive reference point is chosen as a naive hint point.} {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. ÊParameter \ccc{hint} is assumed to be any point located on the input primitives (the closer \ccc{hint} to \ccc{query}, the faster). If \ccc{hint} is closer to \ccc{query} than any of the primitives, \ccc{hint} is returned. Parameter \ccc{hint} can be omitted. If the internal KD-tree data structure has been constructed using function \ccc{accelerate_distance_queries} (see below), it is used to efficiently query the nearest hint point from the query, among a set of hint points stored in the internal KD-tree. Otherwise, the first primitive reference point is chosen as a naive hint point.}
\ccMethod{Primitive::Id
closest_primitive(const Point& query,
const Primitive::Id& hint);}
{Returns the id of the primitive which realizes the smallest distance between the query point and all input primitives. Parameter \ccc{hint} is assumed to be the id of any input primitive (the closer \ccc{hint} to \ccc{query}, the faster). Parameter \ccc{hint} can be omitted. If the internal KD-tree data structure has been constructed using function \ccc{accelerate_distance_queries} (see below), it is used to efficiently query the nearest hint primitive from the query, among a set of hint primitives stored in the internal KD-tree. Otherwise, the first primitive is chosen as a naive hint.}
\ccMethod{Point_and_primitive_id \ccMethod{Point_and_primitive_id
closest_point_and_primitive(const Point& query, closest_point_and_primitive(const Point& query,
const Point_and_primitive_id& hint);} const Point_and_primitive_id& hint);}

View File

@ -25,29 +25,58 @@
namespace CGAL namespace CGAL
{ {
template <class Underlying, class Id>
class Add_decorated_point: public Underlying
{
class Decorated_point: public Underlying::Point_3
{
public:
Id id;
Decorated_point(): Underlying::Point_3(), id(){}
// Allows the user not to provide the id
// so that we don't break existing code
Decorated_point(const typename Underlying::Point_3& p): Underlying::Point_3(p), id(){}
};
public:
typedef Decorated_point Point_3;
};
template <class Traits> template <class Traits>
class AABB_search_tree class AABB_search_tree
{ {
public: public:
typedef typename Traits::FT FT; typedef typename Traits::FT FT;
typedef typename Traits::Point_3 Point; typedef typename Traits::Point_3 Point;
typedef typename CGAL::Search_traits_3<Traits> TreeTraits; typedef typename Traits::Point_and_primitive_id Point_and_primitive_id;
typedef typename CGAL::Search_traits_3<Add_decorated_point<Traits, typename Traits::Primitive::Id> > 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:
template <class ConstPointIterator> template <class ConstPointIterator>
AABB_search_tree(ConstPointIterator begin, ConstPointIterator beyond): AABB_search_tree(ConstPointIterator begin, ConstPointIterator beyond)
m_tree(begin, beyond){} {
typedef typename Add_decorated_point<Traits, typename Traits::Primitive::Id>::Point_3 Decorated_point;
std::vector<Decorated_point> points;
while(begin != beyond) {
points.push_back(Decorated_point(begin->first));
points.back().id = begin->second;
++begin;
}
m_tree = new Tree(points.begin(), points.end());
}
~AABB_search_tree() {} ~AABB_search_tree() {
delete m_tree;
}
// TOFIX: make it const // TOFIX: make it const
Point closest_point(const Point& query) Point_and_primitive_id closest_point(const Point& query)
{ {
Neighbor_search search(m_tree, query, 1); typedef typename Add_decorated_point<Traits, typename Traits::Primitive::Id>::Point_3 Decorated_point;
return search.begin()->first; Neighbor_search search(*m_tree, query, 1);
return Point_and_primitive_id(static_cast<Point>(search.begin()->first), search.begin()->first.id);
} }
}; };

View File

@ -55,8 +55,8 @@ public:
typedef typename GeomTraits::Point_3::Point Point; typedef typename GeomTraits::Point_3::Point Point;
#endif #endif
typedef typename std::pair<Object,Primitive> Object_and_primitive; typedef typename std::pair<Object,typename Primitive::Id> Object_and_primitive_id;
typedef typename std::pair<Point,Primitive> Point_and_primitive; typedef typename std::pair<Point,typename Primitive::Id> Point_and_primitive_id;
// types for search tree // types for search tree
// TOFIX: how can we avoid repeating those? // TOFIX: how can we avoid repeating those?
@ -128,7 +128,7 @@ public:
template<typename Query> template<typename Query>
bool intersection(const Query& q, bool intersection(const Query& q,
const Primitive& pr, const Primitive& pr,
Object_and_primitive& result) const; Object_and_primitive_id& result) const;
Sphere sphere(const Point& center, Sphere sphere(const Point& center,
const Point& hint) const const Point& hint) const
@ -215,7 +215,7 @@ template<typename Query>
bool bool
AABB_traits<GT,P>::intersection(const Query& query, AABB_traits<GT,P>::intersection(const Query& query,
const P& primitive, const P& primitive,
Object_and_primitive& result) const Object_and_primitive_id& result) const
{ {
// TODO: implement a real intersection construction method // TODO: implement a real intersection construction method
// do_intersect is needed here because we construct intersection between // do_intersect is needed here because we construct intersection between

View File

@ -43,8 +43,8 @@ namespace CGAL {
typedef typename AABBTraits::Primitive Primitive; typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Size_type Size_type; typedef typename AABBTraits::Size_type Size_type;
typedef typename AABBTraits::Bounding_box Bounding_box; typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Point_and_primitive Point_and_primitive; typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive Object_and_primitive; typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
private: private:
// internal KD-tree used to accelerate the distance queries // internal KD-tree used to accelerate the distance queries
@ -118,19 +118,17 @@ namespace CGAL {
// any intersection // any intersection
template <typename Query> template <typename Query>
boost::optional<Primitive> any_intersected_primitive(const Query& query) const; boost::optional<typename Primitive::Id> any_intersected_primitive(const Query& query) const;
template <typename Query> template <typename Query>
boost::optional<Object_and_primitive> any_intersection(const Query& query) const; boost::optional<Object_and_primitive_id> any_intersection(const Query& query) const;
// distance queries // distance queries
FT squared_distance(const Point& query) const; FT squared_distance(const Point& query) const;
FT squared_distance(const Point& query, const Point& hint) const; FT squared_distance(const Point& query, const Point& hint) const;
Point closest_point(const Point& query); Point closest_point(const Point& query);
Point closest_point(const Point& query, const Point& hint); Point closest_point(const Point& query, const Point& hint);
Primitive closest_primitive(const Point& query) const; Point_and_primitive_id closest_point_and_primitive(const Point& query) const;
Primitive closest_primitive(const Point& query, const Point& hint) const; Point_and_primitive_id closest_point_and_primitive(const Point& query, const Point_and_primitive_id& hint) const;
Point_and_primitive closest_point_and_primitive(const Point& query) const;
Point_and_primitive closest_point_and_primitive(const Point& query, const Point& hint) const;
private: private:
@ -168,7 +166,7 @@ namespace CGAL {
class First_intersection_traits class First_intersection_traits
{ {
public: public:
typedef typename boost::optional<Object_and_primitive> Result; typedef typename boost::optional<Object_and_primitive_id> Result;
public: public:
First_intersection_traits() First_intersection_traits()
: m_is_found(false) : m_is_found(false)
@ -178,7 +176,7 @@ namespace CGAL {
void intersection(const Query& query, const Primitive& primitive) void intersection(const Query& query, const Primitive& primitive)
{ {
Object_and_primitive op; Object_and_primitive_id op;
m_is_found = AABBTraits().intersection(query, primitive, op); m_is_found = AABBTraits().intersection(query, primitive, op);
if(m_is_found) if(m_is_found)
m_result = Result(op); m_result = Result(op);
@ -240,14 +238,13 @@ namespace CGAL {
{ {
public: public:
Listing_intersection_traits(Output_iterator out_it) Listing_intersection_traits(Output_iterator out_it)
: m_intersection() : m_out_it(out_it) {}
, m_out_it(out_it) {}
bool go_further() const { return true; } bool go_further() const { return true; }
void intersection(const Query& query, const Primitive& primitive) void intersection(const Query& query, const Primitive& primitive)
{ {
Object_and_primitive intersection; Object_and_primitive_id intersection;
if( AABBTraits().intersection(query, primitive, intersection) ) if( AABBTraits().intersection(query, primitive, intersection) )
{ {
*m_out_it++ = intersection; *m_out_it++ = intersection;
@ -280,7 +277,7 @@ namespace CGAL {
{ {
if( AABBTraits().do_intersect(query, primitive) ) if( AABBTraits().do_intersect(query, primitive) )
{ {
*m_out_it++ = primitive; *m_out_it++ = primitive.id();
} }
} }
@ -311,7 +308,7 @@ namespace CGAL {
{ {
if( AABBTraits().do_intersect(query, primitive) ) if( AABBTraits().do_intersect(query, primitive) )
{ {
m_result = boost::optional<Primitive>(primitive); m_result = boost::optional<typename Primitive::Id>(primitive.id());
m_is_found = true; m_is_found = true;
} }
} }
@ -321,12 +318,12 @@ namespace CGAL {
return AABBTraits().do_intersect(query, node.bbox()); return AABBTraits().do_intersect(query, node.bbox());
} }
boost::optional<Primitive> result() const { return m_result; } boost::optional<typename Primitive::Id> result() const { return m_result; }
bool is_intersection_found() const { return m_is_found; } bool is_intersection_found() const { return m_is_found; }
private: private:
bool m_is_found; bool m_is_found;
boost::optional<Primitive> m_result; boost::optional<typename Primitive::Id> m_result;
}; };
/** /**
@ -337,7 +334,7 @@ namespace CGAL {
public: public:
Distance_traits(const Point& query, Distance_traits(const Point& query,
const Point& hint, const Point& hint,
const Primitive& hint_primitive) const typename Primitive::Id& hint_primitive)
: m_closest_point(hint), : m_closest_point(hint),
m_closest_primitive(hint_primitive), m_closest_primitive(hint_primitive),
m_sphere(AABBTraits().sphere(query,hint)) m_sphere(AABBTraits().sphere(query,hint))
@ -353,7 +350,7 @@ namespace CGAL {
AABBTraits().closest_point(query, primitive, m_closest_point); AABBTraits().closest_point(query, primitive, m_closest_point);
if(new_closest_point != m_closest_point) if(new_closest_point != m_closest_point)
{ {
m_closest_primitive = primitive; m_closest_primitive = primitive.id();
m_closest_point = new_closest_point; m_closest_point = new_closest_point;
} }
m_sphere = AABBTraits().sphere(query, m_closest_point); m_sphere = AABBTraits().sphere(query, m_closest_point);
@ -365,29 +362,29 @@ namespace CGAL {
} }
Point closest_point() const { return m_closest_point; } Point closest_point() const { return m_closest_point; }
Primitive closest_primitive() const { return m_closest_primitive; } typename Primitive::Id closest_primitive() const { return m_closest_primitive; }
private: private:
Sphere m_sphere; Sphere m_sphere;
Point m_closest_point; Point m_closest_point;
Primitive m_closest_primitive; typename Primitive::Id m_closest_primitive;
}; };
private: private:
// returns a point guaranteed to be on one primitive // returns a point guaranteed to be on one primitive
Point any_reference_point() Point_and_primitive_id any_reference_point_and_id()
{ {
CGAL_assertion(!empty()); CGAL_assertion(!empty());
return m_data[0].reference_point(); return Point_and_primitive_id(m_data[0].reference_point(), m_data[0].id());
} }
public: public:
Point best_hint(const Point& query) Point_and_primitive_id best_hint(const Point& query)
{ {
if(m_search_tree_constructed) if(m_search_tree_constructed)
return m_p_search_tree->closest_point(query); return m_p_search_tree->closest_point(query);
else else
return this->any_reference_point(); return this->any_reference_point_and_id();
} }
private: private:
@ -494,10 +491,10 @@ namespace CGAL {
CGAL_assertion(!m_data.empty()); CGAL_assertion(!m_data.empty());
// iterate over primitives to get reference points on them // iterate over primitives to get reference points on them
std::vector<Point> points; std::vector<Point_and_primitive_id> points;
typename std::vector<Primitive>::const_iterator it; typename 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)
points.push_back(it->reference_point()); points.push_back(Point_and_primitive_id(it->reference_point(), it->id()));
return accelerate_distance_queries(points.begin(), points.end()); return accelerate_distance_queries(points.begin(), points.end());
} }
@ -546,7 +543,7 @@ namespace CGAL {
template <typename Tr> template <typename Tr>
template <typename Query> template <typename Query>
boost::optional<typename Tr::Object_and_primitive> boost::optional<typename AABB_tree<Tr>::Object_and_primitive_id>
AABB_tree<Tr>::any_intersection(const Query& query) const AABB_tree<Tr>::any_intersection(const Query& query) const
{ {
First_intersection_traits<Query> traversal_traits; First_intersection_traits<Query> traversal_traits;
@ -556,7 +553,7 @@ namespace CGAL {
template <typename Tr> template <typename Tr>
template <typename Query> template <typename Query>
boost::optional<typename Tr::Primitive> boost::optional<typename AABB_tree<Tr>::Primitive::Id>
AABB_tree<Tr>::any_intersected_primitive(const Query& query) const AABB_tree<Tr>::any_intersected_primitive(const Query& query) const
{ {
First_primitive_traits<Query> traversal_traits; First_primitive_traits<Query> traversal_traits;
@ -570,7 +567,7 @@ namespace CGAL {
AABB_tree<Tr>::closest_point(const Point& query, AABB_tree<Tr>::closest_point(const Point& query,
const Point& hint) const Point& hint)
{ {
Primitive hint_primitive = m_data[0]; typename Primitive::Id hint_primitive = m_data[0].id();
Distance_traits distance_traits(query,hint,hint_primitive); Distance_traits distance_traits(query,hint,hint_primitive);
this->traversal(query, distance_traits); this->traversal(query, distance_traits);
return distance_traits.closest_point(); return distance_traits.closest_point();
@ -582,8 +579,8 @@ namespace CGAL {
typename AABB_tree<Tr>::Point typename AABB_tree<Tr>::Point
AABB_tree<Tr>::closest_point(const Point& query) AABB_tree<Tr>::closest_point(const Point& query)
{ {
const Point hint = best_hint(query); const Point_and_primitive_id hint = best_hint(query);
return closest_point(query,hint); return closest_point(query,hint.first);
} }
// squared distance with user-specified hint // squared distance with user-specified hint
@ -607,20 +604,20 @@ namespace CGAL {
// closest point with user-specified hint // closest point with user-specified hint
template<typename Tr> template<typename Tr>
typename AABB_tree<Tr>::Primitive typename AABB_tree<Tr>::Point_and_primitive_id
AABB_tree<Tr>::closest_primitive(const Point& query) const AABB_tree<Tr>::closest_point_and_primitive(const Point& query) const
{ {
return closest_primitive(query,best_hint(query)); return closest_primitive(query,best_hint(query));
} }
// closest point with user-specified hint // closest point with user-specified hint
template<typename Tr> template<typename Tr>
typename AABB_tree<Tr>::Primitive typename AABB_tree<Tr>::Point_and_primitive_id
AABB_tree<Tr>::closest_primitive(const Point& query, AABB_tree<Tr>::closest_point_and_primitive(const Point& query,
const Point& hint) const const Point_and_primitive_id& hint) const
{ {
const Point hint = best_hint(query); // const Point hint = best_hint(query);
Distance_traits distance_traits(query,hint,any_primitive()); Distance_traits distance_traits(query,hint.first,hint.second);
this->traversal(query, distance_traits); this->traversal(query, distance_traits);
return distance_traits.closest_primitive(); return distance_traits.closest_primitive();
} }