2004-05-10 16:45:46 +02: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. *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
2005-08-02 13:18:36 +02:00
|
|
|
History
|
2004-05-10 16:45:46 +02:00
|
|
|
|
|
|
|
$Log: not supported by cvs2svn $
|
2007-07-16 18:59:26 +02:00
|
|
|
Revision 1.37 2007/07/16 15:13:39 cignoni
|
|
|
|
Splitted initialiazation functions of grid to add flexibility in the creation
|
|
|
|
|
2007-07-16 17:13:39 +02:00
|
|
|
Revision 1.36 2005/12/02 00:43:31 cignoni
|
|
|
|
Forgotten a base deferencing like the previous one
|
|
|
|
Note also the different possible sintax with this-> instead of the base class name
|
|
|
|
|
2005-12-02 01:43:31 +01:00
|
|
|
Revision 1.35 2005/12/02 00:25:13 cignoni
|
|
|
|
Added and removed typenames for gcc compiling.
|
|
|
|
Added base class qualifier for referencing the elemntes of the templated base class (BasicGrid)
|
|
|
|
it seems to be needed by the standard
|
|
|
|
|
2005-12-02 01:25:13 +01:00
|
|
|
Revision 1.34 2005/11/30 16:01:25 m_di_benedetto
|
|
|
|
Added std:: namespace for max() and min().
|
|
|
|
|
2005-11-30 17:01:25 +01:00
|
|
|
Revision 1.33 2005/11/30 10:32:44 m_di_benedetto
|
|
|
|
Added (int) cast to std::distance to prevent compiler warning message.
|
|
|
|
|
2005-11-30 11:32:44 +01:00
|
|
|
Revision 1.32 2005/11/10 15:44:17 cignoni
|
|
|
|
Added casts to remove warnings
|
|
|
|
|
2005-11-10 16:44:17 +01:00
|
|
|
Revision 1.31 2005/10/07 13:27:22 turini
|
|
|
|
Minor changes in Set method: added use of template scalar type computing BBox.
|
|
|
|
|
2005-10-07 15:27:22 +02:00
|
|
|
Revision 1.30 2005/10/05 17:05:08 pietroni
|
|
|
|
corrected bug on Set Function .... bbox must be exetended in order to have'nt any object on his borde
|
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
Revision 1.29 2005/10/03 13:57:56 pietroni
|
|
|
|
added GetInSphere and GetInBox functions
|
|
|
|
|
2005-10-03 15:58:21 +02:00
|
|
|
Revision 1.28 2005/10/02 23:15:26 cignoni
|
|
|
|
Inveted the boolean sign of an assert in Grid()
|
|
|
|
|
2005-10-03 01:15:26 +02:00
|
|
|
Revision 1.27 2005/09/30 15:07:28 cignoni
|
|
|
|
Reordered grid access functions
|
|
|
|
Added possibility of setting BBox explicitly in Set(...)
|
|
|
|
|
2005-09-30 17:07:28 +02:00
|
|
|
Revision 1.26 2005/09/30 13:15:21 pietroni
|
|
|
|
added wrapping to functions defined in GridClosest:
|
2005-10-05 19:05:08 +02:00
|
|
|
- GetClosest
|
|
|
|
- GetKClosest
|
|
|
|
- DoRay
|
2005-09-30 17:07:28 +02:00
|
|
|
|
2005-09-30 15:15:21 +02:00
|
|
|
Revision 1.25 2005/09/21 09:22:51 pietroni
|
|
|
|
removed closest functions. Closest function is now on index\\Closest.h
|
|
|
|
Users must use trimesh\\closest.h to perform spatial query.
|
|
|
|
|
2005-09-21 11:22:51 +02:00
|
|
|
Revision 1.24 2005/09/16 11:57:15 cignoni
|
|
|
|
Removed two wrong typenames
|
|
|
|
|
2005-09-16 13:57:15 +02:00
|
|
|
Revision 1.23 2005/09/15 13:16:42 spinelli
|
|
|
|
fixed bugs
|
|
|
|
|
2005-09-15 15:16:42 +02:00
|
|
|
Revision 1.22 2005/09/15 11:14:39 pietroni
|
|
|
|
minor changes
|
|
|
|
|
2005-09-15 13:15:00 +02:00
|
|
|
Revision 1.21 2005/09/14 13:27:38 spinelli
|
|
|
|
minor changes
|
|
|
|
|
2005-09-14 15:27:38 +02:00
|
|
|
Revision 1.20 2005/09/14 12:57:52 pietroni
|
|
|
|
canged template parameters for Closest Function (use of TempMark class)
|
|
|
|
|
2005-09-14 14:57:52 +02:00
|
|
|
Revision 1.19 2005/09/14 09:05:32 pietroni
|
|
|
|
added * operator to Link
|
|
|
|
modified getClosest in order to use Temporary mark
|
|
|
|
corrected bug on functor calling compilation
|
|
|
|
|
2005-09-14 11:05:32 +02:00
|
|
|
Revision 1.18 2005/09/09 11:29:21 m_di_benedetto
|
|
|
|
Modified old GetClosest() to respect old min_dist semantic (in/out) and removed #included <limits>
|
|
|
|
|
2005-09-09 13:29:21 +02:00
|
|
|
Revision 1.17 2005/09/09 11:11:15 m_di_benedetto
|
|
|
|
#included <limits> for std::numeric_limits<ScalarType>::max() and corrected parameters bug in old GetClosest();
|
|
|
|
|
2005-09-09 13:11:15 +02:00
|
|
|
Revision 1.16 2005/09/09 11:01:02 m_di_benedetto
|
|
|
|
Modified GetClosest(): now it uses a functor for distance calculation.
|
|
|
|
Added comments and a GetClosest() method with backward compatibility.
|
|
|
|
|
2005-09-09 13:01:02 +02:00
|
|
|
Revision 1.15 2005/08/26 09:27:58 cignoni
|
|
|
|
Added a templated version of SetBBox
|
|
|
|
|
2005-08-26 11:27:58 +02:00
|
|
|
Revision 1.14 2005/08/02 11:18:36 pietroni
|
|
|
|
exetended form BasicGrid, changed type of t in class Link (from Iterator to Pointer to the object)
|
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
Revision 1.13 2005/04/14 17:23:08 ponchio
|
|
|
|
*** empty log message ***
|
|
|
|
|
2005-04-14 19:23:08 +02:00
|
|
|
Revision 1.12 2005/03/15 11:43:18 cignoni
|
|
|
|
Removed BestDim function from the grid_static_ptr class and moved to a indipendent file (grid_util.h) for sake of generality.
|
|
|
|
|
2005-03-15 12:43:18 +01:00
|
|
|
Revision 1.11 2005/01/03 11:21:26 cignoni
|
|
|
|
Added some casts
|
|
|
|
|
2005-01-03 12:21:26 +01:00
|
|
|
Revision 1.10 2004/09/28 10:25:05 ponchio
|
|
|
|
SetBox minimal change.
|
|
|
|
|
2004-09-28 12:25:05 +02:00
|
|
|
Revision 1.9 2004/09/23 14:29:42 ponchio
|
|
|
|
Small bugs fixed.
|
|
|
|
|
2004-09-23 16:29:42 +02:00
|
|
|
Revision 1.8 2004/09/23 13:44:25 ponchio
|
|
|
|
Removed SetSafeBBox. SetBBox is now safe enough.
|
|
|
|
|
2004-09-23 15:44:25 +02:00
|
|
|
Revision 1.7 2004/09/09 12:44:39 fasano
|
|
|
|
included stdio.h
|
|
|
|
|
2004-09-09 14:44:39 +02:00
|
|
|
Revision 1.6 2004/09/09 08:39:29 ganovelli
|
|
|
|
minor changes for gcc
|
|
|
|
|
2004-09-09 10:39:29 +02:00
|
|
|
Revision 1.5 2004/06/25 18:34:23 ganovelli
|
|
|
|
added Grid to return all the cells sharing a specified edge
|
|
|
|
|
2004-06-25 20:34:23 +02:00
|
|
|
Revision 1.4 2004/06/23 15:49:03 ponchio
|
|
|
|
Added some help and inndentation
|
|
|
|
|
2004-06-23 17:49:03 +02:00
|
|
|
Revision 1.3 2004/05/12 18:50:58 ganovelli
|
|
|
|
changed calls to Dist
|
|
|
|
|
2004-05-12 20:50:58 +02:00
|
|
|
Revision 1.2 2004/05/11 14:33:46 ganovelli
|
|
|
|
changed to grid_static_obj to grid_static_ptr
|
|
|
|
|
2004-05-11 16:33:46 +02:00
|
|
|
Revision 1.1 2004/05/10 14:44:13 ganovelli
|
|
|
|
created
|
|
|
|
|
2004-05-10 16:45:46 +02:00
|
|
|
Revision 1.1 2004/03/08 09:21:31 cignoni
|
|
|
|
Initial commit
|
|
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __VCGLIB_UGRID
|
|
|
|
#define __VCGLIB_UGRID
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
2004-09-09 14:44:39 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2004-05-10 16:45:46 +02:00
|
|
|
#include <vcg/space/box3.h>
|
|
|
|
#include <vcg/space/line3.h>
|
2005-03-15 12:43:18 +01:00
|
|
|
#include <vcg/space/index/grid_util.h>
|
2005-09-30 15:15:21 +02:00
|
|
|
#include <vcg/space/index/grid_closest.h>
|
2005-09-14 11:05:32 +02:00
|
|
|
#include <vcg/simplex/face/distance.h>
|
2005-11-30 17:01:25 +01:00
|
|
|
|
2004-05-10 16:45:46 +02:00
|
|
|
namespace vcg {
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
/** Static Uniform Grid
|
|
|
|
A spatial search structure for a accessing a container of objects.
|
|
|
|
It is based on a uniform grid overlayed over a protion of space.
|
|
|
|
The grid partion the space into cells. Cells contains just pointers
|
|
|
|
to the object that are stored elsewhere.
|
|
|
|
The set of objects is meant to be static and pointer stable.
|
|
|
|
|
|
|
|
Useful for situation were many space related query are issued over
|
|
|
|
the same dataset (ray tracing, measuring distances between meshes,
|
|
|
|
re-detailing ecc.).
|
|
|
|
Works well for distribution that ar reasonably uniform.
|
|
|
|
How to use it:
|
|
|
|
ContainerType must have a 'value_type' typedef inside.
|
|
|
|
(stl containers already have it)
|
|
|
|
|
|
|
|
Objects pointed by cells (of kind 'value_type') must have
|
|
|
|
a 'ScalarType' typedef (float or double usually)
|
2005-09-09 13:01:02 +02:00
|
|
|
and a member function:
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
void GetBBox(Box3<ScalarType> &b)
|
|
|
|
which return the bounding box of the object
|
|
|
|
|
2005-09-09 13:01:02 +02:00
|
|
|
When using the GetClosest() method, the user must supply a functor object
|
|
|
|
(whose type is a method template argument) which expose the following
|
|
|
|
operator ():
|
|
|
|
|
|
|
|
bool operator () (const ObjType & obj, const Point3f & point, ScalarType & mindist, Point3f & result);
|
|
|
|
which return true if the distance from point to the object 'obj' is < mindist
|
|
|
|
and set mindist to said distance, and result must be set as the closest
|
|
|
|
point of the object to point)
|
2005-08-02 13:18:36 +02:00
|
|
|
*/
|
|
|
|
|
2005-12-02 01:25:13 +01:00
|
|
|
template < class OBJTYPE, class FLT=float >
|
2008-07-01 11:33:47 +02:00
|
|
|
class GridStaticPtr: public BasicGrid<FLT>, SpatialIndex<OBJTYPE,FLT>
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-09-30 15:15:21 +02:00
|
|
|
typedef OBJTYPE ObjType;
|
2005-08-02 13:18:36 +02:00
|
|
|
typedef ObjType* ObjPtr;
|
|
|
|
typedef typename ObjType::ScalarType ScalarType;
|
|
|
|
typedef Point3<ScalarType> CoordType;
|
|
|
|
typedef Box3<ScalarType> Box3x;
|
|
|
|
typedef Line3<ScalarType> Line3x;
|
2005-12-02 01:25:13 +01:00
|
|
|
typedef GridStaticPtr<OBJTYPE,FLT> GridPtrType;
|
2008-07-01 11:33:47 +02:00
|
|
|
typedef BasicGrid<FLT> BT;
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
/** Internal class for keeping the first pointer of object.
|
|
|
|
Definizione Link dentro la griglia. Classe di supporto per GridStaticObj.
|
|
|
|
*/
|
|
|
|
class Link
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/// Costruttore di default
|
|
|
|
inline Link(){};
|
|
|
|
/// Costruttore con inizializzatori
|
|
|
|
inline Link(ObjPtr nt, const int ni ){
|
|
|
|
assert(ni>=0);
|
|
|
|
t = nt;
|
|
|
|
i = ni;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
inline bool operator < ( const Link & l ) const{ return i < l.i; }
|
|
|
|
inline bool operator <= ( const Link & l ) const{ return i <= l.i; }
|
|
|
|
inline bool operator > ( const Link & l ) const{ return i > l.i; }
|
|
|
|
inline bool operator >= ( const Link & l ) const{ return i >= l.i; }
|
|
|
|
inline bool operator == ( const Link & l ) const{ return i == l.i; }
|
|
|
|
inline bool operator != ( const Link & l ) const{ return i != l.i; }
|
|
|
|
|
2005-09-16 13:57:15 +02:00
|
|
|
inline ObjPtr & Elem() {
|
2005-08-02 13:18:36 +02:00
|
|
|
return t;
|
|
|
|
}
|
2005-09-14 11:05:32 +02:00
|
|
|
|
|
|
|
ObjType &operator *(){return *(t);}
|
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
inline int & Index() {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Puntatore all'elemento T
|
|
|
|
ObjPtr t;
|
|
|
|
/// Indirizzo del voxel dentro la griglia
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
};//end class Link
|
|
|
|
|
|
|
|
typedef Link* Cell;
|
2005-09-16 13:57:15 +02:00
|
|
|
typedef Cell CellIterator;
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
std::vector<Link> links; /// Insieme di tutti i links
|
2005-09-14 11:05:32 +02:00
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
std::vector<Cell> grid; /// Griglia vera e propria
|
|
|
|
|
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
/// Date le coordinate di un grid point (corner minx,miy,minz) ritorna le celle che condividono
|
|
|
|
/// l'edge cell che parte dal grid point in direzione axis
|
|
|
|
inline void Grid( Point3i p, const int axis,
|
|
|
|
std::vector<Cell*> & cl)
|
|
|
|
{
|
2004-05-10 16:45:46 +02:00
|
|
|
#ifndef NDEBUG
|
2005-12-02 01:25:13 +01:00
|
|
|
if ( p[0]<0 || p[0] > BT::siz[0] ||
|
|
|
|
p[1]<0 || p[1]> BT::siz[1] ||
|
|
|
|
p[2]<0 || p[2]> BT::siz[2] )
|
2005-08-02 13:18:36 +02:00
|
|
|
assert(0);
|
|
|
|
//return NULL;
|
|
|
|
else
|
2004-05-10 16:45:46 +02:00
|
|
|
#endif
|
2005-12-02 01:25:13 +01:00
|
|
|
assert(((unsigned int) p[0]+BT::siz[0]*p[1]+BT::siz[1]*p[2])<grid.size());
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
int axis0 = (axis+1)%3;
|
|
|
|
int axis1 = (axis+2)%3;
|
|
|
|
int i,j,x,y;
|
|
|
|
x = p[axis0];
|
|
|
|
y = p[axis1];
|
2005-12-02 01:43:31 +01:00
|
|
|
for(i = std::max(x-1,0); i <= std::min( x,BT::siz[axis0]-1);++i)
|
|
|
|
for(j = std::max(y-1,0); j <= std::min( y,this->siz[axis1]-1);++j){
|
2005-08-02 13:18:36 +02:00
|
|
|
p[axis0]=i;
|
|
|
|
p[axis1]=j;
|
2005-12-02 01:25:13 +01:00
|
|
|
cl.push_back(Grid(p[0]+BT::siz[0]*(p[1]+BT::siz[1]*p[2])));
|
2005-08-02 13:18:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-30 17:07:28 +02:00
|
|
|
|
|
|
|
////////////////
|
2005-10-05 19:05:08 +02:00
|
|
|
// Official access functions
|
|
|
|
////////////////
|
|
|
|
/// BY CELL
|
|
|
|
Cell* Grid(const int i) {
|
2005-08-02 13:18:36 +02:00
|
|
|
return &grid[i];
|
|
|
|
}
|
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
void Grid( const Cell* g, Cell & first, Cell & last )
|
2005-09-30 17:07:28 +02:00
|
|
|
{
|
2005-08-02 13:18:36 +02:00
|
|
|
first = *g;
|
|
|
|
last = *(g+1);
|
2004-05-10 16:45:46 +02:00
|
|
|
}
|
2005-10-05 19:05:08 +02:00
|
|
|
|
2005-09-30 17:07:28 +02:00
|
|
|
/// BY INTEGER COORDS
|
|
|
|
inline Cell* Grid( const int x, const int y, const int z )
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2005-12-02 01:25:13 +01:00
|
|
|
assert(!( x<0 || x>=BT::siz[0] || y<0 || y>=BT::siz[1] || z<0 || z>=BT::siz[2] ));
|
2005-10-05 19:05:08 +02:00
|
|
|
assert(grid.size()>0);
|
2005-12-02 01:25:13 +01:00
|
|
|
return &*grid.begin() + ( x+BT::siz[0]*(y+BT::siz[1]*z) );
|
2005-08-02 13:18:36 +02:00
|
|
|
}
|
2005-09-30 17:07:28 +02:00
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
inline Cell* Grid( const Point3i &pi)
|
|
|
|
{
|
|
|
|
return Grid(pi[0],pi[1],pi[2]);
|
|
|
|
}
|
2005-09-30 17:07:28 +02:00
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
void Grid( const int x, const int y, const int z, Cell & first, Cell & last )
|
|
|
|
{
|
|
|
|
Cell* g = Grid(x,y,z);
|
|
|
|
first = *g;
|
|
|
|
last = *(g+1);
|
|
|
|
}
|
2005-09-30 17:07:28 +02:00
|
|
|
|
2005-12-02 01:25:13 +01:00
|
|
|
void Grid( const Point3<ScalarType> & p, Cell & first, Cell & last )
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2005-10-05 19:05:08 +02:00
|
|
|
Cell* g = Grid(GridP(p));
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
first = *g;
|
|
|
|
last = *(g+1);
|
|
|
|
}
|
2005-10-05 19:05:08 +02:00
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
/// Set the bounding box of the grid
|
|
|
|
///We need some extra space for numerical precision.
|
2005-08-26 11:27:58 +02:00
|
|
|
template <class Box3Type>
|
2005-10-05 19:05:08 +02:00
|
|
|
void SetBBox( const Box3Type & b )
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2005-12-02 01:25:13 +01:00
|
|
|
this->bbox.Import( b );
|
|
|
|
ScalarType t = this->bbox.Diag()/100.0;
|
2007-07-16 17:13:39 +02:00
|
|
|
if(t == 0) t = ScalarType(1e-20); // <--- Some doubts on this (Cigno 5/1/04)
|
2005-12-02 01:25:13 +01:00
|
|
|
this->bbox.Offset(t);
|
|
|
|
this->dim = this->bbox.max - this->bbox.min;
|
2005-08-02 13:18:36 +02:00
|
|
|
}
|
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
void ShowStats(FILE *fp)
|
|
|
|
{
|
|
|
|
// Conto le entry
|
|
|
|
//int nentry = 0;
|
|
|
|
//Hist H;
|
|
|
|
//H.SetRange(0,1000,1000);
|
|
|
|
//int pg;
|
|
|
|
//for(pg=0;pg<grid.size()-1;++pg)
|
|
|
|
// if( grid[pg]!=grid[pg+1] )
|
|
|
|
// {
|
|
|
|
// ++nentry;
|
|
|
|
// H.Add(grid[pg+1]-grid[pg]);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// fprintf(fp,"Uniform Grid: %d x %d x %d (%d voxels), %.1f%% full, %d links \nNon empty Cell Occupancy Distribution Avg: %f (%4.0f %4.0f %4.0f) \n",
|
|
|
|
// siz[0],siz[1],siz[2],grid.size()-1,
|
|
|
|
// double(nentry)*100.0/(grid.size()-1),links.size(),H.Avg(),H.Percentile(.25),H.Percentile(.5),H.Percentile(.75)
|
|
|
|
//
|
|
|
|
//);
|
|
|
|
}
|
|
|
|
|
2007-07-16 17:13:39 +02:00
|
|
|
template <class OBJITER>
|
|
|
|
inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd)
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2007-07-16 17:13:39 +02:00
|
|
|
Box3<FLT> _bbox;
|
2005-10-05 19:05:08 +02:00
|
|
|
Box3<FLT> b;
|
2007-07-16 17:13:39 +02:00
|
|
|
OBJITER i;
|
|
|
|
for(i = _oBegin; i!= _oEnd; ++i)
|
|
|
|
{
|
|
|
|
(*i).GetBBox(b);
|
|
|
|
_bbox.Add(b);
|
|
|
|
}
|
|
|
|
///inflate the bb calculated
|
2005-11-30 11:32:44 +01:00
|
|
|
int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
|
2007-07-16 17:13:39 +02:00
|
|
|
ScalarType infl=_bbox.Diag()/_size;
|
|
|
|
_bbox.min-=vcg::Point3<FLT>(infl,infl,infl);
|
|
|
|
_bbox.max+=vcg::Point3<FLT>(infl,infl,infl);
|
|
|
|
|
|
|
|
Set(_oBegin,_oEnd,_bbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function automatically compute a reasonable size for the uniform grid providing the side (radius) of the cell
|
|
|
|
//
|
|
|
|
// Note that the bbox must be already 'inflated' so to be sure that no object will fall on the border of the grid.
|
|
|
|
|
|
|
|
template <class OBJITER>
|
|
|
|
inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox, FLT radius)
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2007-07-16 17:13:39 +02:00
|
|
|
Point3i _siz;
|
|
|
|
Point3<FLT> _dim = _bbox.max - _bbox.min;
|
|
|
|
_dim/=radius;
|
|
|
|
assert(_dim[0]>0 && _dim[1]>0 && _dim[2]>0 );
|
2007-07-16 18:59:26 +02:00
|
|
|
_siz[0] = (int)ceil(_dim[0]);
|
|
|
|
_siz[1] = (int)ceil(_dim[1]);
|
|
|
|
_siz[2] = (int)ceil(_dim[2]);
|
|
|
|
|
2007-07-16 17:13:39 +02:00
|
|
|
Point3<FLT> offset=Point3<FLT>::Construct(_siz);
|
|
|
|
offset*=radius;
|
2007-07-16 18:59:26 +02:00
|
|
|
offset -= (_bbox.max - _bbox.min);
|
2007-07-16 17:13:39 +02:00
|
|
|
offset /=2;
|
|
|
|
|
|
|
|
assert( offset[0]>=0 && offset[1]>=0 && offset[2]>=0 );
|
|
|
|
|
2007-07-16 18:59:26 +02:00
|
|
|
Box3x bb = _bbox;
|
|
|
|
bb.min -= offset;
|
|
|
|
bb.max += offset;
|
2007-07-16 17:13:39 +02:00
|
|
|
|
2007-07-16 18:59:26 +02:00
|
|
|
Set(_oBegin,_oEnd, bb,_siz);
|
2007-07-16 17:13:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This function automatically compute a reasonable size for the uniform grid such that the number of cells is
|
|
|
|
// the same of the nubmer of elements to be inserted in the grid.
|
|
|
|
//
|
|
|
|
// Note that the bbox must be already 'inflated' so to be sure that no object will fall on the border of the grid.
|
|
|
|
|
|
|
|
template <class OBJITER>
|
|
|
|
inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox)
|
|
|
|
{
|
|
|
|
int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
|
|
|
|
Point3<FLT> _dim = _bbox.max - _bbox.min;
|
|
|
|
Point3i _siz;
|
|
|
|
BestDim( _size, _dim, _siz );
|
|
|
|
|
|
|
|
Set(_oBegin,_oEnd,_bbox,_siz);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class OBJITER>
|
|
|
|
inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox, Point3i _siz)
|
|
|
|
{
|
|
|
|
OBJITER i;
|
|
|
|
|
|
|
|
this->bbox=_bbox;
|
|
|
|
this->siz=_siz;
|
|
|
|
|
|
|
|
// find voxel size starting from the provided bbox and grid size.
|
|
|
|
|
|
|
|
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];
|
|
|
|
this->voxel[2] = this->dim[2]/this->siz[2];
|
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
// "Alloca" la griglia: +1 per la sentinella
|
2005-12-02 01:25:13 +01:00
|
|
|
grid.resize( this->siz[0]*this->siz[1]*this->siz[2]+1 );
|
2005-10-05 19:05:08 +02:00
|
|
|
|
|
|
|
// Ciclo inserimento dei tetraedri: creazione link
|
|
|
|
links.clear();
|
|
|
|
for(i=_oBegin; i!=_oEnd; ++i)
|
|
|
|
{
|
|
|
|
Box3x bb; // Boundig box del tetraedro corrente
|
|
|
|
(*i).GetBBox(bb);
|
2005-12-02 01:25:13 +01:00
|
|
|
bb.Intersect(this->bbox);
|
2005-10-05 19:05:08 +02:00
|
|
|
if(! bb.IsNull() )
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2005-10-05 19:05:08 +02:00
|
|
|
|
|
|
|
Box3i ib; // Boundig box in voxels
|
2008-07-29 15:01:10 +02:00
|
|
|
this->BoxToIBox( bb,ib );
|
2005-10-05 19:05:08 +02:00
|
|
|
int x,y,z;
|
|
|
|
for(z=ib.min[2];z<=ib.max[2];++z)
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2005-12-02 01:25:13 +01:00
|
|
|
int bz = z*this->siz[1];
|
2005-10-05 19:05:08 +02:00
|
|
|
for(y=ib.min[1];y<=ib.max[1];++y)
|
|
|
|
{
|
2005-12-02 01:25:13 +01:00
|
|
|
int by = (y+bz)*this->siz[0];
|
2005-10-05 19:05:08 +02:00
|
|
|
for(x=ib.min[0];x<=ib.max[0];++x)
|
|
|
|
// Inserire calcolo cella corrente
|
|
|
|
// if( pt->Intersect( ... )
|
|
|
|
links.push_back( Link(&(*i),by+x) );
|
|
|
|
}
|
2005-08-02 13:18:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-10-05 19:05:08 +02:00
|
|
|
// Push della sentinella
|
|
|
|
/*links.push_back( Link((typename ContainerType::iterator)NULL,
|
|
|
|
(grid.size()-1)));*/
|
2005-08-02 13:18:36 +02:00
|
|
|
|
2005-11-10 16:44:17 +01:00
|
|
|
links.push_back( Link( NULL, int(grid.size())-1) );
|
2005-08-02 13:18:36 +02:00
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
// Ordinamento dei links
|
|
|
|
sort( links.begin(), links.end() );
|
2005-08-02 13:18:36 +02:00
|
|
|
|
2005-10-05 19:05:08 +02:00
|
|
|
// Creazione puntatori ai links
|
|
|
|
typename std::vector<Link>::iterator pl;
|
|
|
|
unsigned int pg;
|
|
|
|
pl = links.begin();
|
|
|
|
for(pg=0;pg<grid.size();++pg)
|
2005-08-02 13:18:36 +02:00
|
|
|
{
|
2005-10-05 19:05:08 +02:00
|
|
|
assert(pl!=links.end());
|
|
|
|
grid[pg] = &*pl;
|
|
|
|
while( (int)pg == pl->Index() ) // Trovato inizio
|
|
|
|
{
|
|
|
|
++pl; // Ricerca prossimo blocco
|
|
|
|
if(pl==links.end())
|
|
|
|
break;
|
|
|
|
}
|
2005-08-02 13:18:36 +02:00
|
|
|
}
|
|
|
|
|
2005-12-02 01:25:13 +01:00
|
|
|
}
|
|
|
|
|
2005-08-02 13:18:36 +02:00
|
|
|
|
|
|
|
int MemUsed()
|
|
|
|
{
|
|
|
|
return sizeof(GridStaticPtr)+ sizeof(Link)*links.size() +
|
|
|
|
sizeof(Cell) * grid.size();
|
|
|
|
}
|
2005-09-30 15:15:21 +02:00
|
|
|
|
|
|
|
template <class OBJPOINTDISTFUNCTOR, class OBJMARKER>
|
|
|
|
ObjPtr GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker,
|
2008-09-24 11:28:53 +02:00
|
|
|
const typename OBJPOINTDISTFUNCTOR::QueryType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt)
|
2005-09-30 15:15:21 +02:00
|
|
|
{
|
|
|
|
return (vcg::GridClosest<GridPtrType,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<GridPtrType,
|
|
|
|
OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>(*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points));
|
|
|
|
}
|
2005-10-05 19:05:08 +02:00
|
|
|
|
2005-10-03 15:58:21 +02:00
|
|
|
template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
|
2005-10-05 19:05:08 +02:00
|
|
|
unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance,
|
|
|
|
OBJMARKER & _marker,
|
|
|
|
const CoordType & _p,
|
|
|
|
const ScalarType & _r,
|
|
|
|
OBJPTRCONTAINER & _objectPtrs,
|
|
|
|
DISTCONTAINER & _distances,
|
|
|
|
POINTCONTAINER & _points)
|
2005-10-03 15:58:21 +02:00
|
|
|
{
|
|
|
|
return(vcg::GridGetInSphere<GridPtrType,
|
|
|
|
OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
|
2005-10-05 19:05:08 +02:00
|
|
|
(*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points));
|
2005-10-03 15:58:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class OBJMARKER, class OBJPTRCONTAINER>
|
|
|
|
unsigned int GetInBox(OBJMARKER & _marker,
|
2005-12-02 01:25:13 +01:00
|
|
|
const vcg::Box3<ScalarType> _bbox,
|
2005-10-03 15:58:21 +02:00
|
|
|
OBJPTRCONTAINER & _objectPtrs)
|
|
|
|
{
|
|
|
|
return(vcg::GridGetInBox<GridPtrType,OBJMARKER,OBJPTRCONTAINER>
|
2005-10-05 19:05:08 +02:00
|
|
|
(*this,_marker,_bbox,_objectPtrs));
|
2005-10-03 15:58:21 +02:00
|
|
|
}
|
|
|
|
|
2005-09-30 15:15:21 +02:00
|
|
|
template <class OBJRAYISECTFUNCTOR, class OBJMARKER>
|
2005-10-05 19:05:08 +02:00
|
|
|
ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3<ScalarType> & _ray, const ScalarType & _maxDist, ScalarType & _t)
|
2005-09-30 15:15:21 +02:00
|
|
|
{
|
|
|
|
return(vcg::GridDoRay<GridPtrType,OBJRAYISECTFUNCTOR,OBJMARKER>(*this,_rayIntersector,_marker,_ray,_maxDist,_t));
|
|
|
|
}
|
2007-07-16 18:59:26 +02:00
|
|
|
|
|
|
|
/* If the grid has a cubic voxel of side <radius> this function
|
|
|
|
process all couple of elementes in neighbouring cells.
|
|
|
|
GATHERFUNCTOR needs to expose this method:
|
|
|
|
bool operator()(OBJTYPE *v1, OBJTYPE *v2);
|
|
|
|
which is then called ONCE per unordered pair v1,v2.
|
|
|
|
example:
|
|
|
|
|
|
|
|
struct GFunctor {
|
|
|
|
double radius2, iradius2;
|
|
|
|
GFunctor(double radius) { radius2 = radius*radius; iradius2 = 1/radius2; }
|
|
|
|
|
|
|
|
bool operator()(CVertex *v1, CVertex *v2) {
|
|
|
|
Point3d &p = v1->P();
|
|
|
|
Point3d &q = v2->P();
|
|
|
|
double dist2 = (p-q).SquaredNorm();
|
|
|
|
if(dist2 < radius2) {
|
|
|
|
double w = exp(dist2*iradius2);
|
|
|
|
//do something
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}; */
|
|
|
|
|
|
|
|
template <class GATHERFUNCTOR>
|
|
|
|
void Gather(GATHERFUNCTOR gfunctor) {
|
|
|
|
static int corner[8*3] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
|
|
|
|
0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 };
|
|
|
|
|
|
|
|
static int diagonals[14*2] = { 0, 0,
|
|
|
|
0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7,
|
|
|
|
2, 3, 1, 3, 1, 2,
|
|
|
|
1, 4, 2, 5, 3, 6 };
|
|
|
|
|
|
|
|
Cell ostart, oend, dstart, dend;
|
|
|
|
for(int z = 0; z < this->siz[2]; z++) {
|
|
|
|
for(int y = 0; y < this->siz[1]; y++) {
|
|
|
|
for(int x = 0; x < this->siz[0]; x++) {
|
|
|
|
|
|
|
|
Grid(x, y, z, ostart, oend);
|
|
|
|
|
|
|
|
for(Cell c = ostart; c != oend; c++)
|
|
|
|
for(Cell s = c+1; s != oend; s++)
|
|
|
|
gfunctor(c->Elem(), s->Elem());
|
|
|
|
|
|
|
|
for(int d = 2; d < 28; d += 2) { //skipping self
|
|
|
|
int *cs = corner + 3*diagonals[d];
|
|
|
|
int *ce = corner + 3*diagonals[d+1];
|
|
|
|
if((x + cs[0] < this->siz[0]) && (y + cs[1] < this->siz[1]) && (z + cs[2] < this->siz[2]) &&
|
|
|
|
(x + ce[0] < this->siz[0]) && (y + ce[1] < this->siz[1]) && (z + ce[2] < this->siz[2])) {
|
|
|
|
|
|
|
|
Grid(x+cs[0], y+cs[1], z+cs[2], ostart, oend);
|
|
|
|
Grid(x+ce[0], y+ce[1], z+ce[2], dstart, dend);
|
|
|
|
|
|
|
|
for(Cell c = ostart; c != oend; c++)
|
|
|
|
for(Cell s = dstart; s != dend; s++)
|
|
|
|
gfunctor(c->Elem(), s->Elem());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-30 15:15:21 +02:00
|
|
|
|
|
|
|
}; //end class GridStaticPtr
|
2005-08-02 13:18:36 +02:00
|
|
|
|
2005-12-02 01:25:13 +01:00
|
|
|
} // end namespace
|
2004-05-10 16:45:46 +02:00
|
|
|
|
|
|
|
#endif
|