OpenWalnut 1.2.5

WMarchingLegoAlgorithm.h

00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WMARCHINGLEGOALGORITHM_H
00026 #define WMARCHINGLEGOALGORITHM_H
00027 
00028 #include <vector>
00029 #include <map>
00030 #include "../../common/math/WMatrix.h"
00031 #include "../../common/WProgressCombiner.h"
00032 #include "../WTriangleMesh.h"
00033 #include "../WExportWGE.h"
00034 
00035 /**
00036  * A point consisting of its coordinates and ID
00037  */
00038 struct WMLPointXYZId
00039 {
00040     unsigned int newID; //!< ID of the point
00041     double x; //!< x coordinates of the point.
00042     double y; //!< y coordinates of the point.
00043     double z; //!< z coordinates of the point.
00044 };
00045 
00046 typedef std::map< unsigned int, WMLPointXYZId > ID2WMLPointXYZId;
00047 
00048 /**
00049  * Encapsulated ids representing a triangle.
00050  */
00051 struct WMLTriangle
00052 {
00053     unsigned int pointID[3]; //!< The IDs of the vertices of the triangle.
00054 };
00055 
00056 typedef std::vector<WMLTriangle> WMLTriangleVECTOR;
00057 
00058 
00059 /**
00060  * Creates a non interpolated triangulation of an isosurface
00061  */
00062 class WGE_EXPORT WMarchingLegoAlgorithm
00063 {
00064 public:
00065     /**
00066      * standard constructor
00067      */
00068     WMarchingLegoAlgorithm();
00069 
00070     /**
00071      * destructor
00072      */
00073     ~WMarchingLegoAlgorithm();
00074 
00075     /**
00076      * Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
00077      * the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
00078      * This might be useful where texture transformation matrices are used.
00079      *
00080      * \param nbCoordsX number of vertices in X direction
00081      * \param nbCoordsY number of vertices in Y direction
00082      * \param nbCoordsZ number of vertices in Z direction
00083      * \param mat the matrix transforming the vertices from canonical space
00084      * \param vals the values at the vertices
00085      * \param isoValue The surface will run through all positions with this value.
00086      *
00087      * \return the created triangle mesh
00088      */
00089     template< typename T >
00090     boost::shared_ptr< WTriangleMesh > generateSurface(  size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
00091                                                           const WMatrix< double >& mat,
00092                                                           const std::vector< T >* vals,
00093                                                           double isoValue );
00094 
00095     /**
00096      * Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
00097      * the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
00098      * This might be useful where texture transformation matrices are used.
00099      *
00100      * \param nbCoordsX number of vertices in X direction
00101      * \param nbCoordsY number of vertices in Y direction
00102      * \param nbCoordsZ number of vertices in Z direction
00103      * \param mat the matrix transforming the vertices from canonical space
00104      * \param vals the values at the vertices
00105      * \param isoValue The surface will run through all positions with this value.
00106      *
00107      * \return the created triangle mesh
00108      */
00109     boost::shared_ptr< WTriangleMesh > genSurfaceOneValue(  size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
00110                                                               const WMatrix< double >& mat,
00111                                                               const std::vector< size_t >* vals,
00112                                                               size_t isoValue );
00113 
00114 protected:
00115 private:
00116     /**
00117      * adds 2 triangles for a given face of the voxel
00118      * \param x position of the voxel
00119      * \param y position of the voxel
00120      * \param z position of the voxel
00121      * \param surface which side of the voxel to paint
00122      */
00123     void addSurface( size_t x, size_t y, size_t z, size_t surface );
00124 
00125     /**
00126      * returns a vertex id for a given grid point
00127      * \param nX x position in space
00128      * \param nY y position in space
00129      * \param nZ z position in space
00130      * \return the id
00131      */
00132     size_t getVertexID( size_t nX, size_t nY, size_t nZ );
00133 
00134     unsigned int m_nCellsX;  //!< No. of cells in x direction.
00135     unsigned int m_nCellsY;  //!< No. of cells in y direction.
00136     unsigned int m_nCellsZ;  //!< No. of cells in z direction.
00137 
00138     double m_tIsoLevel;  //!< The isovalue.
00139 
00140     WMatrix< double > m_matrix; //!< The 4x4 transformation matrix for the triangle vertices.
00141 
00142     ID2WMLPointXYZId m_idToVertices;  //!< List of WPointXYZIds which form the isosurface.
00143     WMLTriangleVECTOR m_trivecTriangles;  //!< List of WMCTriangleS which form the triangulation of the isosurface.
00144 };
00145 
00146 template<typename T> boost::shared_ptr<WTriangleMesh> WMarchingLegoAlgorithm::generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
00147                                                                                                  const WMatrix< double >& mat,
00148                                                                                                  const std::vector< T >* vals,
00149                                                                                                  double isoValue )
00150 {
00151     WAssert( vals, "No value set provided." );
00152 
00153     m_idToVertices.clear();
00154     m_trivecTriangles.clear();
00155 
00156     m_nCellsX = nbCoordsX - 1;
00157     m_nCellsY = nbCoordsY - 1;
00158     m_nCellsZ = nbCoordsZ - 1;
00159 
00160     m_matrix = mat;
00161 
00162     m_tIsoLevel = isoValue;
00163 
00164     size_t nX = nbCoordsX;
00165     size_t nY = nbCoordsY;
00166 
00167     size_t nPointsInSlice = nX * nY;
00168 
00169     // Generate isosurface.
00170     for( size_t z = 0; z < m_nCellsZ; z++ )
00171     {
00172         for( size_t y = 0; y < m_nCellsY; y++ )
00173         {
00174             for( size_t x = 0; x < m_nCellsX; x++ )
00175             {
00176                 if( ( *vals )[ z * nPointsInSlice + y * nX + x ] < m_tIsoLevel )
00177                 {
00178                     continue;
00179                 }
00180 
00181                 if( x > 0 && ( ( *vals )[ z * nPointsInSlice + y * nX + x - 1 ] < m_tIsoLevel ) )
00182                 {
00183                     addSurface( x, y, z, 1 );
00184                 }
00185                 if( x < m_nCellsX - 1 && ( ( *vals )[ z * nPointsInSlice + y * nX + x + 1 ] < m_tIsoLevel ) )
00186                 {
00187                     addSurface( x, y, z, 2 );
00188                 }
00189 
00190                 if( y > 0 && ( ( *vals )[ z * nPointsInSlice + ( y - 1 ) * nX + x ] < m_tIsoLevel ) )
00191                 {
00192                     addSurface( x, y, z, 3 );
00193                 }
00194 
00195                 if( y < m_nCellsY - 1 && ( ( *vals )[ z * nPointsInSlice + ( y + 1 ) * nX + x ] < m_tIsoLevel ) )
00196                 {
00197                     addSurface( x, y, z, 4 );
00198                 }
00199 
00200                 if( z > 0 && ( ( *vals )[ ( z - 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
00201                 {
00202                     addSurface( x, y, z, 5 );
00203                 }
00204 
00205                 if( z < m_nCellsZ - 1 && ( ( *vals )[ ( z + 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
00206                 {
00207                     addSurface( x, y, z, 6 );
00208                 }
00209 
00210                 if( x == 0 )
00211                 {
00212                     addSurface( x, y, z, 1 );
00213                 }
00214                 if( x == m_nCellsX - 1 )
00215                 {
00216                     addSurface( x, y, z, 2 );
00217                 }
00218 
00219                 if( y == 0 )
00220                 {
00221                     addSurface( x, y, z, 3 );
00222                 }
00223 
00224                 if( y == m_nCellsY - 1 )
00225                 {
00226                     addSurface( x, y, z, 4 );
00227                 }
00228 
00229                 if( z == 0 )
00230                 {
00231                     addSurface( x, y, z, 5 );
00232                 }
00233 
00234                 if( z == m_nCellsZ - 1 )
00235                 {
00236                     addSurface( x, y, z, 6 );
00237                 }
00238             }
00239         }
00240     }
00241     unsigned int nextID = 0;
00242     boost::shared_ptr< WTriangleMesh > triMesh( new WTriangleMesh( m_idToVertices.size(), m_trivecTriangles.size() ) );
00243 
00244     // Rename vertices.
00245     ID2WMLPointXYZId::iterator mapIterator = m_idToVertices.begin();
00246     while( mapIterator != m_idToVertices.end() )
00247     {
00248         WPosition texCoord = WPosition( mapIterator->second.x / nbCoordsX,
00249                                                       mapIterator->second.y / nbCoordsY,
00250                                                       mapIterator->second.z / nbCoordsZ );
00251 
00252         // transform from grid coordinate system to world coordinates
00253         WPosition pos = WPosition( mapIterator->second.x, mapIterator->second.y, mapIterator->second.z );
00254 
00255         std::vector< double > resultPos4D( 4 );
00256         resultPos4D[0] = m_matrix( 0, 0 ) * pos[0] + m_matrix( 0, 1 ) * pos[1] + m_matrix( 0, 2 ) * pos[2] + m_matrix( 0, 3 ) * 1;
00257         resultPos4D[1] = m_matrix( 1, 0 ) * pos[0] + m_matrix( 1, 1 ) * pos[1] + m_matrix( 1, 2 ) * pos[2] + m_matrix( 1, 3 ) * 1;
00258         resultPos4D[2] = m_matrix( 2, 0 ) * pos[0] + m_matrix( 2, 1 ) * pos[1] + m_matrix( 2, 2 ) * pos[2] + m_matrix( 2, 3 ) * 1;
00259         resultPos4D[3] = m_matrix( 3, 0 ) * pos[0] + m_matrix( 3, 1 ) * pos[1] + m_matrix( 3, 2 ) * pos[2] + m_matrix( 3, 3 ) * 1;
00260 
00261         ( *mapIterator ).second.newID = nextID;
00262         triMesh->addVertex( resultPos4D[0] / resultPos4D[3],
00263                             resultPos4D[1] / resultPos4D[3],
00264                             resultPos4D[2] / resultPos4D[3] );
00265         triMesh->addTextureCoordinate( texCoord );
00266         nextID++;
00267         mapIterator++;
00268     }
00269 
00270     // Now rename triangles.
00271     WMLTriangleVECTOR::iterator vecIterator = m_trivecTriangles.begin();
00272     while( vecIterator != m_trivecTriangles.end() )
00273     {
00274         for( unsigned int i = 0; i < 3; i++ )
00275         {
00276             unsigned int newID = m_idToVertices[( *vecIterator ).pointID[i]].newID;
00277             ( *vecIterator ).pointID[i] = newID;
00278         }
00279         triMesh->addTriangle( ( *vecIterator ).pointID[0], ( *vecIterator ).pointID[1], ( *vecIterator ).pointID[2] );
00280         vecIterator++;
00281     }
00282     return triMesh;
00283 }
00284 #endif  // WMARCHINGLEGOALGORITHM_H
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends