first release version

This commit is contained in:
Nico Pietroni 2012-06-22 14:27:33 +00:00
parent 614a5fec16
commit 066f46c20b
4 changed files with 1288 additions and 0 deletions

View File

@ -0,0 +1,328 @@
/****************************************************************************
* 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
****************************************************************************/
#ifndef __VCGLIB_SPATIALINDEX_2DH
#define __VCGLIB_SPATIALINDEX_2DH
// standard headers
#include <assert.h>
// vcg headers
#include <vcg/space/point2.h>
#include <vcg/space/ray2.h>
#include <vcg/space/box2.h>
namespace vcg {
/****************************************************************************
Class SpatialIndex
Description:
This class exposes the base interface for all spatial indexing data
structures, i.e. grids, bounding volume trees.
Template Parameters:
OBJTYPE: Type of the indexed objects.
SCALARTYPE: Scalars type for structure's internal data (may differ from
object's scalar type).
****************************************************************************/
template <class OBJTYPE, class SCALARTYPE>
class SpatialIndex2D {
public:
/**************************************************************************
Commonly used typedefs.
**************************************************************************/
typedef SpatialIndex2D<OBJTYPE, SCALARTYPE> ClassType;
typedef OBJTYPE ObjType;
typedef SCALARTYPE ScalarType;
typedef ObjType * ObjPtr;
typedef Point2<ScalarType> CoordType;
typedef vcg::Box2<ScalarType> BoxType;
/**************************************************************************
Method Set.
Description:
The Set method initializes the spatial structure.
Template Parameters:
OBJITER: Objects Container's iterator type.
Method Parameters:
_oBegin : [IN] begin objects container's iterator
_oEnd : [IN] end objects container's iterator
Return Value:
None.
**************************************************************************/
template <class OBJITER>
void Set(const OBJITER & _oBegin, const OBJITER & _oEnd) {
assert(0); // this is a base interface.
(void)_oBegin; // avoid "unreferenced parameter" compiler warning.
(void)_oEnd;
}
/**************************************************************************
Method Empty.
Description:
check if the spatial structure is empty.
Return Value:
true if it is empty.
**************************************************************************/
bool Empty() {
assert(0); // this is a base interface.
return true;
}
/**************************************************************************
Method GetClosest.
Description:
The GetClosest method finds the closest object given a point.
It also finds the closest point and minimum distance.
Template Parameters:
OBJPOINTDISTFUNCTOR : Object-Point distance functor type;
this type must implement an operator () with signature
bool operator () (const ObjType & obj, const CoordType & p, ScalarType & d, CoordType & q)
where:
obj [IN] is a reference to the current object being tested,
p [IN] is the query point,
d [IN/OUT] is in input the reject distance and in output the closest distance,
q [OUT] is the closest point.
The operator returns true if the closest distance is less than input reject distance.
OBJMARKER : The type of a marker functor.
Method Parameters:
_getPointDistance : [IN] Functor for point-distance calculation.
_marker : [IN] Functor for marking objects already tested.
_p : [IN] The query point.
_maxDist : [IN] Maximum reject distance.
_minDist : [OUT] Closest distance.
_closestPt : [OUT] Closest point.
Return Value:
A pointer to the closest object (if any).
**************************************************************************/
/*template <class OBJPOINTDISTFUNCTOR, class OBJMARKER>
ObjPtr GetClosest(
OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _maxDist,
ScalarType & _minDist, CoordType & _closestPt) {
assert(0);
(void)_getPointDistance;
(void)_marker;
(void)_p;
(void)_maxDist;
(void)_minDist;
(void)_closestPt;
return ((ObjPtr)0);
}*/
/**************************************************************************
Method GetKClosest.
Description:
The GetKClosest method finds the K closest object given a point.
It also finds the closest points and minimum distances.
Template Parameters:
OBJPOINTDISTFUNCTOR : Object-Point distance functor type;
this type must implement an operator () with signature
bool operator () (const ObjType & obj, const CoordType & p, ScalarType & d, CoordType & q)
where:
obj [IN] is a reference to the current object being tested,
p [IN] is the query point,
d [IN/OUT] is in input the reject distance and in output the closest distance,
q [OUT] is the closest point.
The operator returns true if the closest distance is less than input reject distance.
OBJMARKER : The type of a marker functor.
OBJPTRCONTAINER : The type of a object pointers container.
DISTCONTAINER : The type of a container which, in return, will contain the closest distances.
POINTCONTAINER : The type of a container which, in return, will contain the closest points.
Method Parameters:
_getPointDistance : [IN] Functor for point-distance calculation.
_marker : [IN] Functor for marking objects already tested.
_k : [IN] The number of closest objects to search for.
_p : [IN] The query point.
_maxDist : [IN] Maximum reject distance.
_objectPtrs : [OUT] Container which, in return, will contain pointers to the closest objects.
_distances : [OUT] Container which, in return, will contain the closest distances.
_objectPtrs : [OUT] Container which, in return, will contain the closest points.
Return Value:
The number of closest objects found.
**************************************************************************/
//template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
//unsigned int GetKClosest(
// OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,
// OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) {
// assert(0);
// (void)_getPointDistance;
// (void)_marker;
// (void)_k;
// (void)_p;
// (void)_maxDist;
// (void)_objectPtrs;
// (void)_distances;
// (void)_points;
// return (0);
//}
/**************************************************************************
Method GetInSphere.
Description:
The GetInSphere method finds all the objects in the specified sphere
Template Parameters:
OBJPOINTDISTFUNCTOR : Object-Point distance functor type;
this type must implement an operator () with signature
bool operator () (const ObjType & obj, const CoordType & p, ScalarType & d, CoordType & q)
where:
obj [IN] is a reference to the current object being tested,
p [IN] is the query point,
d [IN/OUT] is in input the reject distance and in output the closest distance,
q [OUT] is the closest point.
The operator returns true if the closest distance is less than input reject distance.
OBJMARKER : The type of a marker functor.
OBJPTRCONTAINER : The type of a object pointers container.
DISTCONTAINER : The type of a container which, in return, will contain the closest distances.
POINTCONTAINER : The type of a container which, in return, will contain the closest points.
Method Parameters:
_getPointDistance : [IN] Functor for point-distance calculation.
_marker : [IN] Functor for marking objects already tested.
_p : [IN] The query point.
_r : [IN] The radius of the specified sphere.
_objectPtrs : [OUT] Container which, in return, will contain pointers to the in-sphere objects.
_distances : [OUT] Container which, in return, will contain the in-sphere distances.
_objectPtrs : [OUT] Container which, in return, will contain the in-sphere nearests points for each object.
Return Value:
The number of in-sphere objects found.
**************************************************************************/
//template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
//unsigned int GetInCircle(
// OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker,const CoordType & _p, const ScalarType & _r,OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) {
// assert(0);
// (void)_getPointDistance;
// (void)_marker;
// (void)_p;
// (void)_r;
// (void)_objectPtrs;
// (void)_distances;
// (void)_points;
// return (0);
//}
/**************************************************************************
Method GetInBox.
Description:
The GetInBox returns all the object in the specified bbox
Template Parameters:
OBJMARKER : The type of a marker functor.
OBJPTRCONTAINER : The type of a object pointers container.
Method Parameters:
_marker : [IN] Functor for marking objects already tested.
_bbox : [IN] The bounding box of spatial query.
_objectPtrs : [OUT] Container which, in return, will contain pointers to the closest objects.
Return Value:
The number of in-box objects found.
**************************************************************************/
template <class OBJMARKER, class OBJPTRCONTAINER>
unsigned int GetInBox(OBJMARKER & _marker, const BoxType _bbox,OBJPTRCONTAINER & _objectPtrs) {
assert(0);
(void)_marker;
(void)_bbox;
(void)_objectPtrs;
return (0);
}
/**************************************************************************
Method DoRay.
Description:
The DoRay method finds the first object in the structure hit by a ray.
Template Parameters:
OBJRAYISECTFUNCTOR : Object-Ray intersection functor type;
this type must implement an operator () with signature
bool operator () (const ObjType & obj, const Ray3<scalarType> ray, ScalarType & t)
where:
obj [IN] is a reference to the current object being tested,
ray [IN] is the query ray,
t [OUT] is the parameter of the ray equation at which intersection occurs.
The operator returns true if the the object has been hit by the ray (i.e. they intersect).
OBJMARKER : The type of a marker functor.
Method Parameters:
_rayIntersector : [IN] Functor for object-ray intersection.
_marker : [IN] Functor for marking objects already tested.
_ray : [IN] The query ray.
_maxDist : [IN] Maximum reject distance.
_t : [OUT] the parameter of the ray equation at which intersection occurs.
Return Value:
A pointer to the first object hit by the ray (if any).
**************************************************************************/
/*template <class OBJRAYISECTFUNCTOR, class OBJMARKER>
ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3<ScalarType> & _ray, const ScalarType & _maxDist, ScalarType & _t) {
assert(0);
(void)_rayIntersector;
(void)_marker;
(void)_ray;
(void)_maxDist;
(void)_t;
return ((ObjPtr)0);
}*/
};
} // end namespace vcg
#endif // #ifndef __VCGLIB_SPATIALINDEX_H

View File

@ -0,0 +1,307 @@
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* 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 $
Revision 1.16 2006/10/02 09:34:03 cignoni
Re-added diff 1.12 by Pietroni (cancelled by previous rollback):
in GridDoRay function the RayIterator must be initialized with maximum distance
Revision 1.15 2006/10/02 09:28:45 cignoni
Reverted to version 1.10 to nullify dangerous marfr960's changes
Revision 1.10 2006/05/17 12:48:52 pietroni
corrected bug in GridGetInBox function
Revision 1.9 2006/01/27 09:58:47 corsini
fix signed/unsigned mismatch
Revision 1.8 2005/12/06 18:00:39 pietroni
added deleted objects control for GridClosest() function call
Revision 1.7 2005/12/02 00:30:27 cignoni
Corrected typename usage and removed excess ';' from end of template functions, for gcc compiling
Revision 1.6 2005/10/03 13:57:32 pietroni
added GridGetInSphere and GridGetInBox functions
Revision 1.5 2005/10/02 23:18:06 cignoni
Small bug in the computation of the intersection between the todo box and the grid bbox that failed for extrema points.
Revision 1.4 2005/09/30 15:12:16 cignoni
Completely rewrote the GridClosest, now it:
- works for point out of the grid
- expands the box in a distance coherent way
- does not re-visit already visited cells
- shorter code!!
( still to be tested :) )
Revision 1.3 2005/09/30 13:15:48 pietroni
added functions:
- GetKClosest
- DoRay
Revision 1.2 2005/09/28 08:27:11 cignoni
Added a control to avoid multiple check of the same cells during radial expansion
Still miss some code to properly initialize when point is out of the BBox of the grid.
Revision 1.1 2005/09/27 15:09:38 cignoni
First Version
****************************************************************************/
///** Returns the closest posistion of a point _p and its distance
//@param _p a 3d point
//@param _maxDist maximum distance not to search beyond.
//@param _getPointDistance (templated type) a functor object used to calculate distance from a grid object to the point _p.
//@param _minDist the returned closest distance
//@param _closestPt the returned closest point
//@return The closest element
//*/
///*
// A DISTFUNCT object must implement an operator () with signature:
// bool operator () (const ObjType& obj, const CoordType & _p, ScalarType & min_dist, CoordType & _closestPt);
//*/
#ifndef __VCGLIB_GRID_CLOSEST
#define __VCGLIB_GRID_CLOSEST
#include <vcg/space/index/space_iterators.h>
namespace vcg{
//template <class SPATIAL_INDEX, class OBJPOINTDISTFUNCTOR, class OBJMARKER>
// typename SPATIAL_INDEX::ObjPtr GridClosest(SPATIAL_INDEX &Si,
// OBJPOINTDISTFUNCTOR _getPointDistance,
// OBJMARKER & _marker,
// const typename OBJPOINTDISTFUNCTOR::QueryType & _p_obj,
// const typename SPATIAL_INDEX::ScalarType & _maxDist,
// typename SPATIAL_INDEX::ScalarType & _minDist,
// typename SPATIAL_INDEX:: CoordType &_closestPt)
//{
// typedef typename SPATIAL_INDEX::ObjPtr ObjPtr;
// typedef SPATIAL_INDEX SpatialIndex;
// typedef typename SPATIAL_INDEX::CoordType CoordType;
// typedef typename SPATIAL_INDEX::ScalarType ScalarType;
// typedef typename SPATIAL_INDEX::Box3x Box3x;
//
// Point3<ScalarType> _p = OBJPOINTDISTFUNCTOR::Pos(_p_obj);
// // Initialize min_dist with _maxDist to exploit early rejection test.
// _minDist = _maxDist;
// ObjPtr winner=NULL;
// _marker.UnMarkAll();
// ScalarType newradius = Si.voxel.Norm();
// ScalarType radius;
// Box3i iboxdone,iboxtodo;
// CoordType t_res;
// typename SPATIAL_INDEX::CellIterator first,last,l;
// if(Si.bbox.IsInEx(_p))
// {
// Point3i _ip;
// Si.PToIP(_p,_ip);
// Si.Grid( _ip[0],_ip[1],_ip[2], first, last );
// for(l=first;l!=last;++l)
// {
// ObjPtr elem=&(**l);
// if (!elem->IsD())
// {
// if (_getPointDistance((**l), _p_obj,_minDist, t_res)) // <-- NEW: use of distance functor
// {
// winner=elem;
// _closestPt=t_res;
// newradius=_minDist; //
// }
// _marker.Mark(elem);
// }
// }
// iboxdone=Box3i(_ip,_ip);
// }
// int ix,iy,iz;
// Box3i ibox(Point3i(0,0,0),Si.siz-Point3i(1,1,1));
// do
// {
// radius=newradius;
// Box3x boxtodo=Box3x(_p,radius);
// //boxtodo.Intersect(Si.bbox);
// Si.BoxToIBox(boxtodo, iboxtodo);
// iboxtodo.Intersect(ibox);
// if(!boxtodo.IsNull())
// {
// for (ix=iboxtodo.min[0]; ix<=iboxtodo.max[0]; ix++)
// for (iy=iboxtodo.min[1]; iy<=iboxtodo.max[1]; iy++)
// for (iz=iboxtodo.min[2]; iz<=iboxtodo.max[2]; iz++)
// if(ix<iboxdone.min[0] || ix>iboxdone.max[0] || // this test is to avoid to re-process already analyzed cells.
// iy<iboxdone.min[1] || iy>iboxdone.max[1] ||
// iz<iboxdone.min[2] || iz>iboxdone.max[2] )
// {
// Si.Grid( ix, iy, iz, first, last );
// for(l=first;l!=last;++l) if (!(**l).IsD())
// {
// ObjPtr elem=&(**l);
// if (!elem->IsD())
// {
// if( ! _marker.IsMarked(elem))
// {
// if (_getPointDistance((**l), _p_obj, _minDist, t_res))
// {
// winner=elem;
// _closestPt=t_res;
// };
// _marker.Mark(elem);
// }
// }
// }
// }
// }
// if(!winner) newradius=radius+Si.voxel.Norm();
// else newradius = _minDist;
// }
// while (_minDist>radius);
// return winner;
//}
//template <class SPATIALINDEXING,class OBJPOINTDISTFUNCTOR, class OBJMARKER,
//class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
// unsigned int GridGetKClosest(SPATIALINDEXING &_Si,
// OBJPOINTDISTFUNCTOR & _getPointDistance,
// OBJMARKER & _marker,
// const unsigned int _k,
// const typename SPATIALINDEXING::CoordType & _p,
// const typename SPATIALINDEXING::ScalarType & _maxDist,
// OBJPTRCONTAINER & _objectPtrs,
// DISTCONTAINER & _distances,
// POINTCONTAINER & _points)
//{
// typedef vcg::ClosestIterator<SPATIALINDEXING,OBJPOINTDISTFUNCTOR,OBJMARKER> ClosestIteratorType;
// ClosestIteratorType Cli=ClosestIteratorType(_Si,_getPointDistance);
// Cli.SetMarker(_marker);
// Cli.Init(_p,_maxDist);
// unsigned int i=0;
// _objectPtrs.clear();
// _distances.clear();
// _points.clear();
// while ((!Cli.End())&&(i<_k))
// {
// _objectPtrs.push_back(&(*Cli));
// _distances.push_back(Cli.Dist());
// _points.push_back(Cli.NearestPoint());
// ++Cli;
// i++;
// }
// return (i);
//}
//template <class SPATIALINDEXING,class OBJRAYISECTFUNCTOR, class OBJMARKER>
// typename SPATIALINDEXING::ObjPtr GridDoRay(SPATIALINDEXING &_Si,
// OBJRAYISECTFUNCTOR &_rayIntersector,
// OBJMARKER &_marker,
// const Ray3<typename SPATIALINDEXING::ScalarType> & _ray,
// const typename SPATIALINDEXING::ScalarType & _maxDist,
// typename SPATIALINDEXING::ScalarType & _t)
//{
// typedef vcg::RayIterator<SPATIALINDEXING,OBJRAYISECTFUNCTOR,OBJMARKER> RayIteratorType;
// RayIteratorType RayIte=RayIteratorType(_Si,_rayIntersector,_maxDist);
// RayIte.SetMarker(_marker);
// RayIte.Init(_ray);
// if (!RayIte.End())
// {
// _t=RayIte.Dist();
// return(&(*RayIte));
// }
// return 0;
//}
//
//template <class SPATIALINDEXING, class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
// unsigned int GridGetInSphere(SPATIALINDEXING &_Si,
// OBJPOINTDISTFUNCTOR & _getPointDistance,
// OBJMARKER & _marker,
// const typename SPATIALINDEXING::CoordType & _p,
// const typename SPATIALINDEXING::ScalarType & _r,
// OBJPTRCONTAINER & _objectPtrs,
// DISTCONTAINER & _distances,
// POINTCONTAINER & _points)
//{
// typedef vcg::ClosestIterator<SPATIALINDEXING,OBJPOINTDISTFUNCTOR,OBJMARKER> ClosestIteratorType;
// ClosestIteratorType Cli=ClosestIteratorType(_Si,_getPointDistance);
// Cli.SetMarker(_marker);
// Cli.Init(_p,_r);
// _objectPtrs.clear();
// _distances.clear();
// _points.clear();
// while (!Cli.End())
// {
// _objectPtrs.push_back(&(*Cli));
// _distances.push_back(Cli.Dist());
// _points.push_back(Cli.NearestPoint());
// ++Cli;
// }
// return ((int)_objectPtrs.size());
// }
template <class SPATIALINDEXING,class OBJMARKER, class OBJPTRCONTAINER>
unsigned int GridGetInBox2D(SPATIALINDEXING &_Si,
OBJMARKER & _marker,
const vcg::Box2<typename SPATIALINDEXING::ScalarType> &_bbox,
OBJPTRCONTAINER & _objectPtrs)
{
typename SPATIALINDEXING::CellIterator first,last,l;
_objectPtrs.clear();
vcg::Box2i ibbox;
Box2i Si_ibox(Point2i(0,0),_Si.siz-Point2i(1,1));
_Si.BoxToIBox(_bbox, ibbox);
ibbox.Intersect(Si_ibox);
_marker.UnMarkAll();
if (ibbox.IsNull())
return 0;
else
{
int ix,iy,iz;
for (ix=ibbox.min[0]; ix<=ibbox.max[0]; ix++)
for (iy=ibbox.min[1]; iy<=ibbox.max[1]; iy++)
{
_Si.Grid( ix, iy, first, last );
for(l=first;l!=last;++l)
if (!(**l).IsD())
{
typename SPATIALINDEXING::ObjPtr elem=&(**l);
vcg::Box2<typename SPATIALINDEXING::ScalarType> box_elem;
elem->GetBBox(box_elem);
if(( ! _marker.IsMarked(elem))&&(box_elem.Collide(_bbox))){
_objectPtrs.push_back(elem);
_marker.Mark(elem);
}
}
}
return (static_cast<unsigned int>(_objectPtrs.size()));
}
}
}//end namespace vcg
#endif

View File

@ -0,0 +1,222 @@
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* 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. *
* *
****************************************************************************/
/****************************************************************************
****************************************************************************/
#ifndef __VCGLIB_GRID_UTIL_2D
#define __VCGLIB_GRID_UTIL_2D
#include<vcg/space/index/index2D/base_2D.h>
#include<vcg/space/box2.h>
//#include <vcg/space/index/space_iterators.h>
#ifndef WIN32
#define __int64 long long
#define __cdecl
#endif
namespace vcg {
/** BasicGrid2D
Basic Class abstracting a gridded structure in a 3d space;
Usueful for having coherent float to integer conversion in a unique place:
Some Notes:
- bbox is the real occupation of the box in the space;
- siz is the number of cells for each side
OBJTYPE: Type of the indexed objects.
SCALARTYPE: Scalars type for structure's internal data (may differ from
object's scalar type).
*/
template <class SCALARTYPE>
class BasicGrid2D
{
public:
typedef SCALARTYPE ScalarType;
typedef Box2<ScalarType> Box2x;
typedef Point2<ScalarType> CoordType;
typedef BasicGrid2D<SCALARTYPE> GridType;
Box2x bbox;
CoordType dim; /// Spatial Dimention (edge legth) of the bounding box
Point2i siz; /// Number of cells forming the grid
CoordType voxel; /// Dimensions of a single cell
/*
Derives the right values of Dim and voxel starting
from the current values of siz and bbox
*/
void ComputeDimAndVoxel()
{
this->dim = this->bbox.max - this->bbox.min;
this->voxel[0] = this->dim[0]/this->siz[0];
this->voxel[1] = this->dim[1]/this->siz[1];
}
/* Given a 3D point, returns the coordinates of the cell where the point is
* @param p is a 3D point
* @return integer coordinates of the cell
*/
inline Point2i GridP( const Point2<ScalarType> & p ) const
{
Point2i pi;
PToIP(p, pi);
return pi;
}
/* Given a 3D point p, returns the index of the corresponding cell
* @param p is a 3D point in the space
* @return integer coordinates pi of the cell
*/
inline void PToIP(const CoordType & p, Point2i &pi ) const
{
CoordType t = p - bbox.min;
pi[0] = int( t[0] / voxel[0] );
pi[1] = int( t[1] / voxel[1] );
}
/* Given a cell index return the lower corner of the cell
* @param integer coordinates pi of the cell
* @return p is a 3D point representing the lower corner of the cell
*/
inline void IPiToPf(const Point2i & pi, CoordType &p ) const
{
p[0] = ((ScalarType)pi[0])*voxel[0];
p[1] = ((ScalarType)pi[1])*voxel[1];
p += bbox.min;
}
/* Given a cell index return the corresponding box
* @param integer coordinates pi of the cell
* @return b is the corresponding box in <ScalarType> coordinates
*/
inline void IPiToBox(const Point2i & pi, Box2x & b ) const
{
CoordType p;
p[0] = ((ScalarType)pi[0])*voxel[0];
p[1] = ((ScalarType)pi[1])*voxel[1];
p += bbox.min;
b.min = p;
b.max = (p + voxel);
}
/* Given a cell index return the center of the cell itself
* @param integer coordinates pi of the cell
* @return b is the corresponding box in <ScalarType> coordinates
*/inline void IPiToBoxCenter(const Point2i & pi, CoordType & c ) const
{
CoordType p;
IPiToPf(pi,p);
c = p + voxel/ScalarType(2.0);
}
// Same of IPiToPf but for the case that you just want to transform
// from a space to the other.
inline void IPfToPf(const CoordType & pi, CoordType &p ) const
{
p[0] = ((ScalarType)pi[0])*voxel[0];
p[1] = ((ScalarType)pi[1])*voxel[1];
p += bbox.min;
}
/* Given a cell in <ScalarType> coordinates, compute the corresponding cell in integer coordinates
* @param b is the cell in <ScalarType> coordinates
* @return ib is the correspondent box in integer coordinates
*/
inline void BoxToIBox( const Box2x & b, Box2i & ib ) const
{
PToIP(b.min, ib.min);
PToIP(b.max, ib.max);
//assert(ib.max[0]>=0 && ib.max[1]>=0 && ib.max[2]>=0);
}
/* Given a cell in integer coordinates, compute the corresponding cell in <ScalarType> coordinates
* @param ib is the cell in integer coordinates
* @return b is the correspondent box in <ScalarType> coordinates
*/
/// Dato un box in voxel ritorna gli estremi del box reale
void IBoxToBox( const Box2i & ib, Box2x & b ) const
{
IPiToPf(ib.min,b.min);
IPiToPf(ib.max+Point2i(1,1),b.max);
}
};
template<class scalar_type>
void BestDim2D( const Box2<scalar_type> box, const scalar_type voxel_size, Point2i & dim )
{
Point2<scalar_type> box_size = box.max-box.min;
__int64 elem_num = (__int64)(box_size[0]/voxel_size +0.5) *( __int64)(box_size[1]/voxel_size +0.5);
BestDim2D(elem_num,box_size,dim);
}
/** Calcolo dimensioni griglia.
Calcola la dimensione della griglia in funzione
della ratio del bounding box e del numero di elementi
*/
template<class scalar_type>
void BestDim2D( const __int64 elems, const Point2<scalar_type> & size, Point2i & dim )
{
const __int64 mincells = 1; // Numero minimo di celle
const double GFactor = 1; // GridEntry = NumElem*GFactor
double diag = size.Norm(); // Diagonale del box
double eps = diag*1e-4; // Fattore di tolleranza
assert(elems>0);
assert(size[0]>=0.0);
assert(size[1]>=0.0);
__int64 ncell = (__int64)(elems*GFactor); // Calcolo numero di voxel
if(ncell<mincells)
ncell = mincells;
dim[0] = 1;
dim[1] = 1;
if ((size[0]>eps)&&(size[1]>eps))
{
scalar_type Area=size[0]*size[1];
double k = pow((double)(ncell/Area),double(1.0/2.f));
dim[0] = int(size[0] * k);
dim[1] = int(size[1] * k);
}
else
{
if(size[0]>eps)
dim[0] = int(ncell);
else
dim[1] = int(ncell);
}
dim[0] = std::max(dim[0],1);
dim[1] = std::max(dim[1],1);
}
}///end namespace
#endif

View File

@ -0,0 +1,431 @@
/****************************************************************************
* 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. *
* *
****************************************************************************/
#ifndef VCGLIB_SPATIAL_HASHING_2D
#define VCGLIB_SPATIAL_HASHING_2D
#include <vcg/space/index/index2D/grid_util_2D.h>
#include <vcg/space/index/index2D/grid_closest_2D.h>
//#include <map>
#include <vector>
#include <algorithm>
#ifdef _WIN32
#ifndef __MINGW32__
#include <hash_map>
#define STDEXT stdext
#else
#include <ext/hash_map>
#define STDEXT __gnu_cxx
#endif
#else // We are in the *nix gcc branch
#if (__GNUC__ ==4) && (__GNUC_MINOR__ > 3) && (defined(__DEPRECATED))
#undef __DEPRECATED // since gcc 4.4 <ext/hash_map> was deprecated and generate warnings. Relax Deprecation Just for this...
#define ___WE_UNDEFINED_DEPRECATED__
#endif
#include <ext/hash_map>
#define STDEXT __gnu_cxx
#if defined(___WE_UNDEFINED_DEPRECATED__)
#define __DEPRECATED
#endif
#endif
namespace vcg{
// hashing function
struct HashFunctor : public std::unary_function<Point2i, size_t>
{
enum
{ // parameters for hash table
bucket_size = 4, // 0 < bucket_size
min_buckets = 8
};
size_t operator()(const Point2i &p) const
{
const size_t _HASH_P0 = 73856093u;
const size_t _HASH_P1 = 19349663u;
//const size_t _HASH_P2 = 83492791u;
return size_t(p.V(0))*_HASH_P0 ^ size_t(p.V(1))*_HASH_P1;// ^ size_t(p.V(2))*_HASH_P2;
}
bool operator()(const Point2i &s1, const Point2i &s2) const
{ // test if s1 ordered before s2
return (s1 < s2);
}
};
/** Spatial Hash Table
Spatial Hashing as described in
"Optimized Spatial Hashing for Coll ision Detection of Deformable Objects",
Matthias Teschner and Bruno Heidelberger and Matthias Muller and Danat Pomeranets and Markus Gross
*/
template < typename ObjType,class FLT=double>
class SpatialHashTable2D:public BasicGrid2D<FLT>, public SpatialIndex2D<ObjType,FLT>
{
public:
typedef SpatialHashTable2D SpatialHashType;
typedef ObjType* ObjPtr;
typedef typename ObjType::ScalarType ScalarType;
typedef Point2<ScalarType> CoordType;
typedef typename BasicGrid2D<FLT>::Box2x Box2x;
// Hash table definition
// the hash index directly the grid structure.
// We use a MultiMap because we need to store many object (faces) inside each cell of the grid.
typedef typename STDEXT::hash_multimap<Point2i, ObjType *, HashFunctor> HashType;
typedef typename HashType::iterator HashIterator;
HashType hash_table; // The real HASH TABLE **************************************
// This vector is just a handy reference to all the allocated cells,
// becouse hashed multimaps does not expose a direct list of all the different keys.
std::vector<Point2i> AllocatedCells;
// Class to abstract a HashIterator (that stores also the key,
// while the interface of the generic spatial indexing need only simple object (face) pointers.
struct CellIterator
{
CellIterator(){}
HashIterator t;
ObjPtr &operator *(){return (t->second); }
ObjPtr operator *() const {return (t->second); }
bool operator != (const CellIterator & p) const {return t!=p.t;}
void operator ++() {t++;}
};
inline bool Empty() const
{
return hash_table.empty();
}
size_t CellSize(const Point3i &cell)
{
return hash_table.count(cell);
}
inline bool EmptyCell(const Point3i &cell) const
{
return hash_table.find(cell) == hash_table.end();
}
void UpdateAllocatedCells()
{
AllocatedCells.clear();
if(hash_table.empty()) return;
AllocatedCells.push_back(hash_table.begin()->first);
for(HashIterator fi=hash_table.begin();fi!=hash_table.end();++fi)
{
if(AllocatedCells.back()!=fi->first) AllocatedCells.push_back(fi->first);
}
}
protected:
///insert a new cell
void InsertObject(ObjType* s, const Point2i &cell)
{
hash_table.insert(typename HashType::value_type(cell, s));
}
///remove all the objects in a cell
void RemoveCell(const Point3i &/*cell*/)
{
}
bool RemoveObject(ObjType* s, const Point2i &cell)
{
std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(cell);
CellIterator first; first.t=CellRange.first;
CellIterator end; end.t=CellRange.second;
for(CellIterator ci = first; ci!=end;++ci)
{
if (*ci == s)
{
hash_table.erase(ci.t);
return true;
}
}
return false;
}
public:
vcg::Box2i Add( ObjType* s)
{
Box2<ScalarType> b;
s->GetBBox(b);
vcg::Box2i bb;
this->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++)
InsertObject(s,vcg::Point2i(i,j));
//for (int k=bb.min.Z();k<=bb.max.Z();k++)
//InsertObject(s,vcg::Point3i(i,j,k));
return bb;
}
///Remove all the objects contained in the cell containing s
// it removes s too.
bool RemoveCell(ObjType* s)
{
Point3i pi;
PToIP(s->cP(),pi);
std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(pi);
hash_table.erase(CellRange.first,CellRange.second);
return true;
} ///insert a new cell
/* int RemoveInSphere(const Point3<ScalarType> &p, const ScalarType radius)
{
Box3x b(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
vcg::Box3i bb;
this->BoxToIBox(b,bb);
ScalarType r2=radius*radius;
int cnt=0;
std::vector<HashIterator> toDel;
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++)
{
std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(Point3i(i,j,k));
for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
{
if(SquaredDistance(p,hi->second->cP()) <= r2)
{
cnt++;
toDel.push_back(hi);
}
}
}
for(typename std::vector<HashIterator>::iterator vi=toDel.begin(); vi!=toDel.end();++vi)
hash_table.erase(*vi);
return cnt;
}*/
//// Specialized version that is able to take in input a
//template<class DistanceFunctor>
//int RemoveInSphereNormal(const Point3<ScalarType> &p, const Point3<ScalarType> &n, DistanceFunctor &DF, const ScalarType radius)
//{
// Box3x b(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
// vcg::Box3i bb;
// this->BoxToIBox(b,bb);
// int cnt=0;
// std::vector<HashIterator> toDel;
// 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++)
// {
// std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(Point3i(i,j,k));
// for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
// {
// if(DF(p,n,hi->second->cP(),hi->second->cN()) <= radius)
// {
// cnt++;
// toDel.push_back(hi);
// }
// }
// }
// for(typename std::vector<HashIterator>::iterator vi=toDel.begin(); vi!=toDel.end();++vi)
// hash_table.erase(*vi);
// return cnt;
//}
//// This version of the removal is specialized for the case where
//// an object has a pointshaped box and using the generic bbox interface is just a waste of time.
//void RemovePunctual( ObjType *s)
//{
// Point3i pi;
// PToIP(s->cP(),pi);
// std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(pi);
// for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
// {
// if (hi->second == s)
// {
// hash_table.erase(hi);
// return;
// }
// }
//}
void Remove( ObjType* s)
{
Box3<ScalarType> b;
s->GetBBox(b);
vcg::Box2i bb;
BoxToIBox(b,bb);
//then remove the obj from 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++)
RemoveObject(s,vcg::Point3i(i,j));//,k));
}
/// set an empty spatial hash table
void InitEmpty(const Box2x &_bbox, vcg::Point2i grid_size)
{
Box2x b;
Box2x &bbox = this->bbox;
CoordType &dim = this->dim;
Point2i &siz = this->siz;
CoordType &voxel = this->voxel;
assert(!_bbox.IsNull());
bbox=_bbox;
dim = bbox.max - bbox.min;
assert((grid_size.V(0)>0)&&(grid_size.V(1)>0));//&&(grid_size.V(2)>0));
siz=grid_size;
voxel[0] = dim[0]/siz[0];
voxel[1] = dim[1]/siz[1];
//voxel[2] = dim[2]/siz[2];
hash_table.clear();
}
/// Insert a mesh in the grid.
template <class OBJITER>
void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box2x &_bbox=Box2x() )
{
OBJITER i;
Box2x b;
Box2x &bbox = this->bbox;
CoordType &dim = this->dim;
Point2i &siz = this->siz;
CoordType &voxel = this->voxel;
int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
if(!_bbox.IsNull()) this->bbox=_bbox;
else
{
for(i = _oBegin; i!= _oEnd; ++i)
{
(*i).GetBBox(b);
this->bbox.Add(b);
}
///inflate the bb calculated
bbox.Offset(bbox.Diag()/100.0) ;
}
dim = bbox.max - bbox.min;
BestDim2D( _size, dim, siz );
// find voxel size
voxel[0] = dim[0]/siz[0];
voxel[1] = dim[1]/siz[1];
//voxel[2] = dim[2]/siz[2];
for(i = _oBegin; i!= _oEnd; ++i)
Add(&(*i));
}
///return the simplexes of the cell that contain p
void GridReal( const Point2<ScalarType> & p, CellIterator & first, CellIterator & last )
{
vcg::Point2i _c;
this->PToIP(p,_c);
Grid(_c,first,last);
}
///return the simplexes on a specified cell
void Grid( int x,int y, CellIterator & first, CellIterator & last )
{
this->Grid(vcg::Point2i(x,y),first,last);
}
///return the simplexes on a specified cell
void Grid( const Point2i & _c, CellIterator & first, CellIterator & end )
{
std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(_c);
first.t=CellRange.first;
end.t=CellRange.second;
}
void Clear()
{
hash_table.clear();
AllocatedCells.clear();
}
/*template <class OBJPOINTDISTFUNCTOR, class OBJMARKER>
ObjPtr GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker,
const CoordType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt)
{
return (vcg::GridClosest<SpatialHashType,OBJPOINTDISTFUNCTOR,OBJMARKER>(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt));
}
template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER,class DISTCONTAINER, class POINTCONTAINER>
unsigned int GetKClosest(OBJPOINTDISTFUNCTOR & _getPointDistance,OBJMARKER & _marker,
const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,OBJPTRCONTAINER & _objectPtrs,
DISTCONTAINER & _distances, POINTCONTAINER & _points)
{
return (vcg::GridGetKClosest<SpatialHashType,
OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
(*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points));
}
template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance,
OBJMARKER & _marker,
const CoordType & _p,
const ScalarType & _r,
OBJPTRCONTAINER & _objectPtrs,
DISTCONTAINER & _distances,
POINTCONTAINER & _points)
{
return(vcg::GridGetInSphere<SpatialHashType,
OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
(*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points));
}*/
template <class OBJMARKER, class OBJPTRCONTAINER>
unsigned int GetInBox(OBJMARKER & _marker,
const Box2x _bbox,
OBJPTRCONTAINER & _objectPtrs)
{
return(vcg::GridGetInBox2D<SpatialHashType,OBJMARKER,OBJPTRCONTAINER>
(*this,_marker,_bbox,_objectPtrs));
}
}; // end class
} // end namespace
#endif