use of standard grid interface
use of vector instead of map inside the cell removed closest iterator
This commit is contained in:
parent
be78e8d97f
commit
54c8562e3a
|
@ -24,6 +24,9 @@
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$Log: not supported by cvs2svn $
|
||||||
|
Revision 1.7 2005/06/15 11:44:47 pietroni
|
||||||
|
minor changes
|
||||||
|
|
||||||
Revision 1.6 2005/06/01 13:47:59 pietroni
|
Revision 1.6 2005/06/01 13:47:59 pietroni
|
||||||
resolved hash code conflicts
|
resolved hash code conflicts
|
||||||
|
|
||||||
|
@ -47,11 +50,13 @@ added vcg header
|
||||||
#ifndef VCGLIB_SPATIAL_HASHING
|
#ifndef VCGLIB_SPATIAL_HASHING
|
||||||
#define VCGLIB_SPATIAL_HASHING
|
#define VCGLIB_SPATIAL_HASHING
|
||||||
|
|
||||||
|
|
||||||
#define P0 73856093
|
#define P0 73856093
|
||||||
#define P1 19349663
|
#define P1 19349663
|
||||||
#define P2 83492791
|
#define P2 83492791
|
||||||
|
|
||||||
#include <map>
|
#include <vcg/space/index/grid_util.h>
|
||||||
|
//#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -62,73 +67,114 @@ added vcg header
|
||||||
#define STDEXT __gnu_cxx
|
#define STDEXT __gnu_cxx
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace vcg{
|
namespace vcg{
|
||||||
/** Spatial Hash Table
|
/** Spatial Hash Table
|
||||||
Spatial Hashing as described in
|
Spatial Hashing as described in
|
||||||
"Optimized Spatial Hashing for Collision Detection of Deformable Objects",
|
"Optimized Spatial Hashing for Coll ision Detection of Deformable Objects",
|
||||||
Matthias Teschner and Bruno Heidelberger and Matthias Muller and Danat Pomeranets and Markus Gross
|
Matthias Teschner and Bruno Heidelberger and Matthias Muller and Danat Pomeranets and Markus Gross
|
||||||
*/
|
*/
|
||||||
template <class ElemType>
|
template < typename ContainerType,class FLT=float >
|
||||||
class SpatialHashTable{
|
class SpatialHashTable:public BasicGrid<FLT>
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef typename ElemType::CoordType CoordType;
|
typedef typename ContainerType::value_type ObjType;
|
||||||
typedef typename CoordType::ScalarType ScalarType;
|
typedef ObjType* ObjPtr;
|
||||||
|
typedef typename ObjType::ScalarType ScalarType;
|
||||||
|
typedef Point3<ScalarType> CoordType;
|
||||||
|
|
||||||
|
|
||||||
//type of entries element of a cell
|
//type of container of pointer to object in a Cell
|
||||||
typedef typename std::pair<ElemType*,int> EntryType;
|
//typedef typename std::pair<ObjType*,int> EntryType ;
|
||||||
|
class EntryType : public std::pair<ObjType*,int>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EntryType(ObjType* sim,const int &_tempMark)
|
||||||
|
{
|
||||||
|
first=sim;
|
||||||
|
second=_tempMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjType& operator *(){return (*this->first);}
|
||||||
|
};
|
||||||
|
|
||||||
|
//typedef typename std::map<ObjType*,int> CellContainerType;
|
||||||
|
typedef typename std::vector<EntryType> CellContainerType;
|
||||||
|
typedef typename CellContainerType::iterator IteMap;
|
||||||
|
typedef typename EntryType* CellIterator;
|
||||||
|
|
||||||
|
////iterator to elems on a cell (need to define method Elem() for Space Iterators)
|
||||||
|
//class CellIterator :public IteMap
|
||||||
|
//{
|
||||||
|
// //std::vector<int>::iterator i;
|
||||||
|
//public:
|
||||||
|
// CellIterator(){}
|
||||||
|
// inline CellIterator & operator = ( IteMap const &c)
|
||||||
|
// {this->); };
|
||||||
|
// ObjType* operator *(){return ((* this)->first);}
|
||||||
|
//};
|
||||||
|
|
||||||
//This Class Identify the cell
|
//This Class Identify the cell
|
||||||
struct HElement
|
struct Cell
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
///the min and max point corresponding to the cell - used to inverse hashing
|
///the min and max point corresponding to the cell - used to inverse hashing
|
||||||
CoordType min;//coordinate min of the cell
|
//CoordType min;//coordinate min of the cell
|
||||||
CoordType max;//coordinate max of the cell
|
//CoordType max;//coordinate max of the cell
|
||||||
|
|
||||||
Point3i cell_n;//cell number
|
Point3i cell_n;//cell number
|
||||||
|
//iterator to the map element into the cell
|
||||||
|
//typedef typename CellContainerType::iterator IteMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//elements
|
//elements
|
||||||
std::map<ElemType*,int> _entries;
|
CellContainerType _entries;
|
||||||
|
|
||||||
//iterator to the map element into the cell
|
Cell()
|
||||||
typedef typename std::map<ElemType*,int>::iterator IteMap;
|
|
||||||
|
|
||||||
HElement()
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
HElement(ElemType* sim,const int &_tempMark,CoordType _min,CoordType _max,Point3i _cell)
|
Cell(ObjType* sim,Point3i _cell,const int &_tempMark)
|
||||||
{
|
{
|
||||||
_entries.insert(EntryType(sim,_tempMark));
|
_entries.push_back(EntryType(sim,_tempMark));
|
||||||
min=_min;
|
/*min=_min;
|
||||||
max=_max;
|
max=_max;
|
||||||
assert(min<max);
|
assert(min<max);*/
|
||||||
cell_n=_cell;
|
cell_n=_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
///return true if the element is in the cell
|
/////return true if the element is in the cell
|
||||||
bool IsIn(ElemType* sim)
|
//bool IsIn(ObjType* sim)
|
||||||
{int n=elem.count(sim);
|
//{
|
||||||
return (n==1);
|
// int n=elem.count(sim);
|
||||||
}
|
// assert((n==0)||(n==1));
|
||||||
|
// return (n==1);
|
||||||
|
//}
|
||||||
|
|
||||||
///return the number of elements stored in the cell
|
///return the number of elements stored in the cell
|
||||||
int Size()
|
int Size()
|
||||||
{return (int)(_entries.size());}
|
{return (int)(_entries.size());}
|
||||||
|
|
||||||
///update or insert an element into a cell
|
///find the simplex into the cell
|
||||||
void Update(ElemType* sim, const int & _tempMark)
|
bool Find(ObjType* sim,IteMap &I)
|
||||||
{
|
{
|
||||||
IteMap I=_entries.find(sim);
|
for (I=_entries.begin();I<_entries.end();I++)
|
||||||
|
if ((*I).first==sim)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (I!=_entries.end())//the entry exist in the cell
|
///update or insert an element into a cell
|
||||||
|
void Update(ObjType* sim, const int & _tempMark)
|
||||||
|
{
|
||||||
|
IteMap I;
|
||||||
|
if (Find(sim,I))///update temporary mark
|
||||||
(*I).second=_tempMark;
|
(*I).second=_tempMark;
|
||||||
else
|
else
|
||||||
_entries.insert(_entries.begin(),EntryType(sim,_tempMark));
|
_entries.push_back(EntryType(sim,_tempMark));
|
||||||
|
|
||||||
//at the end update the temporary mark on the simplex
|
//at the end update the temporary mark on the simplex
|
||||||
sim->Mark()=_tempMark;
|
sim->Mark()=_tempMark;
|
||||||
|
@ -147,294 +193,162 @@ namespace vcg{
|
||||||
///return true if the the entry corripondent to that
|
///return true if the the entry corripondent to that
|
||||||
///simplex is valid or not
|
///simplex is valid or not
|
||||||
///(using temporary mark).
|
///(using temporary mark).
|
||||||
bool IsUpdated(ElemType* sim)
|
bool IsUpdated(ObjType* sim)
|
||||||
{
|
{
|
||||||
IteMap I=_entries.find(sim);
|
IteMap I;
|
||||||
if (I!=_entries.end())
|
if (Find(sim,I))
|
||||||
return(IsUpdated(I));
|
return(IsUpdated(I));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//add to the vector all simplexes of the map that have a right timestamp or are not deleted
|
|
||||||
void Elems(std::vector<ElemType*> & res)
|
|
||||||
{
|
|
||||||
for (IteMap ite=_entries.begin();ite!=_entries.end();ite++)
|
|
||||||
{
|
|
||||||
ElemType* sim=(*ite).first;
|
|
||||||
if (IsUpdated(ite)&&(!sim->IsD()))
|
|
||||||
res.push_back(sim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CoordType Min()
|
|
||||||
{return min;}
|
|
||||||
|
|
||||||
CoordType Max()
|
|
||||||
{return max;}
|
|
||||||
|
|
||||||
Point3i CellN()
|
Point3i CellN()
|
||||||
{return cell_n;}
|
{return cell_n;}
|
||||||
|
|
||||||
bool operator ==(const HElement &h)
|
bool operator ==(const Cell &h)
|
||||||
{return (cell_n==h.CellN());}
|
{return (cell_n==h.CellN());}
|
||||||
|
|
||||||
bool operator !=(const HElement &h)
|
bool operator !=(const Cell &h)
|
||||||
{return ((cell_n!=h.CellN()));}
|
{return ((cell_n!=h.CellN()));}
|
||||||
|
|
||||||
void Assert()
|
|
||||||
{
|
|
||||||
for (IteMap ite=_entries.begin();ite!=_entries.end();ite++)
|
|
||||||
{
|
|
||||||
ElemType* sim=(*ite).first;
|
|
||||||
if (IsUpdated(sim))
|
|
||||||
{
|
|
||||||
ScalarType Xs=sim->P().X();
|
|
||||||
ScalarType Ys=sim->P().Y();
|
|
||||||
ScalarType Zs=sim->P().Z();
|
|
||||||
ScalarType Xm=Min().X()-0.2;
|
|
||||||
ScalarType Ym=Min().Y()-0.2;
|
|
||||||
ScalarType Zm=Min().Z()-0.2;
|
|
||||||
ScalarType XM=Max().X()+0.2;
|
|
||||||
ScalarType YM=Max().Y()+0.2;
|
|
||||||
ScalarType ZM=Max().Z()+0.2;
|
|
||||||
if ((Xs<Xm)||(Xs>XM)||(Ys<Ym)||(Ys>YM)||(Zs<Zm)||(Zs>ZM))
|
|
||||||
{
|
|
||||||
printf("---ERROR---\n");
|
|
||||||
printf("Point=%f,%f,%f.\n",Xs,Ys,Zs);
|
|
||||||
printf("cellMin=%f,%f,%f\n",Xm,Ym,Zm);
|
|
||||||
printf("cellMax=%f,%f,%f\n",XM,YM,ZM);
|
|
||||||
|
|
||||||
}
|
}; // end struct Cell
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end struct HElement
|
////This Class Identify the cell
|
||||||
|
//struct Cell
|
||||||
|
//{
|
||||||
|
//private:
|
||||||
|
|
||||||
///this Iterator returns all the elements that
|
// ///the min and max point corresponding to the cell - used to inverse hashing
|
||||||
///are in a specified box.
|
// //CoordType min;//coordinate min of the cell
|
||||||
struct ClosersIterator{
|
// //CoordType max;//coordinate max of the cell
|
||||||
|
|
||||||
private:
|
// Point3i cell_n;//cell number
|
||||||
CoordType p;
|
// //iterator to the map element into the cell
|
||||||
SpatialHashTable<ElemType> * sh; ///pointer to spatial hash table structure
|
// //typedef typename CellContainerType::iterator IteMap;
|
||||||
vcg::Point3i mincorner,maxcorner; ///corners of the box where the scannig is performed
|
|
||||||
vcg::Point3i curr_ic; /// triple corresponding to the cell coordinate
|
|
||||||
HElement * curr_c; /// current cell pointer
|
|
||||||
typename HElement::IteMap curr_i; /// current iterator inside the cell
|
|
||||||
bool end; ///return true if the scanning of the elements is terminated
|
|
||||||
|
|
||||||
///advance the current coordinate of one step inside the space box
|
//public:
|
||||||
///set and to true if scannig fo cells is complete
|
|
||||||
void Advance(){
|
|
||||||
if(curr_ic[0] < maxcorner[0])
|
|
||||||
++curr_ic[0];
|
|
||||||
else{
|
|
||||||
if(curr_ic[1] < maxcorner[1])
|
|
||||||
++curr_ic[1];
|
|
||||||
else{
|
|
||||||
if(curr_ic[2] < maxcorner[2])
|
|
||||||
++curr_ic[2];
|
|
||||||
else
|
|
||||||
end=true;
|
|
||||||
curr_ic[1] = mincorner[1];
|
|
||||||
}
|
|
||||||
curr_ic[0] = mincorner[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
// //elements
|
||||||
|
// CellContainerType _entries;
|
||||||
|
|
||||||
//operator Next
|
// Cell()
|
||||||
//go to next simplex without considering temporary mark
|
// {}
|
||||||
void Next() {
|
|
||||||
SpatialHashTable<ElemType>::IteHtable I;
|
|
||||||
|
|
||||||
HElement::IteMap e = curr_c->_entries.end();
|
// Cell(ObjType* sim,Point3i _cell,const int &_tempMark)
|
||||||
--e;
|
|
||||||
|
|
||||||
///if the current index
|
|
||||||
//is not at the end of element in the cell so advance of one step
|
|
||||||
if(curr_i != e)
|
|
||||||
++curr_i;
|
|
||||||
else{
|
|
||||||
///Advance until find a cell that isn't empty or the scan is complete
|
|
||||||
Advance();
|
|
||||||
|
|
||||||
while((!End())&&(sh->numElemCell(curr_ic,I)==0))
|
|
||||||
{Advance();}
|
|
||||||
|
|
||||||
if (!End())
|
|
||||||
{
|
|
||||||
curr_c = &((*I).second);
|
|
||||||
curr_i = curr_c->_entries.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void AssertUpdated()
|
|
||||||
{
|
|
||||||
ElemType* sim=(*curr_i).first;
|
|
||||||
ScalarType Xs=sim->P().X();
|
|
||||||
ScalarType Ys=sim->P().Y();
|
|
||||||
ScalarType Zs=sim->P().Z();
|
|
||||||
ScalarType Xm=curr_c->Min().X()-0.2;
|
|
||||||
ScalarType Ym=curr_c->Min().Y()-0.2;
|
|
||||||
ScalarType Zm=curr_c->Min().Z()-0.2;
|
|
||||||
ScalarType XM=curr_c->Max().X()+0.2;
|
|
||||||
ScalarType YM=curr_c->Max().Y()+0.2;
|
|
||||||
ScalarType ZM=curr_c->Max().Z()+0.2;
|
|
||||||
if ((Xs<Xm)||(Xs>XM)||(Ys<Ym)||(Ys>YM)||(Zs<Zm)||(Zs>ZM))
|
|
||||||
{
|
|
||||||
printf("---ERROR---\n");
|
|
||||||
printf("Point=%f,%f,%f.\n",Xs,Ys,Zs);
|
|
||||||
printf("cellMin=%f,%f,%f\n",Xm,Ym,Zm);
|
|
||||||
printf("cellMax=%f,%f,%f\n",XM,YM,ZM);
|
|
||||||
printf("tempMark Simplex=%d\n",sim->Mark());
|
|
||||||
printf("tempMark Global=%d\n",sh->tempMark);
|
|
||||||
if (curr_c->IsUpdated(sim))
|
|
||||||
printf("updated");
|
|
||||||
else
|
|
||||||
printf("disupdated");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///Initialize the iterator, p is the center of the box and _edge is his size
|
|
||||||
void Init(SpatialHashTable<ElemType> * _sh, CoordType _p, const ScalarType &_edge)
|
|
||||||
{
|
|
||||||
end=false;
|
|
||||||
sh = _sh;
|
|
||||||
p =_p;
|
|
||||||
SpatialHashTable<ElemType>::IteHtable I;
|
|
||||||
|
|
||||||
///find the box
|
|
||||||
CoordType halfDiag(_edge,_edge,_edge);
|
|
||||||
mincorner = sh->PointToCell(p-halfDiag);
|
|
||||||
maxcorner = sh->PointToCell(p+halfDiag);
|
|
||||||
|
|
||||||
///set the initial cell of the iterator as the one that stay on the
|
|
||||||
/// left lower position
|
|
||||||
curr_ic = mincorner;
|
|
||||||
|
|
||||||
//if the fist position isn't empty
|
|
||||||
if (sh->numElemCell(curr_ic,I)>0)
|
|
||||||
{
|
|
||||||
curr_c = &((*I).second);
|
|
||||||
curr_i = curr_c->_entries.begin();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{///advance until don't find an non empty cell
|
|
||||||
while((!End())&&(sh->numElemCell(curr_ic,I)==0))
|
|
||||||
Advance();
|
|
||||||
}
|
|
||||||
///then if is not finished find the first updated occorrency
|
|
||||||
if (!End())
|
|
||||||
{
|
|
||||||
curr_c = &((*I).second);
|
|
||||||
curr_i = curr_c->_entries.begin();
|
|
||||||
while ((!curr_c->IsUpdated(curr_i))&&(!end))
|
|
||||||
Next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////operator ++ of the itearator
|
|
||||||
//void Next() {
|
|
||||||
// bool isempty = true;
|
|
||||||
// HElement::IteMap e = curr_c->_entries.end();
|
|
||||||
// --e;
|
|
||||||
|
|
||||||
// ///if the current index
|
|
||||||
// //is not at the end of elemnt in the cell so advance of one step
|
|
||||||
// if(curr_i != e)
|
|
||||||
// ++curr_i;
|
|
||||||
|
|
||||||
// ///if the elemants on the cell are terminated then switch to another cell
|
|
||||||
// if(curr_i == e)
|
|
||||||
// {
|
// {
|
||||||
// ///Advance until find a cell that isn't empty
|
// _entries.insert(EntryType(sim,_tempMark));
|
||||||
// while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
|
// /*min=_min;
|
||||||
// if(!isempty){
|
// max=_max;
|
||||||
// curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
|
// assert(min<max);*/
|
||||||
// curr_i = curr_c->_entries.begin();
|
// cell_n=_cell;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// ///return true if the element is in the cell
|
||||||
|
// bool IsIn(ObjType* sim)
|
||||||
|
// {
|
||||||
|
// int n=elem.count(sim);
|
||||||
|
// assert((n==0)||(n==1));
|
||||||
|
// return (n==1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ///return the number of elements stored in the cell
|
||||||
|
// int Size()
|
||||||
|
// {return (int)(_entries.size());}
|
||||||
|
|
||||||
|
// ///update or insert an element into a cell
|
||||||
|
// void Update(ObjType* sim, const int & _tempMark)
|
||||||
|
// {
|
||||||
|
// IteMap I=_entries.find(sim);
|
||||||
|
|
||||||
|
// if (I!=_entries.end())//the entry exist in the cell
|
||||||
|
// (*I).second=_tempMark;
|
||||||
// else
|
// else
|
||||||
// end = true;
|
// _entries.insert(_entries.begin(),EntryType(sim,_tempMark));
|
||||||
|
|
||||||
|
// //at the end update the temporary mark on the simplex
|
||||||
|
// sim->Mark()=_tempMark;
|
||||||
|
// //Assert();
|
||||||
// }
|
// }
|
||||||
//}
|
|
||||||
|
// ///given an iterator to the instance of the entry in the cell
|
||||||
|
// ///return true if the the entry is valid
|
||||||
|
// ///(using temporary mark).
|
||||||
|
// bool IsUpdated(CellIterator &I)
|
||||||
|
// {
|
||||||
|
// return ((*I).second >= (*I).first->Mark());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ///given an simplex pointer
|
||||||
|
// ///return true if the the entry corripondent to that
|
||||||
|
// ///simplex is valid or not
|
||||||
|
// ///(using temporary mark).
|
||||||
|
// bool IsUpdated(ObjType* sim)
|
||||||
|
// {
|
||||||
|
// IteMap I=_entries.find(sim);
|
||||||
|
// if (I!=_entries.end())
|
||||||
|
// return(IsUpdated(I));
|
||||||
|
// else
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ////add to the vector all simplexes of the map that have a right timestamp or are not deleted
|
||||||
|
// //void Elems(std::vector<ObjType*> & res)
|
||||||
|
// //{
|
||||||
|
// // for (IteMap ite=_entries.begin();ite!=_entries.end();ite++)
|
||||||
|
// // {
|
||||||
|
// // ObjType* sim=(*ite).first;
|
||||||
|
// // if (IsUpdated(ite)&&(!sim->IsD()))
|
||||||
|
// // res.push_back(sim);
|
||||||
|
// // }
|
||||||
|
// //}
|
||||||
|
|
||||||
|
|
||||||
|
// Point3i CellN()
|
||||||
|
// {return cell_n;}
|
||||||
|
|
||||||
///operator ++ of the itearator
|
// bool operator ==(const Cell &h)
|
||||||
void operator ++()
|
// {return (cell_n==h.CellN());}
|
||||||
{
|
|
||||||
Next();
|
|
||||||
while ((!curr_c->IsUpdated(curr_i))&&(!end))
|
|
||||||
Next();
|
|
||||||
|
|
||||||
assert(curr_c->IsUpdated(curr_i)||(end));
|
// bool operator !=(const Cell &h)
|
||||||
}
|
// {return ((cell_n!=h.CellN()));}
|
||||||
|
|
||||||
///dereferent operator
|
|
||||||
ElemType * operator *(){
|
|
||||||
return (*curr_i).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
///return true if the scanning of elements is complete
|
//}; // end struct Cell
|
||||||
bool End(){
|
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end struct CloserIterator
|
|
||||||
|
|
||||||
|
|
||||||
//hash table definition
|
//hash table definition
|
||||||
//typedef typename STDEXT::hash_map<int,HElement> Htable;
|
typedef typename STDEXT::hash_multimap<int,Cell> Htable;
|
||||||
typedef typename STDEXT::hash_multimap<int,HElement> Htable;
|
|
||||||
//hash table definition
|
|
||||||
//typedef typename STDEXT::hash_map<vcg::Point3i,HElement> Htable;
|
|
||||||
//record of the hash table
|
//record of the hash table
|
||||||
typedef typename std::pair<int,HElement> HRecord;
|
typedef typename std::pair<int,Cell> HRecord;
|
||||||
//iterator to the hash table
|
//iterator to the hash table
|
||||||
typedef typename Htable::iterator IteHtable;
|
typedef typename Htable::iterator IteHtable;
|
||||||
|
|
||||||
SpatialHashTable(){};
|
SpatialHashTable(){HashSpace=1000;};//default value for hash_space
|
||||||
~SpatialHashTable(){};
|
~SpatialHashTable(){};
|
||||||
|
|
||||||
int tempMark;
|
int tempMark;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//ContSimplex & _simplex;
|
|
||||||
|
|
||||||
Htable hash_table;
|
Htable hash_table;
|
||||||
|
|
||||||
int num;
|
///number of possible hash code [0...HashSpace]
|
||||||
float l;
|
int HashSpace;
|
||||||
|
|
||||||
|
|
||||||
CoordType min;
|
|
||||||
CoordType max;
|
|
||||||
|
|
||||||
|
///number of conflicts created
|
||||||
int conflicts;
|
int conflicts;
|
||||||
/*Point3i min;
|
|
||||||
Point3i max;*/
|
|
||||||
|
|
||||||
///insert a new cell
|
///insert a new cell
|
||||||
void _InsertNewHentry(ElemType* s,Point3i cell)
|
void _InsertNewHentry(ObjType* s,Point3i cell)
|
||||||
{
|
{
|
||||||
int h=Hash(cell);
|
int h=Hash(cell);
|
||||||
CoordType _min;
|
hash_table.insert(HRecord(h,Cell(s,cell,tempMark)));
|
||||||
CoordType _max;
|
|
||||||
_min=CellToPoint(cell);
|
|
||||||
_max=_min+CoordType(l,l,l);
|
|
||||||
hash_table.insert(HRecord(h,HElement(s,tempMark,_min,_max,cell)));
|
|
||||||
//Assert();
|
|
||||||
s->Mark()=tempMark;
|
s->Mark()=tempMark;
|
||||||
|
//Assert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///return true and return the iterator to the cell if exist
|
||||||
bool _IsInHtable(Point3i cell,IteHtable &result)
|
bool _IsInHtable(Point3i cell,IteHtable &result)
|
||||||
{
|
{
|
||||||
int h=Hash(cell);
|
int h=Hash(cell);
|
||||||
|
@ -449,7 +363,7 @@ namespace vcg{
|
||||||
|
|
||||||
while((i != p.second)&&((*i).second.CellN()!=cell))++i;
|
while((i != p.second)&&((*i).second.CellN()!=cell))++i;
|
||||||
|
|
||||||
if (i==p.second)///the scan is terminated and we have not fuond the cell
|
if (i==p.second)///the scan is terminated and we have not found the right cell
|
||||||
{
|
{
|
||||||
conflicts++;
|
conflicts++;
|
||||||
return false;
|
return false;
|
||||||
|
@ -464,96 +378,98 @@ namespace vcg{
|
||||||
|
|
||||||
///insert an element in a specified cell if the cell doesn't exist than
|
///insert an element in a specified cell if the cell doesn't exist than
|
||||||
///create it.
|
///create it.
|
||||||
void _InsertInCell(ElemType* s,Point3i cell)
|
void _InsertInCell(ObjType* s,Point3i cell)
|
||||||
{
|
{
|
||||||
IteHtable I;
|
IteHtable I;
|
||||||
if (!_IsInHtable(cell,I))
|
if (!_IsInHtable(cell,I))
|
||||||
_InsertNewHentry(s,cell);
|
_InsertNewHentry(s,cell);
|
||||||
else///there is the entry specified by the iterator I so update only the temporary mark
|
else///there is the entry specified by the iterator I so update only the temporary mark
|
||||||
(*I).second.Update(s,tempMark);
|
(*I).second.Update(s,tempMark);
|
||||||
|
|
||||||
//Assert();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashing
|
// hashing
|
||||||
const int Hash(Point3i p) const
|
const int Hash(Point3i p) const
|
||||||
{
|
{
|
||||||
//vcg::Point3i dim(100,100,100);
|
return ((p.V(0)*P0 ^ p.V(1)*P1 ^ p.V(2)*P2)%HashSpace);
|
||||||
return ((p.V(0)*P0 ^ p.V(1)*P1 ^ p.V(2)*P2)%num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///return the cells intersected by the Bounding box of the simplex
|
|
||||||
virtual void BoxCells(CoordType _min,CoordType _max,std::vector<Point3i>& ret)
|
|
||||||
{
|
|
||||||
ret.clear();
|
|
||||||
Point3i MinI=PointToCell(_min);
|
|
||||||
Point3i MaxI=PointToCell(_max);
|
|
||||||
int dimx=abs(MaxI.V(0)-MinI.V(0));
|
|
||||||
int dimy=abs(MaxI.V(1)-MinI.V(1));
|
|
||||||
int dimz=abs(MaxI.V(2)-MinI.V(2));
|
|
||||||
|
|
||||||
for (int x=0;x<=dimx;x++)
|
|
||||||
for (int y=0;y<=dimy;y++)
|
|
||||||
for (int z=0;z<=dimz;z++)
|
|
||||||
{
|
|
||||||
Point3i cell=Point3i(MinI.V(0)+x,MinI.V(1)+y,MinI.V(2)+z);
|
|
||||||
ret.push_back(cell);
|
|
||||||
}
|
|
||||||
assert(ret.size()!=0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*void getAtCell(Point3i _c,std::vector<ElemType*> & res)
|
|
||||||
{
|
|
||||||
std::vector<ElemType> result;
|
|
||||||
int h=Hash(_c);
|
|
||||||
if (numElemCell(_c)!=0){
|
|
||||||
IteHtable h_res=hash_table.find(h);
|
|
||||||
((*h_res).second.Elems(tempMark,res));
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
Point3i PointToCell(CoordType p)
|
|
||||||
{
|
|
||||||
int x=(int)floor((p.V(0)-(ScalarType)min.V(0))/(ScalarType)l);
|
|
||||||
int y=(int)floor((p.V(1)-(ScalarType)min.V(1))/(ScalarType)l);
|
|
||||||
int z=(int)floor((p.V(2)-(ScalarType)min.V(2))/(ScalarType)l);
|
|
||||||
return (vcg::Point3i(x,y,z));
|
|
||||||
}
|
|
||||||
|
|
||||||
CoordType CellToPoint(Point3i c)
|
|
||||||
{
|
|
||||||
ScalarType x=(((ScalarType)c.V(0)+min.V(0))*(ScalarType)l);
|
|
||||||
ScalarType y=(((ScalarType)c.V(1)+min.V(1))*(ScalarType)l);
|
|
||||||
ScalarType z=(((ScalarType)c.V(2)+min.V(2))*(ScalarType)l);
|
|
||||||
return (CoordType(x,y,z));
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
///initialize the structure HashSpace is one estimation about
|
///We need some extra space for numerical precision.
|
||||||
///how many keys the system have to generate in order to obtain as less
|
template <class Box3Type>
|
||||||
///conflicts as possible
|
void SetBBox( const Box3Type & b )
|
||||||
void Init(CoordType _min,CoordType _max,ScalarType _l,int HashSpace=1000)
|
|
||||||
{
|
{
|
||||||
l=_l;
|
bbox.Import( b );
|
||||||
min=_min;
|
ScalarType t = bbox.Diag()/100.0;
|
||||||
max=_max;
|
if(t == 0) t = ScalarType(1e20); // <--- Some doubts on this (Cigno 5/1/04)
|
||||||
num=HashSpace;
|
bbox.Offset(t);
|
||||||
tempMark=0;
|
dim = bbox.max - bbox.min;
|
||||||
conflicts=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<Point3i> AddElem( ElemType* s)
|
virtual vcg::Box3i Add( ObjType* s)
|
||||||
{
|
{
|
||||||
std::vector<Point3i> box;
|
/*std::vector<Point3i> box;
|
||||||
BoxCells(s->BBox().min,s->BBox().max,box);
|
BoxCells(s->BBox().min,s->BBox().max,box);
|
||||||
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
|
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)*/
|
||||||
_InsertInCell(s,*bi);
|
Box3<ScalarType> b;
|
||||||
|
s->GetBBox(b);
|
||||||
|
vcg::Box3i bb;
|
||||||
|
BoxToIBox(b,bb);
|
||||||
|
//then insert all the cell of bb
|
||||||
|
for (int i=bb.min.X();i<=bb.max.X();i++)
|
||||||
|
for (int j=bb.min.Y();j<=bb.max.Y();j++)
|
||||||
|
for (int k=bb.min.Z();k<=bb.max.Z();k++)
|
||||||
|
_InsertInCell(s,vcg::Point3i(i,j,k));
|
||||||
|
|
||||||
return box;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void AddElem( ElemType* s)
|
/// Insert a mesh in the grid.SetBBox() function must be called before
|
||||||
|
/// Hash space is cardinality of hash key set
|
||||||
|
void Set( ContainerType & s)
|
||||||
|
{
|
||||||
|
Set(s,s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert a mesh in the grid.SetBBox() function must be called before
|
||||||
|
void Set( ContainerType & s,int _size )
|
||||||
|
{
|
||||||
|
Point3i _siz;
|
||||||
|
BestDim( _size, dim, _siz );
|
||||||
|
Set(s,_siz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert a mesh in the grid.SetBBox() function must be called before
|
||||||
|
void Set(ContainerType & s, Point3i _siz)
|
||||||
|
{
|
||||||
|
siz=_siz;
|
||||||
|
// find voxel size
|
||||||
|
voxel[0] = dim[0]/siz[0];
|
||||||
|
voxel[1] = dim[1]/siz[1];
|
||||||
|
voxel[2] = dim[2]/siz[2];
|
||||||
|
typename ContainerType::iterator i;
|
||||||
|
for(i = s.begin(); i!= s.end(); ++i)
|
||||||
|
Add(&(*i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////initialize the structure HashSpace is one estimation about
|
||||||
|
/////how many keys the system have to generate in order to obtain as less
|
||||||
|
/////conflicts as possible
|
||||||
|
//void Init(CoordType _min,CoordType _max,ScalarType _l,int HashSpace=1000)
|
||||||
|
//{
|
||||||
|
// l=_l;
|
||||||
|
// min=_min;
|
||||||
|
// max=_max;
|
||||||
|
// HashSpace=HashSpace;
|
||||||
|
// tempMark=0;
|
||||||
|
// conflicts=0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*void AddElem( ObjType* s)
|
||||||
{
|
{
|
||||||
std::vector<Point3i> box;
|
std::vector<Point3i> box;
|
||||||
BoxCells(s->BBox().min,s->BBox().max,box);
|
BoxCells(s->BBox().min,s->BBox().max,box);
|
||||||
|
@ -561,118 +477,51 @@ namespace vcg{
|
||||||
_InsertInCell(s,*bi);
|
_InsertInCell(s,*bi);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
template<class ContElemType>
|
///return the simplexes of the cell that contain p
|
||||||
void AddElems( ContElemType & elem_set)
|
void Grid( const Point3d & p, CellIterator & first, CellIterator & last )
|
||||||
{
|
{
|
||||||
typename ContElemType::iterator i;
|
IteHtable I;
|
||||||
for(i = elem_set.begin(); i!= elem_set.end(); ++i)
|
vcg::Point3i _c;
|
||||||
AddElem(&(*i));
|
PToIP(p,_c);
|
||||||
|
Grid(_c,first,last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////*********************************************************************
|
|
||||||
//template <class A>
|
|
||||||
// bool usefirst(const A & a,const A & b)const {return a.first < b.first;}
|
|
||||||
|
|
||||||
int ClosestK(const int& k,ElemType* e, std::vector<ElemType*>& res)
|
|
||||||
{
|
|
||||||
typedef std::pair<ScalarType,ElemType*> ElemDist;
|
|
||||||
std::vector<ElemDist > neigh_dist;
|
|
||||||
std::vector<ElemDist >::iterator ite_nd;
|
|
||||||
std::vector<ElemType* > neigh;
|
|
||||||
std::vector<ElemType*>::iterator i_neigh;
|
|
||||||
typename ElemType::CoordType p = e->P();
|
|
||||||
ScalarType radius,tmp,d;
|
|
||||||
|
|
||||||
// set the radius as the distance to the closest face
|
|
||||||
radius = p[2]-floor(p[2]/l)*l;
|
|
||||||
if(radius > l*0.5) radius = l -radius;
|
|
||||||
tmp = p[1]-floor(p[1]/l)*l;
|
|
||||||
if(tmp > l*0.5) tmp = l -tmp;
|
|
||||||
if(radius > tmp) tmp = radius;
|
|
||||||
tmp = p[0]-floor(p[0]/l)*l;
|
|
||||||
if(tmp > l*0.5) tmp = l -tmp;
|
|
||||||
if(radius > tmp) radius = tmp;
|
|
||||||
|
|
||||||
int x,y,z;
|
|
||||||
vcg::Point3i mincorner,maxcorner,c;
|
|
||||||
c = PointToCell(p);
|
|
||||||
mincorner = maxcorner = c;
|
|
||||||
neigh_dist.push_back(ElemDist(-1,e));
|
|
||||||
ite_nd = neigh_dist.begin();
|
|
||||||
|
|
||||||
while((int)res.size() < k)
|
|
||||||
{
|
|
||||||
|
|
||||||
//run on the border
|
|
||||||
for( z = mincorner[2]; z <= maxcorner[2]; ++z)
|
|
||||||
for( y = mincorner[1]; y <= maxcorner[1]; ++y)
|
|
||||||
for( x = mincorner[0]; x <= maxcorner[0];)
|
|
||||||
{
|
|
||||||
|
|
||||||
neigh.clear();
|
|
||||||
getAtCell(vcg::Point3i(x,y,z),neigh);
|
|
||||||
for(i_neigh = neigh.begin(); i_neigh != neigh.end(); ++i_neigh)
|
|
||||||
{
|
|
||||||
d = Distance(p,(*i_neigh)->P());
|
|
||||||
if( (*i_neigh) != e)
|
|
||||||
neigh_dist.push_back(ElemDist(d,*i_neigh));
|
|
||||||
}
|
|
||||||
if(
|
|
||||||
( ( y == mincorner[1]) || ( y == maxcorner[1])) ||
|
|
||||||
( ( z == mincorner[2]) || ( z == maxcorner[2])) ||
|
|
||||||
( x == maxcorner[0])
|
|
||||||
)++x; else x=maxcorner[0];
|
|
||||||
}
|
|
||||||
// ,usefirst<ElemDist> ---<std::vector<ElemDist >::iterator >
|
|
||||||
ite_nd =neigh_dist.begin();
|
|
||||||
std::advance(ite_nd,res.size());
|
|
||||||
std::sort(ite_nd,neigh_dist.end());
|
|
||||||
while ( ( (int)res.size() < k ) && (ite_nd != neigh_dist.end()))
|
|
||||||
{
|
|
||||||
if((*ite_nd).first < radius)
|
|
||||||
res.push_back( (*ite_nd).second );
|
|
||||||
++ite_nd;
|
|
||||||
}
|
|
||||||
|
|
||||||
mincorner -= vcg::Point3i(1,1,1);
|
|
||||||
maxcorner += vcg::Point3i(1,1,1);
|
|
||||||
radius+=l;
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//**********************************************************************
|
|
||||||
|
|
||||||
///return the simplexes on a specified cell
|
///return the simplexes on a specified cell
|
||||||
void getAtCell(Point3i _c,std::vector<ElemType*> & res)
|
void Grid( int x,int y,int z, CellIterator & first, CellIterator & last )
|
||||||
|
{
|
||||||
|
Grid(vcg::Point3i(x,y,z),first,last);
|
||||||
|
}
|
||||||
|
|
||||||
|
///return the simplexes on a specified cell
|
||||||
|
void Grid( const Point3i & _c, CellIterator & first, CellIterator & last )
|
||||||
|
{
|
||||||
|
IteHtable I;
|
||||||
|
if (_IsInHtable(_c,I))//if there is the cell then
|
||||||
|
{ ///return pointers to first and last element cell elems
|
||||||
|
first= &*(*I).second._entries.begin();
|
||||||
|
last= &*(*I).second._entries.end();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ ///return 2 equals pointers
|
||||||
|
first=&*(*hash_table.begin()).second._entries.begin();
|
||||||
|
last= &*(*hash_table.begin()).second._entries.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getAtCell(Point3i _c,std::vector<ObjType*> & res)
|
||||||
{
|
{
|
||||||
IteHtable I;
|
IteHtable I;
|
||||||
if (_IsInHtable(_c,I))//if there is the cell then
|
if (_IsInHtable(_c,I))//if there is the cell then
|
||||||
(*I).second.Elems(res);
|
(*I).second.Elems(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the elem closer than radius
|
|
||||||
int CloserThan( typename ElemType::CoordType p,
|
|
||||||
typename ElemType::ScalarType radius,
|
|
||||||
std::vector<ElemType*> & closers){
|
|
||||||
ClosersIterator cli;
|
|
||||||
cli.Init(this,p,radius);
|
|
||||||
while(!cli.End()){
|
|
||||||
if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius))// &&(*cli.curr_i).second >= tempMark)
|
|
||||||
closers.push_back(*cli);
|
|
||||||
++cli;
|
|
||||||
}
|
|
||||||
return (int)closers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Point3i> Cells(ElemType *s)
|
std::vector<Point3i> Cells(ObjType *s)
|
||||||
{
|
{
|
||||||
return BoxCells(s,s->BBox().min,s->BBox().max);
|
return BoxCells(s,s->BBox().min,s->BBox().max);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Point3i MinCell()
|
/*inline Point3i MinCell()
|
||||||
{
|
{
|
||||||
return PointToCell(min);
|
return PointToCell(min);
|
||||||
}
|
}
|
||||||
|
@ -680,18 +529,6 @@ namespace vcg{
|
||||||
inline Point3i MaxCell()
|
inline Point3i MaxCell()
|
||||||
{
|
{
|
||||||
return PointToCell(max);
|
return PointToCell(max);
|
||||||
}
|
|
||||||
|
|
||||||
/*inline int numElemCell(Point3i _c)
|
|
||||||
{
|
|
||||||
int h=Hash(_c);
|
|
||||||
if (hash_table.count(h)==0)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IteHtable Ih=hash_table.find(h);
|
|
||||||
return ((*Ih).second.Size());
|
|
||||||
}
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
///return the number of elemnts in the cell and the iterator to the cell
|
///return the number of elemnts in the cell and the iterator to the cell
|
||||||
|
@ -704,20 +541,6 @@ namespace vcg{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*inline bool IsEmptyCell(Point3i _c)
|
|
||||||
{
|
|
||||||
return(numElemCell(_c)==0);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*inline bool IsEmptyCell(Point3i _c)
|
|
||||||
{
|
|
||||||
int h=Hash(_c);
|
|
||||||
if (hash_table.count(h)==0)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
///return the number of cell created
|
///return the number of cell created
|
||||||
int CellNumber()
|
int CellNumber()
|
||||||
{return (hash_table.size());}
|
{return (hash_table.size());}
|
||||||
|
@ -730,30 +553,15 @@ namespace vcg{
|
||||||
hash_table.clear();
|
hash_table.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetHashSpace()
|
||||||
|
{
|
||||||
|
HashSpace
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateTmark()
|
void UpdateTmark()
|
||||||
{tempMark++;}
|
{tempMark++;}
|
||||||
|
|
||||||
///only debug
|
|
||||||
void DrawCell(HElement &c)
|
|
||||||
{
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslate(c.Min()+vcg::Point3d(l/2,l/2,l/2));
|
|
||||||
glutWireCube(l);
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Draw()
|
|
||||||
{
|
|
||||||
for (IteHtable I=hash_table.begin();I!=hash_table.end();I++)
|
|
||||||
DrawCell((*I).second);
|
|
||||||
}
|
|
||||||
|
|
||||||
///only debug
|
|
||||||
void Assert()
|
|
||||||
{
|
|
||||||
for (IteHtable I=hash_table.begin();I!=hash_table.end();I++)
|
|
||||||
(((*I).second).Assert());
|
|
||||||
}
|
|
||||||
}; // end class
|
}; // end class
|
||||||
|
|
||||||
}// end namespace
|
}// end namespace
|
||||||
|
|
Loading…
Reference in New Issue