vcglib/vcg/space/index/spatial_hashing.h

484 lines
12 KiB
C
Raw Normal View History

2005-02-21 13:13:25 +01:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
2005-09-21 16:22:49 +02:00
Revision 1.8 2005/09/19 13:35:45 pietroni
use of standard grid interface
use of vector instead of map inside the cell
removed closest iterator
Revision 1.7 2005/06/15 11:44:47 pietroni
minor changes
2005-06-15 13:44:47 +02:00
Revision 1.6 2005/06/01 13:47:59 pietroni
resolved hash code conflicts
2005-06-01 15:47:59 +02:00
Revision 1.5 2005/03/15 09:50:44 ganovelli
there was a debug line, now removed
2005-03-15 10:50:44 +01:00
Revision 1.4 2005/03/14 15:11:18 ganovelli
ClosestK added and other minor changes
2005-03-14 16:11:18 +01:00
Revision 1.3 2005/03/11 15:25:29 ganovelli
added ClosersIterator and other minor changes. Not compatible with the previous version.
Still other modifications to do (temporary commit)
Revision 1.2 2005/02/21 12:13:25 ganovelli
added vcg header
2005-02-21 13:13:25 +01:00
****************************************************************************/
#ifndef VCGLIB_SPATIAL_HASHING
#define VCGLIB_SPATIAL_HASHING
2004-12-16 19:00:51 +01:00
#define P0 73856093
#define P1 19349663
#define P2 83492791
2004-12-16 19:00:51 +01:00
#include <vcg/space/index/grid_util.h>
//#include <map>
2004-12-16 19:00:51 +01:00
#include <vector>
2005-03-14 16:11:18 +01:00
#include <algorithm>
#ifdef WIN32
2005-06-01 15:47:59 +02:00
#include <hash_map>
#define STDEXT stdext
#else
2005-06-01 15:47:59 +02:00
#include <ext/hash_map>
#define STDEXT __gnu_cxx
#endif
namespace vcg{
2005-09-21 16:22:49 +02:00
2005-06-01 15:47:59 +02:00
/** Spatial Hash Table
Spatial Hashing as described in
"Optimized Spatial Hashing for Coll ision Detection of Deformable Objects",
2005-06-01 15:47:59 +02:00
Matthias Teschner and Bruno Heidelberger and Matthias Muller and Danat Pomeranets and Markus Gross
*/
2005-09-21 16:22:49 +02:00
template < typename ContainerType,class FLT=double>
class SpatialHashTable:public BasicGrid<FLT>
{
2005-06-01 15:47:59 +02:00
public:
typedef typename ContainerType::value_type ObjType;
typedef ObjType* ObjPtr;
typedef typename ObjType::ScalarType ScalarType;
typedef Point3<ScalarType> CoordType;
2005-06-01 15:47:59 +02:00
//type of container of pointer to object in a Cell
//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;
}
2004-12-16 19:00:51 +01:00
ObjType& operator *(){return (*this->first);}
};
typedef typename std::vector<EntryType> CellContainerType;
typedef typename CellContainerType::iterator IteMap;
typedef typename EntryType* CellIterator;
2005-09-21 16:22:49 +02:00
//This Class Identify the cell
struct Cell
2004-12-16 19:00:51 +01:00
{
2005-09-21 16:22:49 +02:00
protected:
2005-06-01 15:47:59 +02:00
///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
2005-06-01 15:47:59 +02:00
Point3i cell_n;//cell number
//iterator to the map element into the cell
//typedef typename CellContainerType::iterator IteMap;
2005-06-01 15:47:59 +02:00
public:
//elements
CellContainerType _entries;
Cell()
2005-06-01 15:47:59 +02:00
{}
2004-12-16 19:00:51 +01:00
Cell(ObjType* sim,Point3i _cell,const int &_tempMark)
2004-12-16 19:00:51 +01:00
{
_entries.push_back(EntryType(sim,_tempMark));
/*min=_min;
2005-06-01 15:47:59 +02:00
max=_max;
assert(min<max);*/
2005-06-01 15:47:59 +02:00
cell_n=_cell;
2004-12-16 19:00:51 +01:00
}
2005-06-01 15:47:59 +02:00
///return the number of elements stored in the cell
2004-12-16 19:00:51 +01:00
int Size()
2005-06-01 15:47:59 +02:00
{return (int)(_entries.size());}
///find the simplex into the cell
bool Find(ObjType* sim,IteMap &I)
2004-12-16 19:00:51 +01:00
{
for (I=_entries.begin();I<_entries.end();I++)
if ((*I).first==sim)
return true;
return false;
}
2005-06-01 15:47:59 +02:00
///update or insert an element into a cell
void Update(ObjType* sim, const int & _tempMark)
{
IteMap I;
2005-09-21 16:22:49 +02:00
if (Find(sim,I))
{///update temporary mark
(*I).second=_tempMark;
}
2005-06-01 15:47:59 +02:00
else
_entries.push_back(EntryType(sim,_tempMark));
2005-06-01 15:47:59 +02:00
2005-09-21 16:22:49 +02:00
////at the end update the temporary mark on the simplex
//_UpdateHMark(sim);
2005-06-15 13:44:47 +02:00
//Assert();
2005-06-01 15:47:59 +02:00
}
2005-09-21 16:22:49 +02:00
/////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 (Use_Mark)
// return ((*I).second >= (*I).first->HMark());
// else
// return true;
//}
2005-06-01 15:47:59 +02:00
2005-09-21 16:22:49 +02:00
/////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)
//{
// if (Use_Mark)
// {
// IteMap I;
// if (Find(sim,I))
// return(IsUpdated(I));
// else
// return false;
// }
// else return true;
//}
2005-03-14 16:11:18 +01:00
2005-06-01 15:47:59 +02:00
Point3i CellN()
{return cell_n;}
bool operator ==(const Cell &h)
2005-06-01 15:47:59 +02:00
{return (cell_n==h.CellN());}
bool operator !=(const Cell &h)
2005-06-01 15:47:59 +02:00
{return ((cell_n!=h.CellN()));}
2005-09-21 16:22:49 +02:00
protected:
virtual void UpdateHMark(ObjType* s){}
}; // end struct Cell
2005-06-01 15:47:59 +02:00
//hash table definition
typedef typename STDEXT::hash_multimap<int,Cell> Htable;
2005-06-01 15:47:59 +02:00
//record of the hash table
typedef typename std::pair<int,Cell> HRecord;
2005-06-01 15:47:59 +02:00
//iterator to the hash table
typedef typename Htable::iterator IteHtable;
SpatialHashTable(){HashSpace=1000;};//default value for hash_space
2005-06-01 15:47:59 +02:00
~SpatialHashTable(){};
2005-06-15 13:44:47 +02:00
int tempMark;
protected:
2005-06-01 15:47:59 +02:00
Htable hash_table;
///number of possible hash code [0...HashSpace]
int HashSpace;
2005-06-01 15:47:59 +02:00
///number of conflicts created
2005-06-01 15:47:59 +02:00
int conflicts;
///insert a new cell
void _InsertNewHentry(ObjType* s,Point3i cell)
2005-06-01 15:47:59 +02:00
{
int h=Hash(cell);
hash_table.insert(HRecord(h,Cell(s,cell,tempMark)));
//Assert();
2005-06-01 15:47:59 +02:00
}
///return true and return the iterator to the cell if exist
2005-06-01 15:47:59 +02:00
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
2004-12-16 19:00:51 +01:00
{
2005-06-01 15:47:59 +02:00
////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;
if (i==p.second)///the scan is terminated and we have not found the right cell
2005-06-01 15:47:59 +02:00
{
conflicts++;
return false;
}
else ///we have found the right cell
{
result=i;
return true;
}
2004-12-16 19:00:51 +01:00
}
}
2005-09-21 16:22:49 +02:00
virtual void _UpdateHMark(ObjType* s){}
2005-06-01 15:47:59 +02:00
///insert an element in a specified cell if the cell doesn't exist than
///create it.
void _InsertInCell(ObjType* s,Point3i cell)
2004-12-16 19:00:51 +01:00
{
2005-06-01 15:47:59 +02:00
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);
2005-09-21 16:22:49 +02:00
_UpdateHMark(s);
2004-12-16 19:00:51 +01:00
}
// hashing
const int Hash(Point3i p) const
2004-12-16 19:00:51 +01:00
{
return ((p.V(0)*P0 ^ p.V(1)*P1 ^ p.V(2)*P2)%HashSpace);
2004-12-16 19:00:51 +01:00
}
2005-06-01 15:47:59 +02:00
public:
///We need some extra space for numerical precision.
template <class Box3Type>
void SetBBox( const Box3Type & b )
2005-06-01 15:47:59 +02:00
{
bbox.Import( b );
ScalarType t = bbox.Diag()/100.0;
if(t == 0) t = ScalarType(1e20); // <--- Some doubts on this (Cigno 5/1/04)
bbox.Offset(t);
dim = bbox.max - bbox.min;
2005-06-01 15:47:59 +02:00
}
virtual vcg::Box3i Add( ObjType* 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++)*/
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 bb;
}
/// 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));
}
2005-06-01 15:47:59 +02:00
/////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;
//}
2005-06-01 15:47:59 +02:00
/*void AddElem( ObjType* s)
2005-06-01 15:47:59 +02:00
{
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 the simplexes of the cell that contain p
void Grid( const Point3d & p, CellIterator & first, CellIterator & last )
2005-06-01 15:47:59 +02:00
{
IteHtable I;
vcg::Point3i _c;
PToIP(p,_c);
Grid(_c,first,last);
}
2005-06-15 13:44:47 +02:00
///return the simplexes on a specified cell
void Grid( int x,int y,int z, CellIterator & first, CellIterator & last )
{
Grid(vcg::Point3i(x,y,z),first,last);
2005-06-01 15:47:59 +02:00
}
///return the simplexes on a specified cell
void Grid( const Point3i & _c, CellIterator & first, CellIterator & last )
2005-06-01 15:47:59 +02:00
{
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;
if (_IsInHtable(_c,I))//if there is the cell then
(*I).second.Elems(res);
}
std::vector<Point3i> Cells(ObjType *s)
{
return BoxCells(s,s->BBox().min,s->BBox().max);
}
/*inline Point3i MinCell()
{
return PointToCell(min);
}
inline Point3i MaxCell()
{
return PointToCell(max);
2005-06-01 15:47:59 +02:00
}*/
///return the number of elemnts in the cell and the iterator to the cell
///if the cell exist
int numElemCell(Point3i _c,IteHtable &I)
2005-06-01 15:47:59 +02:00
{
if (_IsInHtable(_c,I))
return ((*I).second.Size());
else
return 0;
2005-06-01 15:47:59 +02:00
}
///return the number of cell created
int CellNumber()
{return (hash_table.size());}
int Conflicts()
{return conflicts;}
void Clear()
{
hash_table.clear();
}
2005-09-21 16:22:49 +02:00
void SetHashKeySpace(int n)
{
2005-09-21 16:22:49 +02:00
HashSpace=n;
}
void UpdateTmark()
{tempMark++;}
2005-06-01 15:47:59 +02:00
}; // end class
2005-09-21 16:22:49 +02:00
/** Spatial Hash Table Dynamic
Update the Hmark value on the simplex for dynamic updating of contents of the cell.
The simplex must have the HMark() function.
*/
template < typename ContainerType,class FLT=double>
class DynamicSpatialHashTable:SpatialHashTable<ContainerType,FLT>
{
void _UpdateHMark(ObjType* s){s->HMark()=tempMark;}
};
}// end namespace
2005-02-21 13:13:25 +01:00
#undef P0
#undef P1
#undef P2
#endif