mc_trivial_walker.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004-2009                                           \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 #ifndef __VCG_TRIVIAL_WALKER
00024 #define __VCG_TRIVIAL_WALKER
00025 
00026 namespace vcg {
00027 
00028 // Very simple volume class.
00029 // just an example of the interface that the trivial walker expects
00030 
00031 template <class VOX_TYPE>
00032 class SimpleVolume : public BasicGrid<typename VOX_TYPE::ScalarType>
00033 {
00034 public:
00035   typedef VOX_TYPE VoxelType;
00036   typedef typename VoxelType::ScalarType ScalarType;
00037   typedef typename BasicGrid<typename VOX_TYPE::ScalarType>::Box3x Box3x;
00038 
00039   const Point3i &ISize() {return this->siz;}   
00040 
00041   ScalarType Val(const int &x,const int &y,const int &z) const {
00042     return cV(x,y,z).V();
00043     //else return numeric_limits<float>::quiet_NaN( );
00044   }
00045 
00046   ScalarType &Val(const int &x,const int &y,const int &z) {
00047     return V(x,y,z).V();
00048     //else return numeric_limits<float>::quiet_NaN( );
00049   }
00050 
00051   VOX_TYPE &V(const int &x,const int &y,const int &z) {
00052     return Vol[x+y*this->siz[0]+z*this->siz[0]*this->siz[1]];
00053   }
00054 
00055   VOX_TYPE &V(const Point3i &pi) {
00056     return Vol[ pi[0] + pi[1]*this->siz[0] + pi[2]*this->siz[0]*this->siz[1] ];
00057   }
00058 
00059   const VOX_TYPE &cV(const int &x,const int &y,const int &z) const {
00060     return Vol[x+y*this->siz[0]+z*this->siz[0]*this->siz[1]];
00061   }
00062 
00063   bool ValidCell(const Point3i & /*p0*/, const Point3i & /*p1*/) const { return true;}
00064 
00065   template < class VertexPointerType >
00066   void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00067   { GetIntercept<VertexPointerType,XAxis>(p1,p2,v,thr); }
00068 
00069   template < class VertexPointerType >
00070   void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00071   { GetIntercept<VertexPointerType,YAxis>(p1,p2,v,thr); }
00072 
00073   template < class VertexPointerType >
00074   void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00075   { GetIntercept<VertexPointerType,ZAxis>(p1,p2,v,thr); }
00076 
00079 
00080   std::vector<VoxelType> Vol;
00081 
00082   typedef enum { XAxis=0,YAxis=1,ZAxis=2} VolumeAxis;
00083 
00084   template < class VertexPointerType,  VolumeAxis AxisVal >
00085   void GetIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00086   {
00087     float f1 = V(p1).V()-thr;
00088     float f2 = V(p2).V()-thr;
00089     float u = (float) f1/(f1-f2);
00090     if(AxisVal==XAxis) v->P().X() = (float) p1.X()*(1-u) + u*p2.X();
00091     else v->P().X() = (float) p1.X();
00092     if(AxisVal==YAxis) v->P().Y() = (float) p1.Y()*(1-u) + u*p2.Y();
00093     else v->P().Y() = (float) p1.Y();
00094     if(AxisVal==ZAxis) v->P().Z() = (float) p1.Z()*(1-u) + u*p2.Z();
00095     else v->P().Z() = (float) p1.Z();
00096     this->IPfToPf(v->P(),v->P());
00097     if(VoxelType::HasNormal()) v->N().Import(V(p1).N()*(1-u) + V(p2).N()*u);
00098   }
00099 
00100 
00101 
00102   void Init(Point3i _sz, Box3x bb)
00103   {
00104     this->siz=_sz;
00105     this->bbox = bb;
00106     Vol.resize(this->siz[0]*this->siz[1]*this->siz[2]);
00107     this->ComputeDimAndVoxel();
00108   }
00109 
00110 
00111 
00112 };
00113 template <class _ScalarType=float>
00114 class SimpleVoxel
00115 {
00116 private:
00117   _ScalarType _v;
00118 public:
00119   typedef _ScalarType ScalarType;
00120   ScalarType &V() {return _v;}
00121   ScalarType V() const {return _v;}
00122   static bool HasNormal() {return false;}
00123   vcg::Point3<ScalarType> N() const {return Point3<ScalarType>(0,0,0);}
00124   vcg::Point3<ScalarType> &N()  { static Point3<ScalarType> _p(0,0,0); return _p;}
00125 };
00126 
00127 template <class _ScalarType=float>
00128 class SimpleVoxelWithNormal
00129 {
00130 private:
00131   _ScalarType _v;
00132   vcg::Point3<_ScalarType> _n;
00133 public:
00134   typedef _ScalarType ScalarType;
00135   ScalarType &V() {return _v;}
00136   ScalarType V() const {return _v;}
00137   vcg::Point3<ScalarType> &N() {return _n;}
00138   vcg::Point3<ScalarType> N() const {return _n;}
00139   static bool HasNormal() {return true;}
00140 
00141 };
00142 
00143 
00144 namespace tri {
00145 
00146 
00147 // La classe Walker implementa la politica di visita del volume; conoscendo l'ordine di visita del volume
00148 // Ë conveniente che il Walker stesso si faccia carico del caching dei dati utilizzati durante l'esecuzione
00149 // degli algoritmi MarchingCubes ed ExtendedMarchingCubes, in particolare il calcolo del volume ai vertici
00150 // delle celle e delle intersezioni della superficie con le celle. In questo esempio il volume da processare
00151 // viene suddiviso in fette; in questo modo se il volume ha dimensione h*l*w (rispettivamente altezza,
00152 // larghezza e profondit‡), lo spazio richiesto per il caching dei vertici gi‡ allocati passa da O(h*l*w)
00153 // a O(h*l).
00154 
00155 template <class MeshType, class VolumeType>
00156 class TrivialWalker
00157 {
00158 private:
00159     typedef int VertexIndex;
00160   typedef typename MeshType::ScalarType ScalarType;
00161   typedef typename MeshType::VertexPointer VertexPointer;
00162     public:
00163 
00164   // subbox is the portion of the volume to be computed
00165   // resolution determine the sampling step:
00166   // should be a divisor of bbox size (e.g. if bbox size is 256^3 resolution could be 128,64, etc)
00167 
00168   void Init(VolumeType &volume)
00169   {
00170     Init(volume,Box3i(Point3i(0,0,0),volume.ISize()));
00171   }
00172 
00173   void Init(VolumeType &/*volume*/, Box3i subbox)
00174     {
00175         _bbox                           = subbox;
00176         _slice_dimension = _bbox.DimX()*_bbox.DimZ();
00177 
00178         _x_cs = new VertexIndex[ _slice_dimension ];
00179         _y_cs = new VertexIndex[ _slice_dimension ];
00180         _z_cs = new VertexIndex[ _slice_dimension ];
00181         _x_ns = new VertexIndex[ _slice_dimension ];
00182         _z_ns = new VertexIndex[ _slice_dimension ];
00183 
00184     }
00185 
00186     ~TrivialWalker()
00187     {_thr=0;}
00188 
00189     template<class EXTRACTOR_TYPE>
00190   void BuildMesh(MeshType &mesh, VolumeType &volume, EXTRACTOR_TYPE &extractor, const float threshold, vcg::CallBackPos * cb=0)
00191   {
00192     Init(volume);
00193     _volume = &volume;
00194     _mesh               = &mesh;
00195     _mesh->Clear();
00196     _thr=threshold;
00197     vcg::Point3i p1, p2;
00198 
00199     Begin();
00200     extractor.Initialize();
00201     for (int j=_bbox.min.Y(); j<(_bbox.max.Y()-1)-1; j+=1)
00202     {
00203 
00204       if(cb && ((j%10)==0) )    cb(j*_bbox.DimY()/100.0,"Marching volume");
00205 
00206       for (int i=_bbox.min.X(); i<(_bbox.max.X()-1)-1; i+=1)
00207       {
00208         for (int k=_bbox.min.Z(); k<(_bbox.max.Z()-1)-1; k+=1)
00209         {
00210           p1.X()=i;       p1.Y()=j;     p1.Z()=k;
00211           p2.X()=i+1; p2.Y()=j+1;       p2.Z()=k+1;
00212           if(volume.ValidCell(p1,p2))
00213             extractor.ProcessCell(p1, p2);
00214         }
00215       }
00216       NextSlice();
00217     }
00218     extractor.Finalize();
00219     _volume = NULL;
00220     _mesh               = NULL;
00221   }
00222 
00223     float V(int pi, int pj, int pk)
00224     {
00225     return _volume->Val(pi, pj, pk)-_thr;
00226     }
00227 
00228     bool Exist(const vcg::Point3i &p0, const vcg::Point3i &p1, VertexPointer &v)
00229     {
00230         int pos = p0.X()+p0.Z()*_bbox.max.X();
00231         int vidx;
00232 
00233         if (p0.X()!=p1.X()) // punti allineati lungo l'asse X
00234             vidx = (p0.Y()==_current_slice) ? _x_cs[pos] : _x_ns[pos];
00235         else if (p0.Y()!=p1.Y()) // punti allineati lungo l'asse Y
00236             vidx = _y_cs[pos];
00237         else if (p0.Z()!=p1.Z()) // punti allineati lungo l'asse Z
00238             vidx = (p0.Y()==_current_slice)? _z_cs[pos] : _z_ns[pos];
00239         else
00240             assert(false);
00241 
00242         v = (vidx!=-1)? &_mesh->vert[vidx] : NULL;
00243         return v!=NULL;
00244     }
00245 
00246     void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00247     {
00248         int i = p1.X() - _bbox.min.X();
00249         int z = p1.Z() - _bbox.min.Z();
00250         VertexIndex index = i+z*_bbox.max.X();
00251         VertexIndex pos;
00252         if (p1.Y()==_current_slice)
00253         {
00254             if ((pos=_x_cs[index])==-1)
00255             {
00256                 _x_cs[index] = (VertexIndex) _mesh->vert.size();
00257                 pos = _x_cs[index];
00258                 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00259                 v = &_mesh->vert[pos];
00260                 _volume->GetXIntercept(p1, p2, v, _thr);
00261                 return;
00262             }
00263         }
00264         if (p1.Y()==_current_slice+1)
00265         {
00266             if ((pos=_x_ns[index])==-1)
00267             {
00268                 _x_ns[index] = (VertexIndex) _mesh->vert.size();
00269                 pos = _x_ns[index];
00270                 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00271                 v = &_mesh->vert[pos];
00272                 _volume->GetXIntercept(p1, p2, v,_thr);
00273                 return;
00274             }
00275         }
00276     assert(pos >=0 && size_t(pos)< _mesh->vert.size());
00277         v = &_mesh->vert[pos];
00278     }
00279     void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00280     {
00281         int i = p1.X() - _bbox.min.X();
00282         int z = p1.Z() - _bbox.min.Z();
00283         VertexIndex index = i+z*_bbox.max.X();
00284         VertexIndex pos;
00285         if ((pos=_y_cs[index])==-1)
00286         {
00287             _y_cs[index] = (VertexIndex) _mesh->vert.size();
00288             pos = _y_cs[index];
00289             Allocator<MeshType>::AddVertices( *_mesh, 1);
00290             v = &_mesh->vert[ pos ];
00291             _volume->GetYIntercept(p1, p2, v,_thr);
00292         }
00293         v = &_mesh->vert[pos];
00294     }
00295     void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00296     {
00297         int i = p1.X() - _bbox.min.X();
00298         int z = p1.Z() - _bbox.min.Z();
00299         VertexIndex index = i+z*_bbox.max.X();
00300         VertexIndex pos;
00301         if (p1.Y()==_current_slice)
00302         {
00303             if ((pos=_z_cs[index])==-1)
00304             {
00305                 _z_cs[index] = (VertexIndex) _mesh->vert.size();
00306                 pos = _z_cs[index];
00307                 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00308                 v = &_mesh->vert[pos];
00309                 _volume->GetZIntercept(p1, p2, v,_thr);
00310                 return;
00311             }
00312         }
00313         if (p1.Y()==_current_slice+1)
00314         {
00315             if ((pos=_z_ns[index])==-1)
00316             {
00317                 _z_ns[index] = (VertexIndex) _mesh->vert.size();
00318                 pos = _z_ns[index];
00319                 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00320                 v = &_mesh->vert[pos];
00321                 _volume->GetZIntercept(p1, p2, v,_thr);
00322                 return;
00323             }
00324         }
00325         v = &_mesh->vert[pos];
00326     }
00327 
00328 protected:
00329     Box3i               _bbox;
00330 
00331     int _slice_dimension;
00332     int _current_slice;
00333 
00334     VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente
00335     VertexIndex *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente
00336     VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente
00337     VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta
00338     VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta
00339 
00340     MeshType            *_mesh;
00341     VolumeType  *_volume;
00342 
00343   float _thr;
00344     void NextSlice()
00345     {
00346         memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00347         memset(_y_cs,   -1, _slice_dimension*sizeof(VertexIndex));
00348         memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00349 
00350         std::swap(_x_cs, _x_ns);
00351         std::swap(_z_cs, _z_ns);
00352 
00353         _current_slice += 1;
00354     }
00355 
00356     void Begin()
00357     {
00358         _current_slice = _bbox.min.Y();
00359 
00360         memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00361         memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
00362         memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00363         memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex));
00364         memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex));
00365 
00366     }
00367 };
00368 } // end namespace tri
00369 } // end namespace vcg
00370 #endif // __VCGTEST_WALKER


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