resolved hash code conflicts

This commit is contained in:
Nico Pietroni 2005-06-01 13:47:59 +00:00
parent 536ba5ab48
commit cd855e4e57
1 changed files with 621 additions and 349 deletions

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.5 2005/03/15 09:50:44 ganovelli
there was a debug line, now removed
Revision 1.4 2005/03/14 15:11:18 ganovelli
ClosestK added and other minor changes
@ -71,156 +74,326 @@ public:
typedef typename CoordType::ScalarType ScalarType;
//element of a cell
typedef typename std::pair<ElemType*,int> MapCellElem;
//type of entries element of a cell
typedef typename std::pair<ElemType*,int> EntryType;
//element stored in the hash table
//This Class Identify the cell
struct HElement
{
private:
///the min and max point corresponding to the cell - used to inverse hashing
CoordType min;//coordinate min of the cell
CoordType max;//coordinate max of the cell
Point3i cell_n;//cell number
public:
//elements
std::map<ElemType*,int> _entries;
//iterator to the map element into the cell
typedef typename std::map<ElemType*,int>::iterator IteMap;
std::map<ElemType*,int> elem;
//int flag;
public:
HElement()
{
// flag=0;
}
{}
HElement(ElemType* sim,const int &_tempMark)
HElement(ElemType* sim,const int &_tempMark,CoordType _min,CoordType _max,Point3i _cell)
{
elem.insert(MapCellElem(sim,_tempMark));
// flag=0;
_entries.insert(EntryType(sim,_tempMark));
min=_min;
max=_max;
assert(min<max);
cell_n=_cell;
}
///return true if the element is in the cell
bool IsIn(ElemType* sim)
{
int n=elem.count(sim);
{int n=elem.count(sim);
return (n==1);
}
///return the number of elements stored in the cell
int Size()
{
return (int)(elem.size());
}
{return (int)(_entries.size());}
///update or insert an element into a cell
void Update(ElemType* sim, const int & _tempMark)
{
std::pair<IteMap, bool> res=elem.insert(MapCellElem(sim,_tempMark));
//the element was already in the map structure so update the temporary mark
if (res.second==false)
{
//update the temporary mark
IteMap ite=res.first;
(*ite).second=_tempMark;
}
IteMap I=_entries.find(sim);
if (I!=_entries.end())//the entry exist in the cell
(*I).second=_tempMark;
else
_entries.insert(_entries.begin(),EntryType(sim,_tempMark));
//at the end update the temporary mark on the simplex
sim->Mark()=_tempMark;
}
//return an array of all simplexes of the map that have a right timestamp or are not deleted
void Elems(const int & _tempMark,std::vector<ElemType*> & res)
///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(IteMap &I)
{
/* if ((*I).second >= (*I).first->Mark())
return true;
else
{
printf("DISUPDATED\N");
return false;
}*/
return ((*I).second >= (*I).first->Mark());
}
for (IteMap ite=elem.begin();ite!=elem.end();ite++)
///given an simplex pointer
///return true if the the entry corripondent to that
///simplex is valid or not
///(using temporary mark).
bool IsUpdated(ElemType* sim)
{
IteMap I=_entries.find(sim);
if (I!=_entries.end())
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<ElemType*> & res)
{
for (IteMap ite=_entries.begin();ite!=_entries.end();ite++)
{
ElemType* sim=(*ite).first;
int t=(*ite).second;
if ((!sim->IsD())&&(t>=_tempMark))
if (IsUpdated(ite)&&(!sim->IsD()))
res.push_back(sim);
}
}
CoordType Min()
{return min;}
CoordType Max()
{return max;}
Point3i CellN()
{return cell_n;}
bool operator ==(const HElement &h)
{return (cell_n==h.CellN());}
bool operator !=(const HElement &h)
{return ((cell_n!=h.CellN()));}
}; // end struct HElement
///this Iterator returns all the elements that
///are in a specified box.
struct ClosersIterator{
private:
CoordType p;
SpatialHashTable<ElemType> * sh;
vcg::Point3i mincorner,maxcorner;
ScalarType sq_radius;
SpatialHashTable<ElemType> * sh; ///pointer to spatial hash table structure
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
// current position
vcg::Point3i curr_ic; // triple corresponding to the cell
HElement * curr_c; // current cell
typename HElement::IteMap curr_i; // current iterator
bool end;
bool Advance(){
if(curr_ic[0] < maxcorner[0]) ++curr_ic[0];
///advance the current coordinate of one step inside the space box
///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];
if(curr_ic[1] < maxcorner[1])
++curr_ic[1];
else{
if(curr_ic[2] < maxcorner[2]) ++curr_ic[2];
if(curr_ic[2] < maxcorner[2])
++curr_ic[2];
else
return false;
end=true;
curr_ic[1] = mincorner[1];
}
curr_ic[0] = mincorner[0];
}
curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
return true;
}
void Init(SpatialHashTable<ElemType> * _sh, CoordType _p, const ScalarType &_radius)
{
sh = _sh;
p =_p;
CoordType halfDiag(_radius,_radius,_radius);
mincorner = sh->Cell(p-halfDiag);
maxcorner = sh->Cell(p+halfDiag);
curr_ic = mincorner;
sq_radius = _radius * _radius;
IteHtable iht = sh->hash_table.find(sh->Hash(curr_ic));
// initialize the iterator to the first element
bool isempty = (iht == sh->hash_table.end());
if(isempty)
while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
if(!isempty){
curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
curr_i = curr_c->elem.begin();
end = false;
}
else
end = true;
}
void operator ++() {
bool isempty = true;
HElement::IteMap e = curr_c->elem.end();
//operator Next
//go to next simplex without considering temporary mark
void Next() {
SpatialHashTable<ElemType>::IteHtable I;
HElement::IteMap e = curr_c->_entries.end();
--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{
while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
if(!isempty){
curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
curr_i = curr_c->elem.begin();
///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:
/////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)
//{
// sh = _sh;
// p =_p;
// ///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;
// ///find the cell corrisponding to first podsition
// IteHtable iht = sh->hash_table.find(sh->Hash(curr_ic));
// ///advance until find a cell that contain at least one updated element
// //and initialize the current cell and iterator inside it
// bool isempty = (iht == sh->hash_table.end());
// if(isempty)
// while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
// if(!isempty){
// curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
// curr_i = curr_c->_entries.begin();
// end = false;
// }
// else
// end = true;
//}
void AssertUpdated()
{
ScalarType Xs=(*curr_i).first->P().X();
ScalarType Ys=(*curr_i).first->P().Y();
ScalarType Zs=(*curr_i).first->P().Z();
ScalarType Xm=curr_c->Min().X();
ScalarType Ym=curr_c->Min().Y();
ScalarType Zm=curr_c->Min().Z();
ScalarType XM=curr_c->Max().X();
ScalarType YM=curr_c->Max().Y();
ScalarType ZM=curr_c->Max().Z();
if ((Xs<Xm)||(Xs>XM)||(Ys<Ym)||(Ys>YM)||(Zs<Zm)||(Zs>ZM))
printf("ERROR %d %d %d %d %d");
}
///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
end = true;
{///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
// while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
// if(!isempty){
// curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
// curr_i = curr_c->_entries.begin();
// }
// else
// end = true;
// }
//}
///operator ++ of the itearator
void operator ++()
{
Next();
while ((!curr_c->IsUpdated(curr_i))&&(!end))
Next();
assert(curr_c->IsUpdated(curr_i)||(end));
}
///dereferent operator
ElemType * operator *(){
return (*curr_i).first;
}
///return true if the scanning of elements is complete
bool End(){
//bool __ = (curr_i == curr_c->elem.end());
//return ( (curr_ic == maxcorner) && (curr_i == curr_c->elem.end()) );
return end;
}
}; // end struct CloserIterator
//hash table definition
typedef typename STDEXT::hash_map<int,HElement> Htable;
//typedef typename STDEXT::hash_map<int,HElement> 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
typedef typename std::pair<int,HElement> HRecord;
//iterator to the hash table
@ -229,6 +402,7 @@ public:
SpatialHashTable(){};
~SpatialHashTable(){};
private:
//ContSimplex & _simplex;
int tempMark;
@ -241,56 +415,73 @@ public:
CoordType min;
CoordType max;
int conflicts;
/*Point3i min;
Point3i max;*/
void Init(CoordType _min,CoordType _max,ScalarType _l)
{
min=_min;
max=_max;
l=_l;
CoordType d=max-min;
//num = (int) floor(d.V(0)*d.V(1)*d.V(2)/l);
num = (int) floor(100*d.V(0)*d.V(1)*d.V(2)/l);
tempMark=0;
}
void InsertInCell(ElemType* s,Point3i cell)
///insert a new cell
void _InsertNewHentry(ElemType* s,Point3i cell)
{
int h=Hash(cell);
//insert a cell if there isn't
if (hash_table.count(h)==0)
hash_table.insert(HRecord(h,HElement(s,tempMark)));
//otherwise insert the element or update the temporary mark
CoordType _min;
CoordType _max;
_min=CellToPoint(cell);
_max=_min+CoordType(l,l,l);
hash_table.insert(HRecord(h,HElement(s,tempMark,_min,_max,cell)));
s->Mark()=tempMark;
}
bool _IsInHtable(Point3i cell,IteHtable &result)
{
int h=Hash(cell);
int count=hash_table.count(h);
if (count==0)///in this case there is no entry for that key
return false;
else
{
IteHtable HI=hash_table.find(h);
// (*HI).second.flag|=_flag;
(*HI).second.Update(s,tempMark);
}
}
////std::pair<Htable::const_iterator, Htable::const_iterator> p =hash_table.equal_range(h);
std::pair<IteHtable, IteHtable> p =hash_table.equal_range(h);
IteHtable i = p.first;
while((i != p.second)&&((*i).second.CellN()!=cell))++i;
std::vector<Point3i> AddElem( ElemType* s)
if (i==p.second)///the scan is terminated and we have not fuond the cell
{
std::vector<Point3i> box=BoxCells(s->BBox().min,s->BBox().max);
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
InsertInCell(s,*bi);
return box;
conflicts++;
return false;
}
else ///we have found the right cell
{
result=i;
return true;
}
}
}
template<class ContElemType>
void AddElems( ContElemType & elem_set)
///insert an element in a specified cell if the cell doesn't exist than
///create it.
void _InsertInCell(ElemType* s,Point3i cell)
{
typename ContElemType::iterator i;
for(i = elem_set.begin(); i!= elem_set.end(); ++i)
AddElem(&(*i));
IteHtable I;
if (!_IsInHtable(cell,I))
_InsertNewHentry(s,cell);
else///there is the entry specified by the iterator I so update only the temporary mark
(*I).second.Update(s,tempMark);
}
std::vector<Point3i> BoxCells(CoordType _min,CoordType _max)
// hashing
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)%num);
}
///return the cells intersected by the Bounding box of the simplex
void BoxCells(CoordType _min,CoordType _max,std::vector<Point3i>& ret)
{
std::vector<Point3i> ret;
ret.clear();
Point3i MinI=Cell(_min);
Point3i MaxI=Cell(_max);
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));
@ -302,17 +493,91 @@ public:
Point3i cell=Point3i(MinI.V(0)+x,MinI.V(1)+y,MinI.V(2)+z);
ret.push_back(cell);
}
return ret;
assert(ret.size()!=0);
}
//*********************************************************************
template <class A>
bool usefirst(const A & a,const A & b)const {return a.first < b.first;}
/*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));
}
}*/
int ClosestK(const int& k,
ElemType* e,
std::vector<ElemType*>& res) {
///add to the vector the simplexes with that eddress
void getAtCell(Point3i _c,std::vector<ElemType*> & res)
{
int h=Hash(_c);
IteHtable I;
if (_IsInHtable(_c,I))//if there is the cell then
(*I).second.Elems(res);
}
Point3i PointToCell(CoordType p)
{
int x=(int)floor((p.V(0)-(ScalarType)min.V(0))/l);
int y=(int)floor((p.V(1)-(ScalarType)min.V(1))/l);
int z=(int)floor((p.V(2)-(ScalarType)min.V(2))/l);
return (vcg::Point3i(x,y,z));
}
CoordType CellToPoint(Point3i c)
{
ScalarType x=(((ScalarType)c.V(0)+min.V(0))*l);
ScalarType y=(((ScalarType)c.V(1)+min.V(1))*l);
ScalarType z=(((ScalarType)c.V(2)+min.V(2))*l);
return (CoordType(x,y,z));
}
public:
///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;
num=HashSpace;
tempMark=0;
conflicts=0;
}
std::vector<Point3i> AddElem( ElemType* s)
{
std::vector<Point3i> box;
BoxCells(s->BBox().min,s->BBox().max,box);
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
_InsertInCell(s,*bi);
return box;
}
/*void AddElem( ElemType* s)
{
std::vector<Point3i> box;
BoxCells(s->BBox().min,s->BBox().max,box);
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
_InsertInCell(s,*bi);
}*/
template<class ContElemType>
void AddElems( ContElemType & elem_set)
{
typename ContElemType::iterator i;
for(i = elem_set.begin(); i!= elem_set.end(); ++i)
AddElem(&(*i));
}
////*********************************************************************
//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;
@ -333,7 +598,7 @@ public:
int x,y,z;
vcg::Point3i mincorner,maxcorner,c;
c = Cell(p);
c = PointToCell(p);
mincorner = maxcorner = c;
neigh_dist.push_back(ElemDist(-1,e));
ite_nd = neigh_dist.begin();
@ -389,8 +654,7 @@ public:
ClosersIterator cli;
cli.Init(this,p,radius);
while(!cli.End()){
if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius) &&
(*cli.curr_i).second >= tempMark)
if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius))// &&(*cli.curr_i).second >= tempMark)
closers.push_back(*cli);
++cli;
}
@ -404,15 +668,15 @@ public:
inline Point3i MinCell()
{
return Cell(min);
return PointToCell(min);
}
inline Point3i MaxCell()
{
return Cell(max);
return PointToCell(max);
}
inline int numElemCell(Point3i _c)
/*inline int numElemCell(Point3i _c)
{
int h=Hash(_c);
if (hash_table.count(h)==0)
@ -422,58 +686,66 @@ public:
IteHtable Ih=hash_table.find(h);
return ((*Ih).second.Size());
}
}*/
///return the number of elemnts in the cell ond the iterator to the cell
///if the cell exist
int numElemCell(Point3i _c,IteHtable &I)
{
int h=Hash(_c);
if (_IsInHtable(_c,I))
return ((*I).second.Size());
else
return 0;
}
inline bool IsEmptyCell(Point3i _c)
/*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
int CellNumber()
{return (hash_table.size());}
int Conflicts()
{return conflicts;}
void Clear()
{
hash_table.clear();
}
//void std::vector<ElemType> getAt(CoordType _p,std::vector<ElemType> & res)
//{
// std::vector<ElemType> result;
// Point3i c=Cell(_p);
// return (getAtCell(c,res));
//}
void UpdateTmark()
{tempMark++;}
void getAtCell(Point3i _c,std::vector<ElemType*> & res)
///only debug
void DrawCell(HElement &c)
{
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));
}
glPushMatrix();
glTranslate(c.Min()+vcg::Point3d(l/2,l/2,l/2));
glutWireCube(l);
glPopMatrix();
}
const Point3i Cell(const CoordType & p) const
void Draw()
{
int x=(int)floor(p.V(0)/l);
int y=(int)floor(p.V(1)/l);
int z=(int)floor(p.V(2)/l);
return Point3i(x,y,z);
for (IteHtable I=hash_table.begin();I!=hash_table.end();I++)
DrawCell((*I).second);
}
// hashing
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)%num);
// return ( p[2]-min[2] )* dim[0]*dim[1] +
// ( p[1]-min[1] )* dim[1] +
// ( p[0]-min[0] );
}
private:
///only debug
}; // end class
}// end namespace