mirror of https://github.com/CGAL/cgal
use a traversal traits instead of a pseudo model of AABBTraits
This commit is contained in:
parent
d7e7c74782
commit
df15af614d
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright (c) 2018 GeometryFactory (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
|
|
@ -19,6 +18,7 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Maxime Gimeno
|
||||
// Sebastien Loriot
|
||||
//
|
||||
|
||||
#ifndef CGAL_AABB_DO_INTERSECT_TRANSFORM_TRAITS_H
|
||||
|
|
@ -38,204 +38,263 @@
|
|||
#include <CGAL/Aff_transformation_3.h>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
/// \file AABB_do_intersect_transform_traits.h
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<typename Kernel, typename AABBPrimitive,
|
||||
typename SUPPORTS_ROTATION = CGAL::Tag_true>
|
||||
class AABB_do_intersect_transform_traits:
|
||||
public AABB_traits<Kernel, AABBPrimitive>
|
||||
template<typename AABBTraits, typename Kernel, class SUPPORTS_ROTATION>
|
||||
class Traversal_traits_with_transformation_helper
|
||||
{
|
||||
mutable Aff_transformation_3<Kernel> m_transfo;
|
||||
mutable bool has_rotation;
|
||||
typedef AABB_traits<Kernel, AABBPrimitive> BaseTraits;
|
||||
typedef AABB_do_intersect_transform_traits<Kernel, AABBPrimitive, SUPPORTS_ROTATION> Self;
|
||||
|
||||
void set_transformation(const Aff_transformation_3<Kernel>& trans, CGAL::Tag_true) const
|
||||
{
|
||||
has_rotation = (trans.m(0,1) != 0
|
||||
|| trans.m(0,2) != 0
|
||||
|| trans.m(1,0) != 0
|
||||
|| trans.m(1,2) != 0
|
||||
|| trans.m(2,0) != 0
|
||||
|| trans.m(2,1) !=0);
|
||||
}
|
||||
void set_transformation(const Aff_transformation_3<Kernel>& trans, CGAL::Tag_false) const
|
||||
{}
|
||||
Bbox_3
|
||||
compute_transformed_bbox_impl(const Bbox_3& bbox, Tag_true) const
|
||||
compute_transformed_bbox_impl(const CGAL::Aff_transformation_3<Kernel>& at,
|
||||
const Bbox_3& bbox,
|
||||
bool has_rotation,
|
||||
/*SUPPORTS_ROTATION*/ Tag_true) const
|
||||
{
|
||||
CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD);
|
||||
|
||||
if(!has_rotation)
|
||||
return compute_transformed_bbox_impl(bbox, Tag_false());
|
||||
return compute_transformed_bbox_impl(at, bbox, has_rotation, Tag_false());
|
||||
|
||||
typedef Simple_cartesian<Interval_nt_advanced> AK;
|
||||
typedef Cartesian_converter<Kernel, AK> C2F;
|
||||
C2F c2f;
|
||||
|
||||
AK::Aff_transformation_3 af = c2f(m_transfo);
|
||||
AK::Aff_transformation_3 a_at = c2f(at);
|
||||
|
||||
AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)),
|
||||
c2f(bbox.min(1)), c2f(bbox.max(1)),
|
||||
c2f(bbox.min(2)), c2f(bbox.max(2)) };
|
||||
|
||||
typename AK::Point_3 ps[8];
|
||||
ps[0] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) );
|
||||
ps[1] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[5]) );
|
||||
ps[2] = af( AK::Point_3(xtrm[0], xtrm[3], xtrm[4]) );
|
||||
ps[3] = af( AK::Point_3(xtrm[0], xtrm[3], xtrm[5]) );
|
||||
ps[0] = a_at( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) );
|
||||
ps[1] = a_at( AK::Point_3(xtrm[0], xtrm[2], xtrm[5]) );
|
||||
ps[2] = a_at( AK::Point_3(xtrm[0], xtrm[3], xtrm[4]) );
|
||||
ps[3] = a_at( AK::Point_3(xtrm[0], xtrm[3], xtrm[5]) );
|
||||
|
||||
ps[4] = af( AK::Point_3(xtrm[1], xtrm[2], xtrm[4]) );
|
||||
ps[5] = af( AK::Point_3(xtrm[1], xtrm[2], xtrm[5]) );
|
||||
ps[6] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[4]) );
|
||||
ps[7] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) );
|
||||
ps[4] = a_at( AK::Point_3(xtrm[1], xtrm[2], xtrm[4]) );
|
||||
ps[5] = a_at( AK::Point_3(xtrm[1], xtrm[2], xtrm[5]) );
|
||||
ps[6] = a_at( AK::Point_3(xtrm[1], xtrm[3], xtrm[4]) );
|
||||
ps[7] = a_at( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) );
|
||||
|
||||
return bbox_3(ps, ps+8);
|
||||
}
|
||||
|
||||
Bbox_3
|
||||
compute_transformed_bbox_impl(const Bbox_3& bbox, Tag_false) const
|
||||
compute_transformed_bbox_impl(const CGAL::Aff_transformation_3<Kernel>& at,
|
||||
const Bbox_3& bbox,
|
||||
bool,
|
||||
/*SUPPORTS_ROTATION*/ Tag_false) const
|
||||
{
|
||||
CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD);
|
||||
|
||||
typedef Simple_cartesian<Interval_nt_advanced > AK;
|
||||
typedef Cartesian_converter<Kernel, AK> C2F;
|
||||
C2F c2f;
|
||||
|
||||
AK::Aff_transformation_3 af = c2f(m_transfo);
|
||||
AK::Aff_transformation_3 a_at = c2f(at);
|
||||
|
||||
AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)),
|
||||
c2f(bbox.min(1)), c2f(bbox.max(1)),
|
||||
c2f(bbox.min(2)), c2f(bbox.max(2)) };
|
||||
|
||||
typename AK::Point_3 ps[2];
|
||||
ps[0] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) );
|
||||
ps[1] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) );
|
||||
ps[0] = a_at( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) );
|
||||
ps[1] = a_at( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) );
|
||||
|
||||
return bbox_3(ps, ps+2);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//Constructor
|
||||
AABB_do_intersect_transform_traits(const Aff_transformation_3<Kernel>& transf = Aff_transformation_3<Kernel>(IDENTITY))
|
||||
bool has_rotation(const CGAL::Aff_transformation_3<Kernel>& at) const
|
||||
{
|
||||
has_rotation = false;
|
||||
set_transformation(transf, SUPPORTS_ROTATION());
|
||||
return ( at.m(0,1) != 0 || at.m(0,2) != 0 || at.m(1,0) != 0
|
||||
|| at.m(1,2) != 0 || at.m(2,0) != 0 || at.m(2,1) !=0);
|
||||
}
|
||||
|
||||
// AABBTraits concept types
|
||||
typedef typename BaseTraits::Point_3 Point_3;
|
||||
typedef typename BaseTraits::Primitive Primitive;
|
||||
typedef typename BaseTraits::Bounding_box Bounding_box;
|
||||
Bbox_3
|
||||
compute_transformed_bbox(const CGAL::Aff_transformation_3<Kernel>& at,
|
||||
const Bbox_3& bbox,
|
||||
bool has_rotation) const
|
||||
{
|
||||
return compute_transformed_bbox_impl(at, bbox, has_rotation, SUPPORTS_ROTATION());
|
||||
}
|
||||
};
|
||||
|
||||
// helper functions
|
||||
// traversal traits for a tree vs a primitive
|
||||
template<typename AABBTraits, typename Kernel,
|
||||
typename SUPPORTS_ROTATION = CGAL::Tag_true>
|
||||
class Do_intersect_traversal_traits_with_transformation
|
||||
: public Traversal_traits_with_transformation_helper<AABBTraits, Kernel, SUPPORTS_ROTATION>
|
||||
{
|
||||
typedef typename AABBTraits::Primitive Primitive;
|
||||
typedef ::CGAL::AABB_node<AABBTraits> Node;
|
||||
typedef Traversal_traits_with_transformation_helper<AABBTraits, Kernel, SUPPORTS_ROTATION> Base;
|
||||
|
||||
void register_transformation(CGAL::Tag_true)
|
||||
{
|
||||
m_has_rotation = this->has_rotation(m_transfo);
|
||||
}
|
||||
|
||||
void register_transformation(CGAL::Tag_false)
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
Do_intersect_traversal_traits_with_transformation(const AABBTraits& traits)
|
||||
: m_is_found(false), m_traits(traits), m_has_rotation(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool go_further() const { return !m_is_found; }
|
||||
|
||||
template <class Query>
|
||||
void intersection(const Query& query, const Primitive& primitive)
|
||||
{
|
||||
if( CGAL::do_intersect(query,
|
||||
internal::Primitive_helper<AABBTraits>::get_datum(primitive, m_traits).transform(m_transfo)) )
|
||||
m_is_found = true;
|
||||
}
|
||||
|
||||
template <class Query>
|
||||
bool do_intersect(const Query& query, const Node& node) const
|
||||
{
|
||||
return m_traits.do_intersect_object()(query, compute_transformed_bbox(node.bbox()));
|
||||
}
|
||||
|
||||
bool is_intersection_found() const { return m_is_found; }
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_is_found = false;
|
||||
}
|
||||
|
||||
const Aff_transformation_3<Kernel>&
|
||||
transformation() const
|
||||
{
|
||||
return m_transfo;
|
||||
}
|
||||
|
||||
void set_transformation(const Aff_transformation_3<Kernel>& transfo)
|
||||
{
|
||||
m_transfo = transfo;
|
||||
register_transformation(SUPPORTS_ROTATION());
|
||||
}
|
||||
|
||||
|
||||
Bbox_3
|
||||
compute_transformed_bbox(const Bbox_3& bbox) const
|
||||
{
|
||||
return compute_transformed_bbox_impl(bbox, SUPPORTS_ROTATION());
|
||||
return Base::compute_transformed_bbox(m_transfo, bbox, m_has_rotation);
|
||||
}
|
||||
|
||||
// Do_intersect predicate
|
||||
class Do_intersect
|
||||
: BaseTraits::Do_intersect
|
||||
// helper for Point_inside_vertical_ray_cast
|
||||
class Transformed_tree_helper
|
||||
{
|
||||
typedef AABB_do_intersect_transform_traits<Kernel, AABBPrimitive, SUPPORTS_ROTATION> AABBTraits;
|
||||
const AABBTraits& m_traits;
|
||||
typedef typename BaseTraits::Do_intersect Base;
|
||||
typedef AABB_tree<AABBTraits> Tree;
|
||||
typedef CGAL::AABB_node<AABBTraits> Node;
|
||||
typedef Do_intersect_traversal_traits_with_transformation<AABBTraits, Kernel, SUPPORTS_ROTATION> Traversal_traits;
|
||||
|
||||
Bounding_box
|
||||
compute_transformed_bbox(const Bounding_box& bbox) const
|
||||
{
|
||||
return m_traits.compute_transformed_bbox(bbox);
|
||||
}
|
||||
Traversal_traits m_tt;
|
||||
|
||||
public:
|
||||
Do_intersect(const AABBTraits& traits)
|
||||
: Base(static_cast<const BaseTraits&>(traits)),
|
||||
m_traits(traits)
|
||||
|
||||
Transformed_tree_helper(const Traversal_traits& tt)
|
||||
: m_tt(tt)
|
||||
{}
|
||||
|
||||
template<typename Query>
|
||||
bool operator()(const Query& q, const Bounding_box& bbox) const
|
||||
Bbox_3 get_tree_bbox(const AABB_tree<AABBTraits>& tree) const
|
||||
{
|
||||
return
|
||||
static_cast<const Base*>(this)->operator()(
|
||||
q, compute_transformed_bbox(bbox));
|
||||
return m_tt.compute_transformed_bbox(tree.bbox());
|
||||
}
|
||||
|
||||
template<typename Query>
|
||||
bool operator()(const Query& q, const Primitive& pr) const
|
||||
typename AABBTraits::Primitive::Datum
|
||||
get_primitive_datum(const typename AABBTraits::Primitive& primitive, const AABBTraits& traits) const
|
||||
{
|
||||
// transformation is done within Primitive_helper
|
||||
return do_intersect(q, internal::Primitive_helper<Self>::get_datum(pr,m_traits));
|
||||
return internal::Primitive_helper<AABBTraits>::get_datum(primitive, traits).transform(m_tt.transformation());
|
||||
}
|
||||
|
||||
// intersection with AABB-tree
|
||||
template<typename AABBTraits>
|
||||
bool operator()(const CGAL::AABB_tree<AABBTraits>& other_tree, const Primitive& pr) const
|
||||
Bbox_3 get_node_bbox(const Node& node) const
|
||||
{
|
||||
// transformation is done within Primitive_helper
|
||||
return other_tree.do_intersect( internal::Primitive_helper<Self>::get_datum(pr,m_traits));
|
||||
}
|
||||
|
||||
template<typename AABBTraits>
|
||||
bool operator()(const CGAL::AABB_tree<AABBTraits>& other_tree, const Bounding_box& bbox) const
|
||||
{
|
||||
return other_tree.do_intersect(compute_transformed_bbox(bbox));
|
||||
return m_tt.compute_transformed_bbox(node.bbox());
|
||||
}
|
||||
};
|
||||
|
||||
Do_intersect do_intersect_object() const{
|
||||
return Do_intersect(*this);
|
||||
}
|
||||
|
||||
//Specific
|
||||
void set_transformation(const Aff_transformation_3<Kernel>& trans) const
|
||||
Transformed_tree_helper get_helper() const
|
||||
{
|
||||
m_transfo = trans;
|
||||
set_transformation(trans, SUPPORTS_ROTATION());
|
||||
return Transformed_tree_helper(*this);
|
||||
}
|
||||
|
||||
const Aff_transformation_3<Kernel>& transformation() const { return m_transfo; }
|
||||
private:
|
||||
bool m_is_found;
|
||||
const AABBTraits& m_traits;
|
||||
Aff_transformation_3<Kernel> m_transfo;
|
||||
bool m_has_rotation;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename K, typename P, typename T>
|
||||
struct Primitive_helper<AABB_do_intersect_transform_traits<K,P,T> ,true>{
|
||||
|
||||
typedef AABB_do_intersect_transform_traits<K,P,T> Traits;
|
||||
|
||||
|
||||
static typename Traits::Primitive::Datum get_datum(const typename Traits::Primitive& p,
|
||||
const Traits & traits)
|
||||
// traversal traits for a tree
|
||||
template<typename AABBTraits, class Kernel, typename SUPPORTS_ROTATION = CGAL::Tag_true >
|
||||
class Do_intersect_traversal_traits_for_two_trees
|
||||
: public Traversal_traits_with_transformation_helper<AABBTraits, Kernel, SUPPORTS_ROTATION>
|
||||
{
|
||||
return p.datum(traits.shared_data()).transform(traits.transformation());
|
||||
}
|
||||
typedef typename AABBTraits::Primitive Primitive;
|
||||
typedef ::CGAL::AABB_node<AABBTraits> Node;
|
||||
typedef Traversal_traits_with_transformation_helper<AABBTraits, Kernel, SUPPORTS_ROTATION> Base;
|
||||
|
||||
static typename Traits::Point_3 get_reference_point(const typename Traits::Primitive& p,const Traits& traits) {
|
||||
return p.reference_point(traits.shared_data()).transform(traits.transformation());
|
||||
}
|
||||
void register_transformation(CGAL::Tag_true)
|
||||
{
|
||||
m_has_rotation = this->has_rotation(m_transfo);
|
||||
}
|
||||
|
||||
void register_transformation(CGAL::Tag_false)
|
||||
{}
|
||||
|
||||
Bbox_3
|
||||
compute_transformed_bbox(const Bbox_3& bbox) const
|
||||
{
|
||||
return Base::compute_transformed_bbox(m_transfo, bbox, m_has_rotation);
|
||||
}
|
||||
|
||||
public:
|
||||
Do_intersect_traversal_traits_for_two_trees(const AABBTraits& traits,
|
||||
const Aff_transformation_3<Kernel>& transfo,
|
||||
Do_intersect_traversal_traits_with_transformation<AABBTraits, Kernel, SUPPORTS_ROTATION>& query_traversal_traits)
|
||||
: m_is_found(false)
|
||||
, m_traits(traits)
|
||||
, m_transfo(transfo)
|
||||
, m_has_rotation(false)
|
||||
, m_query_traversal_traits(query_traversal_traits)
|
||||
|
||||
{
|
||||
register_transformation(SUPPORTS_ROTATION());
|
||||
}
|
||||
|
||||
bool go_further() const { return !m_is_found; }
|
||||
|
||||
void intersection(const AABB_tree<AABBTraits>& query, const Primitive& primitive)
|
||||
{
|
||||
query.traversal( internal::Primitive_helper<AABBTraits>::get_datum(primitive,m_traits).transform(m_transfo), m_query_traversal_traits );
|
||||
m_is_found = m_query_traversal_traits.is_intersection_found();
|
||||
m_query_traversal_traits.reset();
|
||||
}
|
||||
|
||||
bool do_intersect(const AABB_tree<AABBTraits>& query, const Node& node) const
|
||||
{
|
||||
query.traversal( compute_transformed_bbox(node.bbox()), m_query_traversal_traits );
|
||||
bool res = m_query_traversal_traits.is_intersection_found();
|
||||
m_query_traversal_traits.reset();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_intersection_found() const { return m_is_found; }
|
||||
|
||||
private:
|
||||
bool m_is_found;
|
||||
const AABBTraits& m_traits;
|
||||
const Aff_transformation_3<Kernel>& m_transfo;
|
||||
bool m_has_rotation;
|
||||
Do_intersect_traversal_traits_with_transformation<AABBTraits, Kernel, SUPPORTS_ROTATION>& m_query_traversal_traits;
|
||||
};
|
||||
|
||||
template<typename K, typename P, typename T>
|
||||
typename CGAL::AABB_tree<AABB_do_intersect_transform_traits<K,P,T> >::Bounding_box
|
||||
get_tree_bbox(const CGAL::AABB_tree<AABB_do_intersect_transform_traits<K,P,T> >& tree)
|
||||
{
|
||||
return tree.traits().compute_transformed_bbox(tree.bbox());
|
||||
}
|
||||
|
||||
template<typename K, typename P, typename T>
|
||||
typename CGAL::AABB_tree<AABB_do_intersect_transform_traits<K,P,T> >::Bounding_box
|
||||
get_node_bbox(const CGAL::AABB_node<AABB_do_intersect_transform_traits<K,P,T> >& node,
|
||||
const AABB_do_intersect_transform_traits<K,P,T>& traits)
|
||||
{
|
||||
return traits.compute_transformed_bbox(node.bbox());
|
||||
}
|
||||
|
||||
} // end internal
|
||||
|
||||
}//end CGAL
|
||||
|
||||
#endif //CGAL_AABB_AABB_do_intersect_transform_traits_H
|
||||
|
|
|
|||
|
|
@ -36,24 +36,32 @@
|
|||
namespace CGAL {
|
||||
namespace internal {
|
||||
|
||||
// added for AABB_do_intersect_transform_traits
|
||||
template<class AABBTree>
|
||||
typename AABBTree::Bounding_box
|
||||
get_tree_bbox(const AABBTree& tree)
|
||||
template <class AABBTree>
|
||||
struct Default_tree_helper
|
||||
{
|
||||
return tree.bbox();
|
||||
}
|
||||
typedef typename AABBTree::AABB_traits AABB_traits;
|
||||
typedef typename CGAL::AABB_node<AABB_traits> Node;
|
||||
|
||||
template<class AABBNode, class AABBTraits>
|
||||
typename AABBNode::Bounding_box
|
||||
get_node_bbox(const AABBNode& node, const AABBTraits&)
|
||||
{
|
||||
return node.bbox();
|
||||
}
|
||||
Bbox_3 get_tree_bbox(const AABBTree& tree) const
|
||||
{
|
||||
return tree.bbox();
|
||||
}
|
||||
|
||||
typename AABBTree::Primitive::Datum
|
||||
get_primitive_datum(const typename AABBTree::Primitive& primitive, const AABB_traits& traits) const
|
||||
{
|
||||
return internal::Primitive_helper<AABB_traits>::get_datum(primitive, traits);
|
||||
}
|
||||
|
||||
Bbox_3 get_node_bbox(const Node& node) const
|
||||
{
|
||||
return node.bbox();
|
||||
}
|
||||
};
|
||||
|
||||
// internal class for point inside test, using existing AABB tree
|
||||
template<class Kernel, class AABBTree>
|
||||
class Point_inside_vertical_ray_cast
|
||||
template<class Kernel, class AABBTree, class Helper = Default_tree_helper<AABBTree> >
|
||||
class Point_inside_vertical_ray_cast
|
||||
{
|
||||
typedef typename Kernel::Point_3 Point;
|
||||
typedef typename Kernel::Ray_3 Ray;
|
||||
|
|
@ -61,14 +69,20 @@ class Point_inside_vertical_ray_cast
|
|||
|
||||
static const unsigned int seed = 1340818006;
|
||||
|
||||
Helper m_helper;
|
||||
|
||||
public:
|
||||
Point_inside_vertical_ray_cast(const Helper& h = Helper())
|
||||
: m_helper(h)
|
||||
{}
|
||||
|
||||
Bounded_side operator()(
|
||||
const Point& point,
|
||||
const AABBTree& tree,
|
||||
typename Kernel::Construct_ray_3 ray_functor = Kernel().construct_ray_3_object(),
|
||||
typename Kernel::Construct_vector_3 vector_functor = Kernel().construct_vector_3_object() ) const
|
||||
{
|
||||
typename Traits::Bounding_box bbox = get_tree_bbox(tree);
|
||||
typename Traits::Bounding_box bbox = m_helper.get_tree_bbox(tree);
|
||||
|
||||
if( point.x() < bbox.xmin() || point.x() > bbox.xmax()
|
||||
|| point.y() < bbox.ymin() || point.y() > bbox.ymax()
|
||||
|
|
@ -103,8 +117,8 @@ private:
|
|||
std::pair<boost::logic::tribool,std::size_t>
|
||||
status( boost::logic::tribool(boost::logic::indeterminate), 0);
|
||||
|
||||
Ray_3_Triangle_3_traversal_traits<Traits, Kernel, Boolean_tag<ray_is_vertical> >
|
||||
traversal_traits(status, tree.traits());
|
||||
Ray_3_Triangle_3_traversal_traits<Traits, Kernel, Helper, Boolean_tag<ray_is_vertical> >
|
||||
traversal_traits(status, tree.traits(), m_helper);
|
||||
|
||||
tree.traversal(ray, traversal_traits);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
//
|
||||
//
|
||||
//
|
||||
// Author(s) : Sebastien Loriot
|
||||
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
namespace CGAL {
|
||||
namespace internal {
|
||||
|
||||
template<typename AABBTraits, class Kernel, class Tag_ray_is_vertical=Tag_false>
|
||||
template<typename AABBTraits, class Kernel, class Helper, class Tag_ray_is_vertical=Tag_false>
|
||||
class Ray_3_Triangle_3_traversal_traits
|
||||
{
|
||||
protected:
|
||||
|
|
@ -46,11 +46,13 @@ protected:
|
|||
const AABBTraits& m_aabb_traits;
|
||||
typedef typename AABBTraits::Primitive Primitive;
|
||||
typedef CGAL::AABB_node<AABBTraits> Node;
|
||||
Helper m_helper;
|
||||
|
||||
public:
|
||||
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status,
|
||||
const AABBTraits& aabb_traits)
|
||||
:m_status(status),m_stop(false), m_aabb_traits(aabb_traits)
|
||||
const AABBTraits& aabb_traits,
|
||||
const Helper& h)
|
||||
:m_status(status),m_stop(false), m_aabb_traits(aabb_traits), m_helper(h)
|
||||
{m_status.first=true;}
|
||||
|
||||
bool go_further() const { return !m_stop; }
|
||||
|
|
@ -60,10 +62,8 @@ public:
|
|||
{
|
||||
internal::r3t3_do_intersect_endpoint_position_visitor visitor;
|
||||
std::pair<bool,internal::R3T3_intersection::type> res=
|
||||
internal::do_intersect(
|
||||
(internal::Primitive_helper<AABBTraits>::get_datum(primitive, m_aabb_traits)),
|
||||
query,Kernel(),visitor);
|
||||
|
||||
internal::do_intersect(m_helper.get_primitive_datum(primitive, m_aabb_traits), query,Kernel(),visitor);
|
||||
|
||||
if (res.first){
|
||||
switch (res.second){
|
||||
case internal::R3T3_intersection::CROSS_FACET:
|
||||
|
|
@ -79,40 +79,40 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Query>
|
||||
bool do_intersect(const Query& query, const Node& node) const
|
||||
{
|
||||
return m_aabb_traits.do_intersect_object()(query, node.bbox());
|
||||
return m_aabb_traits.do_intersect_object()(query, m_helper.get_node_bbox(node));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//specialization for vertical ray
|
||||
template<typename AABBTraits, class Kernel>
|
||||
class Ray_3_Triangle_3_traversal_traits<AABBTraits,Kernel,Tag_true>:
|
||||
public Ray_3_Triangle_3_traversal_traits<AABBTraits,Kernel,Tag_false>
|
||||
template<typename AABBTraits, class Kernel, class TraversalTraits>
|
||||
class Ray_3_Triangle_3_traversal_traits<AABBTraits,Kernel,TraversalTraits,Tag_true>:
|
||||
public Ray_3_Triangle_3_traversal_traits<AABBTraits,Kernel,TraversalTraits,Tag_false>
|
||||
{
|
||||
typedef Ray_3_Triangle_3_traversal_traits<AABBTraits,Kernel,Tag_false> Base;
|
||||
typedef Ray_3_Triangle_3_traversal_traits<AABBTraits,Kernel,TraversalTraits,Tag_false> Base;
|
||||
typedef typename Kernel::Point_3 Point;
|
||||
typedef typename Base::Primitive Primitive;
|
||||
typedef CGAL::AABB_node<AABBTraits> Node;
|
||||
|
||||
public:
|
||||
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status, const AABBTraits& aabb_traits)
|
||||
:Base(status, aabb_traits){}
|
||||
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status, const AABBTraits& aabb_traits, const TraversalTraits& tt)
|
||||
:Base(status, aabb_traits, tt){}
|
||||
|
||||
template <class Query>
|
||||
bool do_intersect(const Query& query, const Bbox_3& bbox) const
|
||||
{
|
||||
const Point& source=query.point(0);
|
||||
const Point& target=query.point(1);
|
||||
|
||||
|
||||
bool inc_z=target.z()>source.z();
|
||||
|
||||
|
||||
//the ray does not intersect the z-slab
|
||||
if ( ( inc_z && source.z()>bbox.zmax() )|| (!inc_z && source.z()<bbox.zmin()) ) return false;
|
||||
|
||||
|
||||
//the source is not in the x-slab
|
||||
if (source.x() > bbox.xmax() || source.x()<bbox.xmin()) return false;
|
||||
//check if the source is not in the y-slab
|
||||
|
|
@ -122,7 +122,7 @@ public:
|
|||
template <class Query>
|
||||
bool do_intersect(const Query& query, const Node& node) const
|
||||
{
|
||||
return do_intersect(query,get_node_bbox(node, this->m_aabb_traits));
|
||||
return do_intersect(query,this->m_helper.get_node_bbox(node));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -139,44 +139,42 @@ public:
|
|||
template<class Query>
|
||||
void intersection(const Query& query, const Primitive& primitive)
|
||||
{
|
||||
typename Kernel::Triangle_3 t
|
||||
= (internal::Primitive_helper<AABBTraits>::get_datum(primitive, this->m_aabb_traits));
|
||||
typename Kernel::Triangle_3 t = this->m_helper.get_primitive_datum(primitive, this->m_aabb_traits);
|
||||
if ( !do_intersect(query,t.bbox()) ) return;
|
||||
|
||||
|
||||
typename Kernel::Point_2 p0=z_project(t[0]);
|
||||
typename Kernel::Point_2 p1=z_project(t[1]);
|
||||
typename Kernel::Point_2 p2=z_project(t[2]);
|
||||
int indices[3]={0,1,2}; //to track whether triangle points have been swapt
|
||||
typename Kernel::Point_2 q=z_project( query.source() );
|
||||
|
||||
|
||||
Orientation orient_2=orientation(p0,p1,p2);
|
||||
|
||||
|
||||
//check whether the face has a normal vector in the xy-plane
|
||||
if (orient_2==COLLINEAR){
|
||||
//in that case the projection of the triangle along the z-axis is a segment.
|
||||
const typename Kernel::Point_2& other_point = p0!=p1?p1:p2;
|
||||
if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection
|
||||
|
||||
//check if the ray source is above or below the triangle and compare it
|
||||
|
||||
//check if the ray source is above or below the triangle and compare it
|
||||
//with the direction of the ray
|
||||
//TODO and if yes return
|
||||
//this is just an optimisation, the current code is valid
|
||||
|
||||
|
||||
this->m_status.first=boost::logic::indeterminate;
|
||||
this->m_stop=true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//regular case
|
||||
if (orient_2==NEGATIVE){
|
||||
std::swap(p1,p2);
|
||||
std::swap(indices[1],indices[2]);
|
||||
}
|
||||
|
||||
|
||||
//check whether the ray intersect the supporting plane
|
||||
Orientation orient_3 = orientation(t[indices[0]],t[indices[1]],t[indices[2]],query.source());
|
||||
if ( orient_3!=COPLANAR &&
|
||||
if ( orient_3!=COPLANAR &&
|
||||
(
|
||||
//indicates whether the ray is oriented toward the positive side of the plane
|
||||
( POSITIVE == CGAL::sign( query.to_vector().z() ) )
|
||||
|
|
@ -185,7 +183,6 @@ public:
|
|||
(orient_3==POSITIVE)
|
||||
)
|
||||
) return; //no intersection
|
||||
|
||||
|
||||
//position against first segment
|
||||
switch( orientation(p0,p1,q) ){
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@
|
|||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h>
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/AABB_face_graph_triangle_primitive.h>
|
||||
#include <CGAL/Side_of_triangle_mesh.h>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
|
|
@ -50,17 +50,16 @@ template <class TriangleMesh, class Kernel, class HAS_ROTATION = CGAL::Tag_true>
|
|||
class Rigid_mesh_collision_detection
|
||||
{
|
||||
typedef CGAL::AABB_face_graph_triangle_primitive<TriangleMesh> Primitive;
|
||||
typedef CGAL::AABB_do_intersect_transform_traits<Kernel, Primitive, HAS_ROTATION> Traits;
|
||||
typedef CGAL::AABB_traits<Kernel, Primitive> Traits;
|
||||
typedef CGAL::AABB_tree<Traits> Tree;
|
||||
typedef Side_of_triangle_mesh<TriangleMesh, Kernel, Default, Tree> Side_of_tm;
|
||||
|
||||
typedef Do_intersect_traversal_traits_with_transformation<Traits, Kernel, HAS_ROTATION> Traversal_traits;
|
||||
|
||||
std::vector<const TriangleMesh*> m_triangle_mesh_ptrs;
|
||||
// TODO: we probably want an option with external trees
|
||||
std::vector<Tree*> m_aabb_trees;
|
||||
std::vector<bool> m_is_closed;
|
||||
std::vector< std::vector<typename Kernel::Point_3> > m_points_per_cc;
|
||||
|
||||
std::vector<Traversal_traits> m_traversal_traits;
|
||||
#if CGAL_CACHE_BOXES
|
||||
boost::dynamic_bitset<> m_bboxes_is_invalid;
|
||||
std::vector<Bbox_3> m_bboxes;
|
||||
|
|
@ -108,6 +107,25 @@ class Rigid_mesh_collision_detection
|
|||
m_points_per_cc.back().push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) );
|
||||
}
|
||||
|
||||
// precondition A and B does not intersect
|
||||
bool does_A_contains_a_CC_of_B(std::size_t id_A, std::size_t id_B)
|
||||
{
|
||||
typename Kernel::Construct_ray_3 ray_functor;
|
||||
typename Kernel::Construct_vector_3 vector_functor;
|
||||
typedef typename Traversal_traits::Transformed_tree_helper Helper;
|
||||
|
||||
BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[id_B])
|
||||
{
|
||||
if( internal::Point_inside_vertical_ray_cast<Kernel, Tree, Helper>(m_traversal_traits[id_A].get_helper())(
|
||||
m_traversal_traits[id_B].transformation()( q ), *m_aabb_trees[id_A],
|
||||
ray_functor, vector_functor) == CGAL::ON_BOUNDED_SIDE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
template <class MeshRange>
|
||||
Rigid_mesh_collision_detection(const MeshRange& triangle_meshes, bool assume_one_CC_per_mesh = false)
|
||||
|
|
@ -131,6 +149,7 @@ public:
|
|||
m_aabb_trees.reserve(nb_meshes);
|
||||
m_is_closed.clear();
|
||||
m_is_closed.resize(nb_meshes, false);
|
||||
m_traversal_traits.reserve(m_aabb_trees.size());
|
||||
#if CGAL_CACHE_BOXES
|
||||
m_bboxes_is_invalid.clear();
|
||||
m_bboxes_is_invalid.resize(nb_meshes, true);
|
||||
|
|
@ -144,6 +163,7 @@ public:
|
|||
m_triangle_mesh_ptrs.push_back( &tm );
|
||||
Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm);
|
||||
m_aabb_trees.push_back(t);
|
||||
m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) );
|
||||
add_cc_points(tm, assume_one_CC);
|
||||
}
|
||||
}
|
||||
|
|
@ -154,6 +174,7 @@ public:
|
|||
m_triangle_mesh_ptrs.push_back( &tm );
|
||||
Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm);
|
||||
m_aabb_trees.push_back(t);
|
||||
m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) );
|
||||
#if CGAL_CACHE_BOXES
|
||||
m_bboxes.push_back(Bbox_3());
|
||||
m_bboxes_is_invalid.resize(m_bboxes_is_invalid.size()+1, true);
|
||||
|
|
@ -169,6 +190,7 @@ public:
|
|||
m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id);
|
||||
m_is_closed.erase(m_is_closed.begin()+mesh_id);
|
||||
m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id);
|
||||
m_traversal_traits.erase(m_traversal_traits.begin()+mesh_id);
|
||||
#if CGAL_CACHE_BOXES
|
||||
// TODO this is a lazy approach that is not optimal
|
||||
m_bboxes.pop_back();
|
||||
|
|
@ -179,7 +201,7 @@ public:
|
|||
|
||||
void set_transformation(std::size_t mesh_id, const Aff_transformation_3<Kernel>& aff_trans)
|
||||
{
|
||||
m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans);
|
||||
m_traversal_traits[mesh_id].set_transformation(aff_trans);
|
||||
#if CGAL_CACHE_BOXES
|
||||
m_bboxes_is_invalid.set(mesh_id);
|
||||
#endif
|
||||
|
|
@ -189,11 +211,11 @@ public:
|
|||
void update_bboxes()
|
||||
{
|
||||
// protector is supposed to have been set
|
||||
for (boost::dynamic_bitset<>::size_type i = m_bboxes.find_first();
|
||||
for (boost::dynamic_bitset<>::size_type i = m_bboxes_is_invalid.find_first();
|
||||
i != m_bboxes_is_invalid.npos;
|
||||
i = m_bboxes_is_invalid.find_next(i))
|
||||
{
|
||||
m_bboxes[i]=internal::get_tree_bbox(*m_aabb_trees[i]);
|
||||
m_bboxes[i]=m_traversal_traits[i].get_helper().get_tree_bbox(*m_aabb_trees[i]);
|
||||
}
|
||||
m_bboxes_is_invalid.reset();
|
||||
}
|
||||
|
|
@ -261,34 +283,27 @@ public:
|
|||
if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue;
|
||||
#endif
|
||||
// TODO: think about an alternative that is using a traversal traits
|
||||
if ( m_aabb_trees[k]->do_intersect( *m_aabb_trees[mesh_id] ) )
|
||||
|
||||
Do_intersect_traversal_traits_for_two_trees<Traits, Kernel, HAS_ROTATION> traversal_traits(
|
||||
m_aabb_trees[k]->traits(), m_traversal_traits[k].transformation(), m_traversal_traits[mesh_id]);
|
||||
m_aabb_trees[k]->traversal(*m_aabb_trees[mesh_id], traversal_traits);
|
||||
if (traversal_traits.is_intersection_found())
|
||||
res.push_back(std::make_pair(k, false));
|
||||
else{
|
||||
if (m_is_closed[mesh_id])
|
||||
{
|
||||
Side_of_tm side_of_mid(*m_aabb_trees[mesh_id]);
|
||||
bool stop = false;
|
||||
BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[k])
|
||||
if ( does_A_contains_a_CC_of_B(mesh_id, k) )
|
||||
{
|
||||
if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE)
|
||||
{
|
||||
res.push_back(std::make_pair(k, true));
|
||||
stop=true;
|
||||
break;
|
||||
}
|
||||
res.push_back(std::make_pair(k, true));
|
||||
continue;
|
||||
}
|
||||
if (stop) continue;
|
||||
}
|
||||
if (m_is_closed[k])
|
||||
{
|
||||
Side_of_tm side_of_mk(*m_aabb_trees[k]);
|
||||
BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[mesh_id])
|
||||
if ( does_A_contains_a_CC_of_B(k, mesh_id) )
|
||||
{
|
||||
if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE)
|
||||
{
|
||||
res.push_back(std::make_pair(k, true));
|
||||
break;
|
||||
}
|
||||
res.push_back(std::make_pair(k, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue