From 066f46c20bb4b00eb74381f931c68cd748a893b3 Mon Sep 17 00:00:00 2001 From: nicopietroni Date: Fri, 22 Jun 2012 14:27:33 +0000 Subject: [PATCH] first release version --- vcg/space/index/index2D/base_2d.h | 328 ++++++++++++++ vcg/space/index/index2D/grid_closest_2D.h | 307 +++++++++++++ vcg/space/index/index2D/grid_util_2D.h | 222 ++++++++++ vcg/space/index/index2D/spatial_hashing_2D.h | 431 +++++++++++++++++++ 4 files changed, 1288 insertions(+) create mode 100644 vcg/space/index/index2D/base_2d.h create mode 100644 vcg/space/index/index2D/grid_closest_2D.h create mode 100644 vcg/space/index/index2D/grid_util_2D.h create mode 100644 vcg/space/index/index2D/spatial_hashing_2D.h diff --git a/vcg/space/index/index2D/base_2d.h b/vcg/space/index/index2D/base_2d.h new file mode 100644 index 00000000..a8c22212 --- /dev/null +++ b/vcg/space/index/index2D/base_2d.h @@ -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 + +// vcg headers +#include +#include +#include + +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 SpatialIndex2D { +public: + /************************************************************************** + Commonly used typedefs. + **************************************************************************/ + typedef SpatialIndex2D ClassType; + typedef OBJTYPE ObjType; + typedef SCALARTYPE ScalarType; + typedef ObjType * ObjPtr; + typedef Point2 CoordType; + typedef vcg::Box2 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 + 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 + 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 + //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 + //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 + 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 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 + ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3 & _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 diff --git a/vcg/space/index/index2D/grid_closest_2D.h b/vcg/space/index/index2D/grid_closest_2D.h new file mode 100644 index 00000000..15f8fc38 --- /dev/null +++ b/vcg/space/index/index2D/grid_closest_2D.h @@ -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 + +namespace vcg{ + + //template + // 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 _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(ixiboxdone.max[0] || // this test is to avoid to re-process already analyzed cells. + // iyiboxdone.max[1] || + // iziboxdone.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 + // 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 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 + // typename SPATIALINDEXING::ObjPtr GridDoRay(SPATIALINDEXING &_Si, + // OBJRAYISECTFUNCTOR &_rayIntersector, + // OBJMARKER &_marker, + // const Ray3 & _ray, + // const typename SPATIALINDEXING::ScalarType & _maxDist, + // typename SPATIALINDEXING::ScalarType & _t) + //{ + // typedef vcg::RayIterator RayIteratorType; + // RayIteratorType RayIte=RayIteratorType(_Si,_rayIntersector,_maxDist); + // RayIte.SetMarker(_marker); + // RayIte.Init(_ray); + + // if (!RayIte.End()) + // { + // _t=RayIte.Dist(); + // return(&(*RayIte)); + // } + // return 0; + //} + + // + //template + // 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 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 + unsigned int GridGetInBox2D(SPATIALINDEXING &_Si, + OBJMARKER & _marker, + const vcg::Box2 &_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 box_elem; + elem->GetBBox(box_elem); + if(( ! _marker.IsMarked(elem))&&(box_elem.Collide(_bbox))){ + _objectPtrs.push_back(elem); + _marker.Mark(elem); + } + } + } + return (static_cast(_objectPtrs.size())); + } + } + + }//end namespace vcg +#endif + diff --git a/vcg/space/index/index2D/grid_util_2D.h b/vcg/space/index/index2D/grid_util_2D.h new file mode 100644 index 00000000..abf0259d --- /dev/null +++ b/vcg/space/index/index2D/grid_util_2D.h @@ -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 +#include +//#include + + +#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 BasicGrid2D + { + public: + + typedef SCALARTYPE ScalarType; + typedef Box2 Box2x; + typedef Point2 CoordType; + typedef BasicGrid2D 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 & 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 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 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 coordinates, compute the corresponding cell in integer coordinates + * @param b is the cell in 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 coordinates + * @param ib is the cell in integer coordinates + * @return b is the correspondent box in 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 + void BestDim2D( const Box2 box, const scalar_type voxel_size, Point2i & dim ) + { + Point2 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 + void BestDim2D( const __int64 elems, const Point2 & 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(ncelleps)&&(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 diff --git a/vcg/space/index/index2D/spatial_hashing_2D.h b/vcg/space/index/index2D/spatial_hashing_2D.h new file mode 100644 index 00000000..e7b2e523 --- /dev/null +++ b/vcg/space/index/index2D/spatial_hashing_2D.h @@ -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 +#include +//#include +#include +#include +#ifdef _WIN32 +#ifndef __MINGW32__ +#include +#define STDEXT stdext +#else +#include +#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 was deprecated and generate warnings. Relax Deprecation Just for this... +#define ___WE_UNDEFINED_DEPRECATED__ +#endif +#include +#define STDEXT __gnu_cxx +#if defined(___WE_UNDEFINED_DEPRECATED__) +#define __DEPRECATED +#endif +#endif + + +namespace vcg{ + + + + // hashing function + struct HashFunctor : public std::unary_function + { + 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, public SpatialIndex2D + { + + public: + typedef SpatialHashTable2D SpatialHashType; + typedef ObjType* ObjPtr; + typedef typename ObjType::ScalarType ScalarType; + typedef Point2 CoordType; + typedef typename BasicGrid2D::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 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 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 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 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 CellRange = hash_table.equal_range(pi); + hash_table.erase(CellRange.first,CellRange.second); + return true; + } ///insert a new cell + + /* int RemoveInSphere(const Point3 &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 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 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::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 + //int RemoveInSphereNormal(const Point3 &p, const Point3 &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 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 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::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 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 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 + 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(_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 & 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 CellRange = hash_table.equal_range(_c); + first.t=CellRange.first; + end.t=CellRange.second; + } + + void Clear() + { + hash_table.clear(); + AllocatedCells.clear(); + } + + + /*template + ObjPtr GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, + const CoordType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt) + { + return (vcg::GridClosest(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt)); + } + + + template + 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 + (*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points)); + } + + template + unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance, + OBJMARKER & _marker, + const CoordType & _p, + const ScalarType & _r, + OBJPTRCONTAINER & _objectPtrs, + DISTCONTAINER & _distances, + POINTCONTAINER & _points) + { + return(vcg::GridGetInSphere + (*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points)); + }*/ + + template + unsigned int GetInBox(OBJMARKER & _marker, + const Box2x _bbox, + OBJPTRCONTAINER & _objectPtrs) + { + return(vcg::GridGetInBox2D + (*this,_marker,_bbox,_objectPtrs)); + } + + }; // end class + + + + } // end namespace + +#endif