OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WMarchingLegoAlgorithm.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WMARCHINGLEGOALGORITHM_H
26 #define WMARCHINGLEGOALGORITHM_H
27 
28 #include <vector>
29 #include <map>
30 #include "../../common/math/WMatrix.h"
31 #include "../../common/WProgressCombiner.h"
32 #include "../WTriangleMesh.h"
33 #include "../WExportWGE.h"
34 
35 /**
36  * A point consisting of its coordinates and ID
37  */
39 {
40  unsigned int newID; //!< ID of the point
41  double x; //!< x coordinates of the point.
42  double y; //!< y coordinates of the point.
43  double z; //!< z coordinates of the point.
44 };
45 
46 typedef std::map< unsigned int, WMLPointXYZId > ID2WMLPointXYZId;
47 
48 /**
49  * Encapsulated ids representing a triangle.
50  */
52 {
53  unsigned int pointID[3]; //!< The IDs of the vertices of the triangle.
54 };
55 
56 typedef std::vector<WMLTriangle> WMLTriangleVECTOR;
57 
58 
59 /**
60  * Creates a non interpolated triangulation of an isosurface
61  */
62 class WGE_EXPORT WMarchingLegoAlgorithm
63 {
64 public:
65  /**
66  * standard constructor
67  */
69 
70  /**
71  * destructor
72  */
74 
75  /**
76  * Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
77  * the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
78  * This might be useful where texture transformation matrices are used.
79  *
80  * \param nbCoordsX number of vertices in X direction
81  * \param nbCoordsY number of vertices in Y direction
82  * \param nbCoordsZ number of vertices in Z direction
83  * \param mat the matrix transforming the vertices from canonical space
84  * \param vals the values at the vertices
85  * \param isoValue The surface will run through all positions with this value.
86  *
87  * \return the created triangle mesh
88  */
89  template< typename T >
90  boost::shared_ptr< WTriangleMesh > generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
91  const WMatrix< double >& mat,
92  const std::vector< T >* vals,
93  double isoValue );
94 
95  /**
96  * Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
97  * the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
98  * This might be useful where texture transformation matrices are used.
99  *
100  * \param nbCoordsX number of vertices in X direction
101  * \param nbCoordsY number of vertices in Y direction
102  * \param nbCoordsZ number of vertices in Z direction
103  * \param mat the matrix transforming the vertices from canonical space
104  * \param vals the values at the vertices
105  * \param isoValue The surface will run through all positions with this value.
106  *
107  * \return the created triangle mesh
108  */
109  boost::shared_ptr< WTriangleMesh > genSurfaceOneValue( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
110  const WMatrix< double >& mat,
111  const std::vector< size_t >* vals,
112  size_t isoValue );
113 
114 protected:
115 private:
116  /**
117  * adds 2 triangles for a given face of the voxel
118  * \param x position of the voxel
119  * \param y position of the voxel
120  * \param z position of the voxel
121  * \param surface which side of the voxel to paint
122  */
123  void addSurface( size_t x, size_t y, size_t z, size_t surface );
124 
125  /**
126  * returns a vertex id for a given grid point
127  * \param nX x position in space
128  * \param nY y position in space
129  * \param nZ z position in space
130  * \return the id
131  */
132  size_t getVertexID( size_t nX, size_t nY, size_t nZ );
133 
134  unsigned int m_nCellsX; //!< No. of cells in x direction.
135  unsigned int m_nCellsY; //!< No. of cells in y direction.
136  unsigned int m_nCellsZ; //!< No. of cells in z direction.
137 
138  double m_tIsoLevel; //!< The isovalue.
139 
140  WMatrix< double > m_matrix; //!< The 4x4 transformation matrix for the triangle vertices.
141 
142  ID2WMLPointXYZId m_idToVertices; //!< List of WPointXYZIds which form the isosurface.
143  WMLTriangleVECTOR m_trivecTriangles; //!< List of WMCTriangleS which form the triangulation of the isosurface.
144 };
145 
146 template<typename T> boost::shared_ptr<WTriangleMesh> WMarchingLegoAlgorithm::generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
147  const WMatrix< double >& mat,
148  const std::vector< T >* vals,
149  double isoValue )
150 {
151  WAssert( vals, "No value set provided." );
152 
153  m_idToVertices.clear();
154  m_trivecTriangles.clear();
155 
156  m_nCellsX = nbCoordsX - 1;
157  m_nCellsY = nbCoordsY - 1;
158  m_nCellsZ = nbCoordsZ - 1;
159 
160  m_matrix = mat;
161 
162  m_tIsoLevel = isoValue;
163 
164  size_t nX = nbCoordsX;
165  size_t nY = nbCoordsY;
166 
167  size_t nPointsInSlice = nX * nY;
168 
169  // Generate isosurface.
170  for( size_t z = 0; z < m_nCellsZ; z++ )
171  {
172  for( size_t y = 0; y < m_nCellsY; y++ )
173  {
174  for( size_t x = 0; x < m_nCellsX; x++ )
175  {
176  if( ( *vals )[ z * nPointsInSlice + y * nX + x ] < m_tIsoLevel )
177  {
178  continue;
179  }
180 
181  if( x > 0 && ( ( *vals )[ z * nPointsInSlice + y * nX + x - 1 ] < m_tIsoLevel ) )
182  {
183  addSurface( x, y, z, 1 );
184  }
185  if( x < m_nCellsX - 1 && ( ( *vals )[ z * nPointsInSlice + y * nX + x + 1 ] < m_tIsoLevel ) )
186  {
187  addSurface( x, y, z, 2 );
188  }
189 
190  if( y > 0 && ( ( *vals )[ z * nPointsInSlice + ( y - 1 ) * nX + x ] < m_tIsoLevel ) )
191  {
192  addSurface( x, y, z, 3 );
193  }
194 
195  if( y < m_nCellsY - 1 && ( ( *vals )[ z * nPointsInSlice + ( y + 1 ) * nX + x ] < m_tIsoLevel ) )
196  {
197  addSurface( x, y, z, 4 );
198  }
199 
200  if( z > 0 && ( ( *vals )[ ( z - 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
201  {
202  addSurface( x, y, z, 5 );
203  }
204 
205  if( z < m_nCellsZ - 1 && ( ( *vals )[ ( z + 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
206  {
207  addSurface( x, y, z, 6 );
208  }
209 
210  if( x == 0 )
211  {
212  addSurface( x, y, z, 1 );
213  }
214  if( x == m_nCellsX - 1 )
215  {
216  addSurface( x, y, z, 2 );
217  }
218 
219  if( y == 0 )
220  {
221  addSurface( x, y, z, 3 );
222  }
223 
224  if( y == m_nCellsY - 1 )
225  {
226  addSurface( x, y, z, 4 );
227  }
228 
229  if( z == 0 )
230  {
231  addSurface( x, y, z, 5 );
232  }
233 
234  if( z == m_nCellsZ - 1 )
235  {
236  addSurface( x, y, z, 6 );
237  }
238  }
239  }
240  }
241  unsigned int nextID = 0;
242  boost::shared_ptr< WTriangleMesh > triMesh( new WTriangleMesh( m_idToVertices.size(), m_trivecTriangles.size() ) );
243 
244  // Rename vertices.
245  ID2WMLPointXYZId::iterator mapIterator = m_idToVertices.begin();
246  while( mapIterator != m_idToVertices.end() )
247  {
248  WPosition texCoord = WPosition( mapIterator->second.x / nbCoordsX,
249  mapIterator->second.y / nbCoordsY,
250  mapIterator->second.z / nbCoordsZ );
251 
252  // transform from grid coordinate system to world coordinates
253  WPosition pos = WPosition( mapIterator->second.x, mapIterator->second.y, mapIterator->second.z );
254 
255  std::vector< double > resultPos4D( 4 );
256  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;
257  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;
258  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;
259  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;
260 
261  ( *mapIterator ).second.newID = nextID;
262  triMesh->addVertex( resultPos4D[0] / resultPos4D[3],
263  resultPos4D[1] / resultPos4D[3],
264  resultPos4D[2] / resultPos4D[3] );
265  triMesh->addTextureCoordinate( texCoord );
266  nextID++;
267  mapIterator++;
268  }
269 
270  // Now rename triangles.
271  WMLTriangleVECTOR::iterator vecIterator = m_trivecTriangles.begin();
272  while( vecIterator != m_trivecTriangles.end() )
273  {
274  for( unsigned int i = 0; i < 3; i++ )
275  {
276  unsigned int newID = m_idToVertices[( *vecIterator ).pointID[i]].newID;
277  ( *vecIterator ).pointID[i] = newID;
278  }
279  triMesh->addTriangle( ( *vecIterator ).pointID[0], ( *vecIterator ).pointID[1], ( *vecIterator ).pointID[2] );
280  vecIterator++;
281  }
282  return triMesh;
283 }
284 #endif // WMARCHINGLEGOALGORITHM_H