Program Listing for File AABBtree.hxx¶
↰ Return to documentation for file (Clothoids/AABBtree.hxx)
/*--------------------------------------------------------------------------*\
| |
| Copyright (C) 2018 |
| |
| , __ , __ |
| /|/ \ /|/ \ |
| | __/ _ ,_ | __/ _ ,_ |
| | \|/ / | | | | \|/ / | | | |
| |(__/|__/ |_/ \_/|/|(__/|__/ |_/ \_/|/ |
| /| /| |
| \| \| |
| |
| Paolo Bevilacqua and Enrico Bertolazzi |
| |
| (1) Dipartimento di Ingegneria e Scienza dell'Informazione |
| (2) Dipartimento di Ingegneria Industriale |
| |
| Universita` degli Studi di Trento |
| email: paolo.bevilacqua@unitn.it |
| email: enrico.bertolazzi@unitn.it |
| |
\*--------------------------------------------------------------------------*/
namespace G2lib {
using std::setw;
using std::vector;
using std::pair;
#ifdef G2LIB_USE_CXX11
using std::make_shared;
using std::shared_ptr; // promemoria shared_ptr<Foo>(&foo, [](void*){});
#endif
class AABBtree;
/*\
| ____ ____
| | __ )| __ ) _____ __
| | _ \| _ \ / _ \ \/ /
| | |_) | |_) | (_) > <
| |____/|____/ \___/_/\_\
\*/
class BBox {
public:
#ifdef G2LIB_USE_CXX11
typedef shared_ptr<BBox const> PtrBBox;
#else
typedef BBox const * PtrBBox;
#endif
private:
real_type m_xmin;
real_type m_ymin;
real_type m_xmax;
real_type m_ymax;
int_type m_id;
int_type m_ipos;
BBox();
BBox( BBox const & );
public:
BBox(
real_type xmin,
real_type ymin,
real_type xmax,
real_type ymax,
int_type id,
int_type ipos
) {
m_xmin = xmin;
m_ymin = ymin;
m_xmax = xmax;
m_ymax = ymax;
m_id = id;
m_ipos = ipos;
}
BBox(
vector<PtrBBox> const & bboxes,
int_type id,
int_type ipos
) {
m_id = id;
m_ipos = ipos;
this -> join( bboxes );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real_type Xmin() const { return m_xmin; }
real_type Ymin() const { return m_ymin; }
real_type Xmax() const { return m_xmax; }
real_type Ymax() const { return m_ymax; }
int_type const & Id() const { return m_id; }
int_type const & Ipos() const { return m_ipos; }
BBox const &
operator = ( BBox const & rhs ) {
m_xmin = rhs.m_xmin;
m_ymin = rhs.m_ymin;
m_xmax = rhs.m_xmax;
m_ymax = rhs.m_ymax;
m_id = rhs.m_id;
m_ipos = rhs.m_ipos;
return *this;
}
bool
collision( BBox const & box ) const {
return !( (box.m_xmin > m_xmax ) ||
(box.m_xmax < m_xmin ) ||
(box.m_ymin > m_ymax ) ||
(box.m_ymax < m_ymin ) );
}
void
join( vector<PtrBBox> const & bboxes );
real_type
distance( real_type x, real_type y ) const;
real_type
maxDistance( real_type x, real_type y ) const;
void
print( ostream_type & stream ) const {
fmt::print( stream,
"BBOX (xmin,ymin,xmax,ymax) = ( {}, {}, {}, {} )\n",
m_xmin, m_ymin, m_xmax, m_ymax
);
}
friend class AABBtree;
};
inline
ostream_type &
operator << ( ostream_type & stream, BBox const & bb ) {
bb.print(stream);
return stream;
}
/*\
| _ _ ____ ____ _
| / \ / \ | __ )| __ )| |_ _ __ ___ ___
| / _ \ / _ \ | _ \| _ \| __| '__/ _ \/ _ \
| / ___ \ / ___ \| |_) | |_) | |_| | | __/ __/
| /_/ \_\/_/ \_\____/|____/ \__|_| \___|\___|
\*/
class AABBtree {
public:
#ifdef G2LIB_USE_CXX11
typedef shared_ptr<BBox const> PtrBBox;
typedef shared_ptr<AABBtree> PtrAABB;
#else
typedef BBox const * PtrBBox;
typedef AABBtree * PtrAABB;
#endif
typedef pair<PtrBBox,PtrBBox> PairPtrBBox;
typedef vector<PtrBBox> VecPtrBBox;
typedef vector<PairPtrBBox> VecPairPtrBBox;
private:
// bbox of the tree
PtrBBox pBBox;
vector<PtrAABB> children;
AABBtree( AABBtree const & tree );
static
real_type
min_maxdist(
real_type x,
real_type y,
AABBtree const & tree,
real_type mmDist
);
static
void
min_maxdist_select(
real_type x,
real_type y,
real_type mmDist,
AABBtree const & tree,
VecPtrBBox & candidateList
);
public:
AABBtree();
~AABBtree();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void clear();
bool empty() const;
void
bbox(
real_type & xmin,
real_type & ymin,
real_type & xmax,
real_type & ymax
) const {
xmin = pBBox->m_xmin;
ymin = pBBox->m_ymin;
xmax = pBBox->m_xmax;
ymax = pBBox->m_ymax;
}
void
build( vector<PtrBBox> const & bboxes );
void
print( ostream_type & stream, int level = 0 ) const;
template <typename COLLISION_fun>
bool
collision(
AABBtree const & tree,
COLLISION_fun ifun,
bool swap_tree = false
) const {
// check bbox with
if ( !tree.pBBox->collision(*pBBox) ) return false;
int icase = (children.empty() ? 0 : 1) +
(tree.children.empty()? 0 : 2);
switch ( icase ) {
case 0: // both leaf, use GeomPrimitive intersection algorithm
if ( swap_tree ) return ifun( tree.pBBox, pBBox );
else return ifun( pBBox, tree.pBBox );
case 1: // first is a tree, second is a leaf
{ typename vector<PtrAABB>::const_iterator it;
for ( it = children.begin(); it != children.end(); ++it )
if ( tree.collision( **it, ifun, !swap_tree ) )
return true;
}
break;
case 2: // first leaf, second is a tree
{ typename vector<PtrAABB>::const_iterator it;
for ( it = tree.children.begin();
it != tree.children.end(); ++it )
if ( this->collision( **it, ifun, swap_tree ) )
return true;
}
break;
case 3: // first is a tree, second is a tree
{ typename vector<PtrAABB>::const_iterator c1;
typename vector<PtrAABB>::const_iterator c2;
for ( c1 = children.begin(); c1 != children.end(); ++c1 )
for ( c2 = tree.children.begin();
c2 != tree.children.end(); ++c2 )
if ( (*c1)->collision( **c2, ifun, swap_tree ) )
return true;
}
break;
}
return false;
}
void
intersect(
AABBtree const & tree,
VecPairPtrBBox & intersectionList,
bool swap_tree = false
) const;
void
min_distance(
real_type x,
real_type y,
VecPtrBBox & candidateList
) const;
};
}