OpenWalnut  1.5.0dev
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 <map>
29 #include <memory>
30 #include <vector>
31 
32 #include "../WProgressCombiner.h"
33 #include "../math/WMatrix.h"
34 #include "core/graphicsEngine/WTriangleMesh.h"
35 
36 /**
37  * A point consisting of its coordinates and ID
38  */
40 {
41  unsigned int newID; //!< ID of the point
42  double x; //!< x coordinates of the point.
43  double y; //!< y coordinates of the point.
44  double z; //!< z coordinates of the point.
45 };
46 
47 typedef std::map< unsigned int, WMLPointXYZId > ID2WMLPointXYZId;
48 
49 /**
50  * Encapsulated ids representing a triangle.
51  */
53 {
54  unsigned int pointID[3]; //!< The IDs of the vertices of the triangle.
55 };
56 
57 typedef std::vector<WMLTriangle> WMLTriangleVECTOR;
58 
59 
60 /**
61  * Creates a non interpolated triangulation of an isosurface
62  */
64 {
65 public:
66  /**
67  * standard constructor
68  */
70 
71  /**
72  * destructor
73  */
75 
76  /**
77  * Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
78  * the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
79  * This might be useful where texture transformation matrices are used.
80  *
81  * \param nbCoordsX number of vertices in X direction
82  * \param nbCoordsY number of vertices in Y direction
83  * \param nbCoordsZ number of vertices in Z direction
84  * \param mat the matrix transforming the vertices from canonical space
85  * \param vals the values at the vertices
86  * \param isoValue The surface will run through all positions with this value.
87  * \param mainProgress Pointer to the parent's progress reporter. Leave empty if no progress should be shown
88  *
89  * \return the created triangle mesh
90  */
91  template< typename T >
92  std::shared_ptr< WTriangleMesh > generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
93  const WMatrix< double >& mat,
94  const std::vector< T >* vals,
95  double isoValue,
96  std::shared_ptr<WProgressCombiner> mainProgress
97  = std::shared_ptr < WProgressCombiner >() );
98 
99  /**
100  * Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
101  * the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
102  * This might be useful where texture transformation matrices are used.
103  *
104  * \param nbCoordsX number of vertices in X direction
105  * \param nbCoordsY number of vertices in Y direction
106  * \param nbCoordsZ number of vertices in Z direction
107  * \param mat the matrix transforming the vertices from canonical space
108  * \param vals the values at the vertices
109  * \param isoValue The surface will run through all positions with this value.
110  * \param progress parent's WProgressCombiner. May be empty if no status report is requested
111  *
112  * \return the created triangle mesh
113  */
114  std::shared_ptr< WTriangleMesh > genSurfaceOneValue( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
115  const WMatrix< double >& mat,
116  const std::vector< size_t >* vals,
117  size_t isoValue,
118  std::shared_ptr<WProgressCombiner> progress
119  = std::shared_ptr < WProgressCombiner >() );
120 
121 protected:
122 private:
123  /**
124  * adds 2 triangles for a given face of the voxel
125  * \param x position of the voxel
126  * \param y position of the voxel
127  * \param z position of the voxel
128  * \param surface which side of the voxel to paint
129  */
130  void addSurface( size_t x, size_t y, size_t z, size_t surface );
131 
132  /**
133  * returns a vertex id for a given grid point
134  * \param nX x position in space
135  * \param nY y position in space
136  * \param nZ z position in space
137  * \return the id
138  */
139  size_t getVertexID( size_t nX, size_t nY, size_t nZ );
140 
141  unsigned int m_nCellsX; //!< No. of cells in x direction.
142  unsigned int m_nCellsY; //!< No. of cells in y direction.
143  unsigned int m_nCellsZ; //!< No. of cells in z direction.
144 
145  double m_tIsoLevel; //!< The isovalue.
146 
147  WMatrix< double > m_matrix; //!< The 4x4 transformation matrix for the triangle vertices.
148 
149  ID2WMLPointXYZId m_idToVertices; //!< List of WPointXYZIds which form the isosurface.
150  WMLTriangleVECTOR m_trivecTriangles; //!< List of WMCTriangleS which form the triangulation of the isosurface.
151 };
152 
153 template<typename T> std::shared_ptr<WTriangleMesh>
154 WMarchingLegoAlgorithm::generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
155  const WMatrix< double >& mat,
156  const std::vector< T >* vals,
157  double isoValue,
158  std::shared_ptr<WProgressCombiner> mainProgress )
159 {
160  WAssert( vals, "No value set provided." );
161 
162  m_idToVertices.clear();
163  m_trivecTriangles.clear();
164 
165  m_nCellsX = nbCoordsX - 1;
166  m_nCellsY = nbCoordsY - 1;
167  m_nCellsZ = nbCoordsZ - 1;
168 
169  m_matrix = mat;
170 
171  m_tIsoLevel = isoValue;
172 
173  size_t nX = nbCoordsX;
174  size_t nY = nbCoordsY;
175 
176  size_t nPointsInSlice = nX * nY;
177 
178  std::shared_ptr< WProgress > progress;
179  if( mainProgress )
180  {
181  progress = std::shared_ptr< WProgress >( new WProgress( "Marching Cubes", m_nCellsZ ) );
182  mainProgress->addSubProgress( progress );
183  }
184 
185  // Generate isosurface.
186  for( size_t z = 0; z < m_nCellsZ; z++ )
187  {
188  if( progress )
189  {
190  ++*progress;
191  }
192  for( size_t y = 0; y < m_nCellsY; y++ )
193  {
194  for( size_t x = 0; x < m_nCellsX; x++ )
195  {
196  if( ( *vals )[ z * nPointsInSlice + y * nX + x ] < m_tIsoLevel )
197  {
198  continue;
199  }
200 
201  if( x > 0 && ( ( *vals )[ z * nPointsInSlice + y * nX + x - 1 ] < m_tIsoLevel ) )
202  {
203  addSurface( x, y, z, 1 );
204  }
205  if( x < m_nCellsX - 1 && ( ( *vals )[ z * nPointsInSlice + y * nX + x + 1 ] < m_tIsoLevel ) )
206  {
207  addSurface( x, y, z, 2 );
208  }
209 
210  if( y > 0 && ( ( *vals )[ z * nPointsInSlice + ( y - 1 ) * nX + x ] < m_tIsoLevel ) )
211  {
212  addSurface( x, y, z, 3 );
213  }
214 
215  if( y < m_nCellsY - 1 && ( ( *vals )[ z * nPointsInSlice + ( y + 1 ) * nX + x ] < m_tIsoLevel ) )
216  {
217  addSurface( x, y, z, 4 );
218  }
219 
220  if( z > 0 && ( ( *vals )[ ( z - 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
221  {
222  addSurface( x, y, z, 5 );
223  }
224 
225  if( z < m_nCellsZ - 1 && ( ( *vals )[ ( z + 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
226  {
227  addSurface( x, y, z, 6 );
228  }
229 
230  if( x == 0 )
231  {
232  addSurface( x, y, z, 1 );
233  }
234  if( x == m_nCellsX - 1 )
235  {
236  addSurface( x, y, z, 2 );
237  }
238 
239  if( y == 0 )
240  {
241  addSurface( x, y, z, 3 );
242  }
243 
244  if( y == m_nCellsY - 1 )
245  {
246  addSurface( x, y, z, 4 );
247  }
248 
249  if( z == 0 )
250  {
251  addSurface( x, y, z, 5 );
252  }
253 
254  if( z == m_nCellsZ - 1 )
255  {
256  addSurface( x, y, z, 6 );
257  }
258  }
259  }
260  }
261  unsigned int nextID = 0;
262  std::shared_ptr< WTriangleMesh > triMesh( new WTriangleMesh( m_idToVertices.size(), m_trivecTriangles.size() ) );
263 
264  // Rename vertices.
265  ID2WMLPointXYZId::iterator mapIterator = m_idToVertices.begin();
266  while( mapIterator != m_idToVertices.end() )
267  {
268  WPosition texCoord = WPosition( mapIterator->second.x / nbCoordsX,
269  mapIterator->second.y / nbCoordsY,
270  mapIterator->second.z / nbCoordsZ );
271 
272  // transform from grid coordinate system to world coordinates
273  WPosition pos = WPosition( mapIterator->second.x, mapIterator->second.y, mapIterator->second.z );
274 
275  std::vector< double > resultPos4D( 4 );
276  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;
277  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;
278  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;
279  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;
280 
281  ( *mapIterator ).second.newID = nextID;
282  triMesh->addVertex( resultPos4D[0] / resultPos4D[3],
283  resultPos4D[1] / resultPos4D[3],
284  resultPos4D[2] / resultPos4D[3] );
285  triMesh->addTextureCoordinate( texCoord );
286  nextID++;
287  mapIterator++;
288  }
289 
290  // Now rename triangles.
291  WMLTriangleVECTOR::iterator vecIterator = m_trivecTriangles.begin();
292  while( vecIterator != m_trivecTriangles.end() )
293  {
294  for( unsigned int i = 0; i < 3; i++ )
295  {
296  unsigned int newID = m_idToVertices[( *vecIterator ).pointID[i]].newID;
297  ( *vecIterator ).pointID[i] = newID;
298  }
299  triMesh->addTriangle( ( *vecIterator ).pointID[0], ( *vecIterator ).pointID[1], ( *vecIterator ).pointID[2] );
300  vecIterator++;
301  }
302  if( progress )
303  {
304  progress->finish();
305  }
306  return triMesh;
307 }
308 #endif // WMARCHINGLEGOALGORITHM_H
Creates a non interpolated triangulation of an isosurface.
ID2WMLPointXYZId m_idToVertices
List of WPointXYZIds which form the isosurface.
WMarchingLegoAlgorithm()
standard constructor
WMatrix< double > m_matrix
The 4x4 transformation matrix for the triangle vertices.
unsigned int m_nCellsX
No. of cells in x direction.
std::shared_ptr< WTriangleMesh > genSurfaceOneValue(size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ, const WMatrix< double > &mat, const std::vector< size_t > *vals, size_t isoValue, std::shared_ptr< WProgressCombiner > progress=std::shared_ptr< WProgressCombiner >())
Generate the triangles for the surface on the given dataSet (inGrid, vals).
size_t getVertexID(size_t nX, size_t nY, size_t nZ)
returns a vertex id for a given grid point
std::shared_ptr< WTriangleMesh > generateSurface(size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ, const WMatrix< double > &mat, const std::vector< T > *vals, double isoValue, std::shared_ptr< WProgressCombiner > mainProgress=std::shared_ptr< WProgressCombiner >())
Generate the triangles for the surface on the given dataSet (inGrid, vals).
unsigned int m_nCellsZ
No. of cells in z direction.
double m_tIsoLevel
The isovalue.
WMLTriangleVECTOR m_trivecTriangles
List of WMCTriangleS which form the triangulation of the isosurface.
void addSurface(size_t x, size_t y, size_t z, size_t surface)
adds 2 triangles for a given face of the voxel
unsigned int m_nCellsY
No. of cells in y direction.
This only is a 3d double vector.
Class managing progress inside of modules.
Definition: WProgress.h:42
Triangle mesh data structure allowing for convenient access of the elements.
Definition: WTriangleMesh.h:46
A point consisting of its coordinates and ID.
double x
x coordinates of the point.
double y
y coordinates of the point.
double z
z coordinates of the point.
unsigned int newID
ID of the point.
Encapsulated ids representing a triangle.
unsigned int pointID[3]
The IDs of the vertices of the triangle.