File indexing completed on 2024-04-28 03:40:49

0001 // Aqsis
0002 // Copyright (C) 2006, Paul C. Gregory
0003 //
0004 // Contact: pgregory@aqsis.org
0005 //
0006 // This library is free software; you can redistribute it and/or
0007 // modify it under the terms of the GNU General Public
0008 // License as published by the Free Software Foundation; either
0009 // version 2 of the License, or (at your option) any later version.
0010 //
0011 // This library is distributed in the hope that it will be useful,
0012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014 // General Public License for more details.
0015 //
0016 // You should have received a copy of the GNU General Public
0017 // License along with this library; if not, write to the Free Software
0018 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
0019 
0020 /** \file
0021     \brief MarchingCubes Algorithm
0022     \author Thomas Lewiner <thomas.lewiner@polytechnique.org>
0023     \author Math Dept, PUC-Rio
0024     \version 0.2
0025     \date    12/08/2002
0026 */
0027 
0028 // Minor modifications for KDE-Edu/Analitza Library: Copyright (C) 2014 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com>
0029 
0030 #ifndef MARCHINGCUBES_H
0031 #define MARCHINGCUBES_H
0032 
0033 #include <QVector>
0034 
0035 struct SpaceLimits {
0036     double minX;
0037     double maxX;
0038     double minY;
0039     double maxY;
0040     double minZ;
0041     double maxZ;
0042 };
0043 
0044 
0045 
0046 
0047 
0048 
0049 // Compute normals
0050 #define COMPUTE_NORMALS 1
0051 
0052 #include <QDebug>
0053 // types
0054 //-----------------------------------------------------------------------------
0055 // Vertex structure
0056 /** \struct Vertex "MarchingCubes.h" MarchingCubes
0057  * Position and normal of a vertex
0058  * \brief vertex structure
0059  * \param x X coordinate
0060  * \param y Y coordinate
0061  * \param z Z coordinate
0062  * \param nx X component of the normal
0063  * \param ny Y component of the normal
0064  * \param nz Z component of the normal
0065  */
0066 typedef struct
0067 {
0068   double  x,  y,  z ;  /**< Vertex coordinates */
0069 #ifdef COMPUTE_NORMALS
0070   double nx, ny, nz ;  /**< Vertex normal */
0071 #endif
0072 } Vertex ;
0073 
0074 //-----------------------------------------------------------------------------
0075 // Triangle structure
0076 /** \struct Triangle "MarchingCubes.h" MarchingCubes
0077  * Indices of the oriented triange vertices
0078  * \brief triangle structure
0079  * \param v1 First vertex index
0080  * \param v2 Second vertex index
0081  * \param v3 Third vertex index
0082  */
0083 typedef struct
0084 {
0085   int v1,v2,v3 ;  /**< Triangle vertices */
0086 } Triangle ;
0087 //_____________________________________________________________________________
0088 
0089 
0090 
0091 //_____________________________________________________________________________
0092 /** Marching Cubes algorithm wrapper */
0093 class MarchingCubes
0094 //-----------------------------------------------------------------------------
0095 {
0096 // Constructors
0097 public :
0098   /**
0099    * Main and default constructor
0100    * \brief constructor
0101    * \param size_x width  of the grid
0102    * \param size_y depth  of the grid
0103    * \param size_z height of the grid
0104    */
0105   MarchingCubes () ;
0106   /** Destructor */
0107   virtual ~MarchingCubes() ;
0108 
0109     virtual double evalScalarField(double x, double y, double z) = 0;
0110     void setupSpace(const SpaceLimits &spaceLimits);
0111     void buildGeometry() {run();}
0112 
0113 //-----------------------------------------------------------------------------
0114 // Accessors
0115 
0116   /** accesses the number of vertices of the generated mesh */
0117   int nverts() const { return i_nverts ; }
0118   /** accesses the number of triangles of the generated mesh */
0119   int ntrigs() const { return i_ntrigs ; }
0120   /** accesses a specific vertex of the generated mesh */
0121   Vertex   * vert( const int i ) const { if( i < 0  || i >= i_nverts ) return ( Vertex *)nullptr ; return i_vertices  + i ; }
0122   /** accesses a specific triangle of the generated mesh */
0123   Triangle * trig( const int i ) const { if( i < 0  || i >= i_ntrigs ) return (Triangle*)nullptr ; return i_triangles + i ; }
0124 
0125   /** accesses the vertex buffer of the generated mesh */
0126   Vertex   *mc_vertices () { return i_vertices  ; }
0127   /** accesses the triangle buffer of the generated mesh */
0128   Triangle *triangles() { return i_triangles ; }
0129 
0130   /**  accesses the width  of the grid */
0131   int size_x() const { return i_size_x ; }
0132   /**  accesses the depth  of the grid */
0133   int size_y() const { return i_size_y ; }
0134   /**  accesses the height of the grid */
0135   int size_z() const { return i_size_z ; }
0136 
0137   /**
0138    * changes the size of the grid
0139    * \param size_x width  of the grid
0140    * \param size_y depth  of the grid
0141    * \param size_z height of the grid
0142    * se encesita llamar a setup space y buildgeometry para que se tome efecto ... esto solo cambia los attr de la clase
0143    */
0144   void set_resolution( const int size_x, const int size_y, const int size_z ) { i_size_x = size_x ;  i_size_y = size_y ;  i_size_z = size_z ; }
0145   
0146   
0147 
0148   // Data access
0149   /**
0150    * accesses a specific cube of the grid
0151    * \param i abscisse of the cube
0152    * \param j ordinate of the cube
0153    * \param k height of the cube
0154    */
0155   double get_data  ( const int i, const int j, const int k ) const { return i_data[ i + j*i_size_x + k*i_size_x*i_size_y] ; }
0156 
0157 //eval de analitza es muy costoso, asi que este aproach esta deprecated... es mejor el triple bucle para llenar la data
0158 //   const double get_data  ( const int i, const int j, const int k )  
0159 //   {
0160 //       double x = xmin+hx*i;
0161 //       double y = ymin+hy*j;
0162 //       double z = zmin+hz*k;
0163 // 
0164 // //       qDebug() << x << y << z;
0165 //       
0166 //       return evalScalarField(x,y,z);
0167 //   }
0168 
0169 
0170   /**
0171    * sets a specific cube of the grid
0172    * \param val new value for the cube
0173    * \param i abscisse of the cube
0174    * \param j ordinate of the cube
0175    * \param k height of the cube
0176    */
0177   void  set_data  ( const double val, const int i, const int j, const int k ) { i_data[ i + j*i_size_x + k*i_size_x*i_size_y] = val ; }
0178 
0179 private:
0180   /**
0181    * selects whether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes
0182    * \param originalMC true for the original Marching Cubes
0183    * DEPRECATED el metodo original no tiene consistencia topologica
0184    */
0185   void set_method    ( const bool originalMC = false ) { i_originalMC = originalMC ; }
0186 
0187   // Data initialization
0188   /** inits temporary structures (must set sizes before call) : the grid and the vertex index per cube */
0189   void init_temps () ;
0190   /** inits all structures (must set sizes before call) : the temporary structures and the mesh buffers */
0191   void init_all   () ;
0192   /** clears temporary structures : the grid and the main */
0193   void clean_temps() ;
0194   /** clears all structures : the temporary structures and the mesh buffers */
0195   void clean_all  () ;
0196 
0197 
0198 //-----------------------------------------------------------------------------
0199 // Exportation
0200 public :
0201   /**
0202    * GTS exportation of the generated mesh
0203    * \param fn  name of the GTS file to create
0204    * \param bin if true, the GTS will be written in binary mode
0205    */
0206   void write( const char *fn, bool bin = false ) ;
0207 
0208 
0209 //-----------------------------------------------------------------------------
0210 // Algorithm
0211 private :
0212   /** Main algorithm : must be called after init_all */
0213   void run() ;
0214 
0215 private :
0216   /** tesselates one cube */
0217   void process_cube ()             ;
0218   /** tests if the components of the tesselation of the cube should be connected by the interior of an ambiguous face */
0219   bool test_face    ( int face ) ;
0220   /** tests if the components of the tesselation of the cube should be connected through the interior of the cube */
0221   bool test_interior( int s )    ;
0222 
0223 
0224 //-----------------------------------------------------------------------------
0225 // Operations
0226 private :
0227   /** computes almost all the vertices of the mesh by interpolation along the cubes edges */
0228   void compute_intersection_points() ;
0229 
0230   /**
0231    * routine to add a triangle to the mesh
0232    * \param trig the code for the triangle as a sequence of edges index
0233    * \param n    the number of triangles to produce
0234    * \param v12  the index of the interior vertex to use, if necessary
0235    */
0236   void add_triangle ( const int* trig, char n, int v12 = -1 ) ;
0237 
0238   /** tests and eventually doubles the vertex buffer capacity for a new vertex insertion */
0239   void test_vertex_addition() ;
0240   /** adds a vertex on the current horizontal edge */
0241   int add_x_vertex() ;
0242   /** adds a vertex on the current longitudinal edge */
0243   int add_y_vertex() ;
0244   /** adds a vertex on the current vertical edge */
0245   int add_z_vertex() ;
0246   /** adds a vertex inside the current cube */
0247   int add_c_vertex() ;
0248 
0249   /**
0250    * interpolates the horizontal gradient of the implicit function at the lower vertex of the specified cube
0251    * \param i abscisse of the cube
0252    * \param j ordinate of the cube
0253    * \param k height of the cube
0254    */
0255   double get_x_grad( const int i, const int j, const int k )  ;
0256   /**
0257    * interpolates the longitudinal gradient of the implicit function at the lower vertex of the specified cube
0258    * \param i abscisse of the cube
0259    * \param j ordinate of the cube
0260    * \param k height of the cube
0261    */
0262   double get_y_grad( const int i, const int j, const int k )  ;
0263   /**
0264    * interpolates the vertical gradient of the implicit function at the lower vertex of the specified cube
0265    * \param i abscisse of the cube
0266    * \param j ordinate of the cube
0267    * \param k height of the cube
0268    */
0269   double get_z_grad( const int i, const int j, const int k )  ;
0270 
0271   /**
0272    * accesses the pre-computed vertex index on the lower horizontal edge of a specific cube
0273    * \param i abscisse of the cube
0274    * \param j ordinate of the cube
0275    * \param k height of the cube
0276    */
0277   int   get_x_vert( const int i, const int j, const int k ) const { return i_x_verts[ i + j*i_size_x + k*i_size_x*i_size_y] ; }
0278   /**
0279    * accesses the pre-computed vertex index on the lower longitudinal edge of a specific cube
0280    * \param i abscisse of the cube
0281    * \param j ordinate of the cube
0282    * \param k height of the cube
0283    */
0284   int   get_y_vert( const int i, const int j, const int k ) const { return i_y_verts[ i + j*i_size_x + k*i_size_x*i_size_y] ; }
0285   /**
0286    * accesses the pre-computed vertex index on the lower vertical edge of a specific cube
0287    * \param i abscisse of the cube
0288    * \param j ordinate of the cube
0289    * \param k height of the cube
0290    */
0291   int   get_z_vert( const int i, const int j, const int k ) const { return i_z_verts[ i + j*i_size_x + k*i_size_x*i_size_y] ; }
0292 
0293   /**
0294    * sets the pre-computed vertex index on the lower horizontal edge of a specific cube
0295    * \param val the index of the new vertex
0296    * \param i abscisse of the cube
0297    * \param j ordinate of the cube
0298    * \param k height of the cube
0299    */
0300   void  set_x_vert( const int val, const int i, const int j, const int k ) { i_x_verts[ i + j*i_size_x + k*i_size_x*i_size_y] = val ; }
0301   /**
0302    * sets the pre-computed vertex index on the lower longitudinal edge of a specific cube
0303    * \param val the index of the new vertex
0304    * \param i abscisse of the cube
0305    * \param j ordinate of the cube
0306    * \param k height of the cube
0307    */
0308   void  set_y_vert( const int val, const int i, const int j, const int k ) { i_y_verts[ i + j*i_size_x + k*i_size_x*i_size_y] = val ; }
0309   /**
0310    * sets the pre-computed vertex index on the lower vertical edge of a specific cube
0311    * \param val the index of the new vertex
0312    * \param i abscisse of the cube
0313    * \param j ordinate of the cube
0314    * \param k height of the cube
0315    */
0316   void  set_z_vert( const int val, const int i, const int j, const int k ) { i_z_verts[ i + j*i_size_x + k*i_size_x*i_size_y] = val ; }
0317 
0318   /** prints cube for debug */
0319   void print_cube() ;
0320 
0321 //-----------------------------------------------------------------------------
0322 // Elements
0323 private :
0324   int       i_originalMC ;   /**< selects whether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes */
0325   int       i_N[15]      ;   /**< counts the occurrence of each case for debug */
0326 
0327   int       i_size_x     ;  /**< width  of the grid */
0328   int       i_size_y     ;  /**< depth  of the grid */
0329   int       i_size_z     ;  /**< height of the grid */
0330   double    *i_data       ;  /**< implicit function values sampled on the grid */
0331 
0332   //BEGIN percy addons
0333   double xmin;
0334   double xmax;
0335   double ymin;
0336   double ymax;
0337   double zmin;
0338   double zmax;
0339   double hx;
0340   double hy;
0341   double hz;
0342   //END
0343 
0344   int      *i_x_verts    ;  /**< pre-computed vertex indices on the lower horizontal   edge of each cube */
0345   int      *i_y_verts    ;  /**< pre-computed vertex indices on the lower longitudinal edge of each cube */
0346   int      *i_z_verts    ;  /**< pre-computed vertex indices on the lower vertical     edge of each cube */
0347 
0348   int       i_nverts     ;  /**< number of allocated vertices  in the vertex   buffer */
0349   int       i_ntrigs     ;  /**< number of allocated triangles in the triangle buffer */
0350   int       i_Nverts     ;  /**< size of the vertex   buffer */
0351   int       i_Ntrigs     ;  /**< size of the triangle buffer */
0352   Vertex     *i_vertices   ;  /**< vertex   buffer */
0353   Triangle   *i_triangles  ;  /**< triangle buffer */
0354 
0355   int       i_i          ;  /**< abscisse of the active cube */
0356   int       i_j          ;  /**< height of the active cube */
0357   int       i_k          ;  /**< ordinate of the active cube */
0358 
0359   double     i_cube[8]    ;  /**< values of the implicit function on the active cube */
0360   unsigned char     i_lut_entry  ;  /**< cube sign representation in [0..255] */
0361   unsigned char     i_case       ;  /**< case of the active cube in [0..15] */
0362   unsigned char     i_config     ;  /**< configuration of the active cube */
0363   unsigned char     i_subconfig  ;  /**< subconfiguration of the active cube */
0364 };
0365 //_____________________________________________________________________________
0366 
0367 
0368 
0369 
0370 #endif