Walker.h
Go to the documentation of this file.
00001 #ifndef __VCGTEST_WALKER
00002 #define __VCGTEST_WALKER
00003 
00004 #include "Definitions.h"
00005 #include "Volume.h"
00006 
00007 // La classe Walker implementa la politica di visita del volume; conoscendo l'ordine di visita del volume
00008 // è conveniente che il Walker stesso si faccia carico del caching dei dati utilizzati durante l'esecuzione 
00009 // degli algoritmi MarchingCubes ed ExtendedMarchingCubes, in particolare il calcolo del volume ai vertici
00010 // delle celle e delle intersezioni della superficie con le celle. In questo esempio il volume da processare
00011 // viene suddiviso in fette; in questo modo se il volume ha dimensione h*l*w (rispettivamente altezza,
00012 // larghezza e profondità), lo spazio richiesto per il caching dei vertici già allocati passa da O(h*l*w)
00013 // a O(h*l). 
00014 class Walker
00015 {
00016 private:
00017         typedef int VertexIndex;
00018 
00019 public:
00020         Walker(const BoundingBox &bbox, const vcg::Point3i &resolution)
00021         {
00022                 _bbox                           = bbox;
00023                 _resolution = resolution;
00024                 _cell_size.X() = _bbox.DimX()/_resolution.X();
00025                 _cell_size.Y() = _bbox.DimY()/_resolution.Y();
00026                 _cell_size.Z() = _bbox.DimZ()/_resolution.Z();
00027                 _slice_dimension = resolution.X()*resolution.Z();
00028 
00029                 _x_cs = new VertexIndex[ _slice_dimension ];
00030                 _y_cs = new VertexIndex[ _slice_dimension ];
00031                 _z_cs = new VertexIndex[ _slice_dimension ];
00032                 _x_ns = new VertexIndex[ _slice_dimension ];
00033                 _z_ns = new VertexIndex[ _slice_dimension ];
00034                 _v_cs = new float[_slice_dimension];
00035                 _v_ns = new float[_slice_dimension];
00036 
00037         };
00038 
00039         ~Walker()
00040         {}
00041 
00042         template<class EXTRACTOR_TYPE>
00043         void BuildMesh(Mesh &mesh, Volume &volume, EXTRACTOR_TYPE &extractor)
00044         {
00045                 _volume = &volume;
00046                 _mesh           = &mesh;
00047                 _mesh->Clear();
00048                 vcg::Point3i p1, p2;
00049 
00050                 Begin();
00051                 extractor.Initialize();
00052                 for (int j=_bbox.min.Y(); j<_bbox.max.Y()-_cell_size.Y(); j+=_cell_size.Y())
00053                 {
00054                         for (int i=_bbox.min.X(); i<_bbox.max.X()-_cell_size.X(); i+=_cell_size.X())
00055                         {
00056                                 for (int k=_bbox.min.Z(); k<_bbox.max.Z()-_cell_size.Z(); k+=_cell_size.Z())
00057                                 {
00058                                         p1.X()=i;                                                                       p1.Y()=j;                                                                       p1.Z()=k;
00059                                         p2.X()=i+_cell_size.X();        p2.Y()=j+_cell_size.Y();        p2.Z()=k+_cell_size.Z();
00060                                         extractor.ProcessCell(p1, p2);
00061                                 }
00062                         }
00063                         NextSlice();
00064                 }
00065                 extractor.Finalize();
00066                 _volume = NULL;
00067                 _mesh           = NULL;
00068         };
00069 
00070         float V(int pi, int pj, int pk)
00071         {
00072                 int i = pi - _bbox.min.X();
00073                 int k = pk - _bbox.min.Z();
00074                 return (pj==_current_slice) ? _v_cs[i+k*_resolution.X()] : _v_ns[i+k*_resolution.X()];
00075         }
00076 
00077         bool Exist(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00078         { 
00079                 int i_idx = p1.X()-_bbox.min.X();
00080                 int k_idx = p2.Z()-_bbox.min.Z();
00081                 int index = i_idx+k_idx*_resolution.X();
00082                 if (p1.X()!=p2.X())                                     //intersezione della superficie con un Xedge
00083                         return (p1.Y()==_current_slice)? _x_cs[index]!=-1 : _x_ns[index]!=-1;
00084                 else if (p1.Y()!=p2.Y())                //intersezione della superficie con un Yedge
00085                         return _y_cs[index]!=-1;
00086                 else if (p1.Z()!=p2.Z())                //intersezione della superficie con un Zedge
00087                         return (p1.Y()==_current_slice)? _z_cs[index]!=-1 : _z_ns[index]!=-1;
00088 
00089                 assert(false); // impossibile: i due punti non erano allineati rispetto a nessuna direzione
00090                 return false;
00091         }
00092 
00093         void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) 
00094         { 
00095                 int i = p1.X() - _bbox.min.X();
00096                 int z = p1.Z() - _bbox.min.Z();
00097                 VertexIndex index = i+z*_resolution.X();
00098                 VertexIndex pos;
00099                 if (p1.Y()==_current_slice)
00100                 {
00101                         if ((pos=_x_cs[index])==-1)
00102                         {
00103                                 _x_cs[index] = (VertexIndex) _mesh->vert.size();
00104                                 pos = _x_cs[index];
00105                                 Allocator::AddVertices( *_mesh, 1 );
00106                                 v = &_mesh->vert[pos];
00107                                 _volume->GetXIntercept(p1, p2, v);
00108                                 return;
00109                         }
00110                 }
00111                 if (p1.Y()==_current_slice+_cell_size.Y())
00112                 {
00113                         if ((pos=_x_ns[index])==-1)
00114                         {
00115                                 _x_ns[index] = (VertexIndex) _mesh->vert.size();
00116                                 pos = _x_ns[index];
00117                                 Allocator::AddVertices( *_mesh, 1 );
00118                                 v = &_mesh->vert[pos];
00119                                 _volume->GetXIntercept(p1, p2, v);
00120                                 return;
00121                         }
00122                 }
00123                 v = &_mesh->vert[pos];
00124         }
00125         void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) 
00126         {
00127                 int i = p1.X() - _bbox.min.X();
00128                 int z = p1.Z() - _bbox.min.Z();
00129                 VertexIndex index = i+z*_resolution.X();
00130                 VertexIndex pos;
00131                 if ((pos=_y_cs[index])==-1)
00132                 {
00133                         _y_cs[index] = (VertexIndex) _mesh->vert.size();
00134                         pos = _y_cs[index];
00135                         Allocator::AddVertices( *_mesh, 1);
00136                         v = &_mesh->vert[ pos ];
00137                         _volume->GetYIntercept(p1, p2, v);
00138                 }
00139                 v = &_mesh->vert[pos];
00140         }
00141         void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) 
00142         {
00143                 int i = p1.X() - _bbox.min.X();
00144                 int z = p1.Z() - _bbox.min.Z();
00145                 VertexIndex index = i+z*_resolution.X();
00146                 VertexIndex pos;
00147                 if (p1.Y()==_current_slice)
00148                 {
00149                         if ((pos=_z_cs[index])==-1)
00150                         {
00151                                 _z_cs[index] = (VertexIndex) _mesh->vert.size();
00152                                 pos = _z_cs[index];
00153                                 Allocator::AddVertices( *_mesh, 1 );
00154                                 v = &_mesh->vert[pos];
00155                                 _volume->GetZIntercept(p1, p2, v);
00156                                 return;
00157                         }
00158                 }
00159                 if (p1.Y()==_current_slice+_cell_size.Y())
00160                 {
00161                         if ((pos=_z_ns[index])==-1)
00162                         {
00163                                 _z_ns[index] = (VertexIndex) _mesh->vert.size();
00164                                 pos = _z_ns[index];
00165                                 Allocator::AddVertices( *_mesh, 1 );
00166                                 v = &_mesh->vert[pos];
00167                                 _volume->GetZIntercept(p1, p2, v);
00168                                 return;
00169                         }
00170                 }
00171                 v = &_mesh->vert[pos];
00172         }
00173 
00174 protected:
00175         BoundingBox             _bbox;
00176         vcg::Point3i    _resolution;
00177         vcg::Point3i    _cell_size;
00178 
00179         int _slice_dimension;
00180         int     _current_slice;
00181   
00182         float *_v_cs; // il valore del campo campionato nella fetta di volumecorrente 
00183         float *_v_ns; // il valore del campo campionato nella prossima fetta di volume
00184         
00185         VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente
00186         VertexIndex     *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente
00187         VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente
00188         VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta 
00189         VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta 
00190 
00191         Mesh            *_mesh;
00192         Volume  *_volume;
00193 
00194         void NextSlice() 
00195         {
00196                 memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00197                 memset(_y_cs,   -1, _slice_dimension*sizeof(VertexIndex));
00198                 memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00199 
00200                 std::swap(_x_cs, _x_ns);
00201                 std::swap(_z_cs, _z_ns);                
00202                 std::swap(_v_cs, _v_ns);
00203                 
00204                 _current_slice += _cell_size.Y();
00205                 int j                                           = _current_slice + _cell_size.Y();
00206                 int k_idx, i_idx, index;
00207                 for (int i=_bbox.min.X(); i<_bbox.max.X(); i+=_cell_size.X())
00208                 {
00209                         i_idx = i-_bbox.min.X();
00210                         for (int k=_bbox.min.Z(); k<_bbox.max.Z(); k+=_cell_size.Z())
00211                         {
00212                                 k_idx = k-_bbox.min.Z();
00213                                 index = i_idx+k_idx*_resolution.X();
00214                                 _v_ns[ index ] = _volume->V(i, j, k);
00215                         }
00216                 }
00217         }
00218 
00219         void Begin()
00220         {
00221                 _current_slice = _bbox.min.Y();
00222 
00223                 memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00224                 memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
00225                 memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00226                 memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex));
00227                 memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex));
00228                 
00229                 int index;
00230                 int j = _current_slice;
00231                 int i_idx, k_idx;
00232                 for (int i=_bbox.min.X(); i<_bbox.max.X(); i+=_cell_size.X())
00233                 {
00234                         i_idx = i-_bbox.min.X();
00235                         for (int k=_bbox.min.Z(); k<_bbox.max.Z(); k+=_cell_size.Z())
00236                         {
00237                                 k_idx = k-_bbox.min.Z();
00238                                 index = i_idx+k_idx*_resolution.X();
00239                                 _v_cs[index] = _volume->V(i, j, k);
00240                                 _v_ns[index] = _volume->V(i, j+_cell_size.Y(), k);
00241                         }
00242                 }
00243         }
00244 };
00245 #endif // __VCGTEST_WALKER


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:38:47