OpenWalnut
1.2.5
|
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