use of standard grid interface

use of vector instead of map inside the cell
removed closest iterator
This commit is contained in:
Nico Pietroni 2005-09-19 13:35:45 +00:00
parent be78e8d97f
commit 54c8562e3a
1 changed files with 333 additions and 525 deletions

View File

@ -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