OpenWalnut  1.3.1
WTriangleMesh_test.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 WTRIANGLEMESH_TEST_H
26 #define WTRIANGLEMESH_TEST_H
27 
28 #include <algorithm>
29 #include <list>
30 #include <vector>
31 
32 #include <cxxtest/TestSuite.h>
33 
34 #include "../../common/math/linearAlgebra/WLinearAlgebra.h"
35 #include "../WTriangleMesh.h"
36 #include "WTriangleMeshTraits.h"
37 
38 /**
39  * Testing the WTriangleMesh class.
40  */
41 class WTriangleMeshTest : public CxxTest::TestSuite
42 {
43 public:
44 // TODO(schurade): fix unit test from old triangle class
45 // /**
46 // * Ensure instatiation does not throw and does initialization right.
47 // */
48 // void testInstatiation()
49 // {
50 // TS_ASSERT_THROWS_NOTHING( WTriangleMesh() );
51 // WTriangleMesh mesh;
52 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 );
53 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 );
54 // }
55 //
56 // /**
57 // * clearMesh should reset all members.
58 // */
59 // void testClearMesh()
60 // {
61 // WTriangleMesh mesh;
62 // mesh.m_fastAddVertId = 9; // just a number
63 // mesh.m_fastAddTriangleId = 10; // just a number
64 // mesh.m_vertices.resize( 11 ); // just some size
65 // mesh.m_triangles.resize( 13 ); // just some size
66 //
67 // mesh.clearMesh();
68 //
69 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 );
70 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 );
71 // TS_ASSERT_EQUALS( mesh.m_vertices.size(), 0 );
72 // TS_ASSERT_EQUALS( mesh.m_triangles.size(), 0 );
73 // }
74 //
75 // /**
76 // * fastAddVert should increment the corresponding counter
77 // */
78 // void testFastAddVert()
79 // {
80 // WTriangleMesh mesh;
81 // mesh.resizeVertices( 2 );
82 // WPosition newVert;
83 //
84 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 );
85 // mesh.fastAddVert( newVert );
86 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 1 );
87 // mesh.fastAddVert( newVert );
88 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 2 );
89 // }
90 //
91 // /**
92 // * fastAddTriangle should increment the corresponding counter
93 // */
94 // void testFastAddTriangle()
95 // {
96 // WTriangleMesh mesh;
97 // mesh.resizeTriangles( 2 );
98 //
99 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 );
100 // mesh.fastAddTriangle( 0, 1, 2 );
101 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 1 );
102 // mesh.fastAddTriangle( 1, 2, 3 );
103 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 2 );
104 // }
105 //
106 // /**
107 // * setVertices should set the fastAddId and resize the member
108 // */
109 // void testSetVertices()
110 // {
111 // WTriangleMesh mesh;
112 // std::vector< WPosition > vertices( 4 );
113 //
114 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 );
115 // TS_ASSERT_EQUALS( mesh.m_vertices.size(), 0 );
116 // mesh.setVertices( vertices );
117 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 4 );
118 // TS_ASSERT_EQUALS( mesh.m_vertices.size(), 4 );
119 // }
120 //
121 // /**
122 // * setTriangles should set the fastAddId and resize the member
123 // */
124 // void testSetTriangles()
125 // {
126 // WTriangleMesh mesh;
127 // std::vector< Triangle > triangles( 5 );
128 //
129 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 );
130 // TS_ASSERT_EQUALS( mesh.m_triangles.size(), 0 );
131 // mesh.setTriangles( triangles );
132 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 5 );
133 // TS_ASSERT_EQUALS( mesh.m_triangles.size(), 5 );
134 // }
135 //
136 // /**
137 // * Test getTriangleNormal
138 // */
139 // void testgetTriangleNormal()
140 // {
141 // WTriangleMesh mesh;
142 //
143 // mesh.resizeVertices( 5 );
144 // WPosition newVert0( 0, 0, 0 );
145 // mesh.fastAddVert( newVert0 );
146 //
147 // WPosition newVert1( 1.3, 2.25, 3.435 );
148 // mesh.fastAddVert( newVert1 );
149 //
150 // WPosition newVert2( 1, 2, 3 );
151 // mesh.fastAddVert( newVert2 );
152 //
153 // WPosition newVert3( 1.2, 1.5, 1.7 );
154 // mesh.fastAddVert( newVert3 );
155 //
156 // WPosition newVert4( 1, 1, 1 );
157 // mesh.fastAddVert( newVert4 );
158 //
159 // // one triangles
160 // mesh.resizeTriangles( 1 );
161 // mesh.fastAddTriangle( 0, 2, 4 );
162 //
163 // WVector3d expectedNormal( -0.40824829, 0.816496581, -0.40824829 );
164 //
165 // double delta = 1e-7;
166 // TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[0], expectedNormal[0], delta );
167 // TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[1], expectedNormal[1], delta );
168 // TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[2], expectedNormal[2], delta );
169 // }
170 //
171 // /**
172 // * Test computeTriNormals
173 // */
174 // void testComputeTriNormals()
175 // {
176 // WTriangleMesh mesh;
177 //
178 // mesh.resizeVertices( 5 );
179 // WPosition newVert0( 0, 0, 0 );
180 // mesh.fastAddVert( newVert0 );
181 //
182 // WPosition newVert1( 1.3, 2.25, 3.435 );
183 // mesh.fastAddVert( newVert1 );
184 //
185 // WPosition newVert2( 1, 2, 3 );
186 // mesh.fastAddVert( newVert2 );
187 //
188 // WPosition newVert3( 1.2, 1.5, 1.7 );
189 // mesh.fastAddVert( newVert3 );
190 //
191 // WPosition newVert4( 1, 1, 1 );
192 // mesh.fastAddVert( newVert4 );
193 //
194 // // two triangles
195 // mesh.resizeTriangles( 2 );
196 // mesh.fastAddTriangle( 0, 2, 4 );
197 // mesh.fastAddTriangle( 0, 1, 4 );
198 //
199 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, false );
200 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 0 );
201 //
202 // mesh.computeTriNormals();
203 //
204 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, true );
205 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 2 );
206 //
207 // double delta = 1e-7;
208 // WVector3d expectedNormal( -0.40824829, 0.816496581, -0.40824829 );
209 // TS_ASSERT_DELTA( length( expectedNormal ), 1, delta ); // check ouu expectance :-)
210 //
211 // TS_ASSERT_DELTA( length( mesh.m_triNormals[0] ), 1, delta );
212 // TS_ASSERT_DELTA( mesh.m_triNormals[0][0], expectedNormal[0], delta );
213 // TS_ASSERT_DELTA( mesh.m_triNormals[0][1], expectedNormal[1], delta );
214 // TS_ASSERT_DELTA( mesh.m_triNormals[0][2], expectedNormal[2], delta );
215 // TS_ASSERT_DELTA( length( mesh.m_triNormals[1] ), 1, delta );
216 // };
217 //
218 // /**
219 // * Test computeVertNormals
220 // */
221 // void testComputeVertNormals()
222 // {
223 // WTriangleMesh mesh;
224 //
225 // mesh.resizeVertices( 5 );
226 // WPosition newVert0( 0, 0, 0 );
227 // mesh.fastAddVert( newVert0 );
228 //
229 // WPosition newVert1( 1.3, 2.25, 3.435 );
230 // mesh.fastAddVert( newVert1 );
231 //
232 // WPosition newVert2( 1, 2, 3 );
233 // mesh.fastAddVert( newVert2 );
234 //
235 // WPosition newVert3( 1.2, 1.5, 1.7 );
236 // mesh.fastAddVert( newVert3 );
237 //
238 // WPosition newVert4( 1, 1, 1 );
239 // mesh.fastAddVert( newVert4 );
240 //
241 // // two triangles
242 // mesh.resizeTriangles( 2 );
243 // mesh.fastAddTriangle( 0, 2, 4 );
244 // mesh.fastAddTriangle( 0, 1, 4 );
245 //
246 // TS_ASSERT_EQUALS( mesh.m_computedVertNormals, false );
247 // TS_ASSERT_EQUALS( mesh.m_vertNormals.size(), 0 );
248 //
249 // // check this too. We need the tri normals for the vert normals
250 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, false );
251 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 0 );
252 //
253 // // call the funtion itself
254 // mesh.computeVertNormals();
255 //
256 // // what we expect
257 // WVector3d expectedNormal0( -0.40824829, 0.816496581, -0.40824829 );
258 // WVector3d expectedNormal1( -0.452271958, 0.814852852, -0.362580895 );
259 // double delta = 1e-7;
260 //
261 // // check this triangle stuff too. We need the tri normals for the vert normals
262 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, true );
263 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 2 );
264 // TS_ASSERT_DELTA( length( mesh.m_triNormals[0] ), 1, delta );
265 // TS_ASSERT_DELTA( mesh.m_triNormals[0][0], expectedNormal0[0], delta );
266 // TS_ASSERT_DELTA( mesh.m_triNormals[0][1], expectedNormal0[1], delta );
267 // TS_ASSERT_DELTA( mesh.m_triNormals[0][2], expectedNormal0[2], delta );
268 // TS_ASSERT_DELTA( mesh.m_triNormals[1][0], expectedNormal1[0], delta );
269 // TS_ASSERT_DELTA( mesh.m_triNormals[1][1], expectedNormal1[1], delta );
270 // TS_ASSERT_DELTA( mesh.m_triNormals[1][2], expectedNormal1[2], delta );
271 //
272 // // check the vertex stuff
273 // TS_ASSERT_EQUALS( mesh.m_computedVertNormals, true );
274 // TS_ASSERT_EQUALS( mesh.m_vertNormals.size(), 5 );
275 // // vertex 2 belongs only to one triangle so it should have the normal of the triangle
276 // TS_ASSERT_DELTA( mesh.m_vertNormals[2][0], expectedNormal0[0], delta );
277 // TS_ASSERT_DELTA( mesh.m_vertNormals[2][1], expectedNormal0[1], delta );
278 // TS_ASSERT_DELTA( mesh.m_vertNormals[2][2], expectedNormal0[2], delta );
279 // // vertex 1 belongs only to one triangle so it should have the normal of the triangle
280 // TS_ASSERT_DELTA( mesh.m_vertNormals[1][0], expectedNormal1[0], delta );
281 // TS_ASSERT_DELTA( mesh.m_vertNormals[1][1], expectedNormal1[1], delta );
282 // TS_ASSERT_DELTA( mesh.m_vertNormals[1][2], expectedNormal1[2], delta );
283 //
284 // // vertex 0 belongs to two triangles so it should have the average normal of the two triangles
285 // WVector3d expectedVertNormal = 0.5 * ( expectedNormal0 + expectedNormal1 );
286 // expectedVertNormal.normalize();
287 // TS_ASSERT_DELTA( mesh.m_vertNormals[0][0], expectedVertNormal[0], delta );
288 // TS_ASSERT_DELTA( mesh.m_vertNormals[0][1], expectedVertNormal[1], delta );
289 // TS_ASSERT_DELTA( mesh.m_vertNormals[0][2], expectedVertNormal[2], delta );
290 // }
291 
292  /**
293  * Two WTriangleMeshes are considered to be equal only if they have the same
294  * points in same order and the same indices of points for the triangles also
295  * in same order.
296  * From an objective point of view there might be different ordering resuling
297  * in the same structure, but this is to expensive to compute.
298  */
299  void testEqualityOperator( void )
300  {
301  WTriangleMesh mesh( 3, 1 );
302  mesh.addVertex( WPosition( 1, 0, 0 ) );
303  mesh.addVertex( WPosition( 0, 1, 0 ) );
304  mesh.addVertex( WPosition( 1, 0, 0 ) );
305  mesh.addTriangle( 0, 1, 2 );
306 
307  WTriangleMesh expected( mesh );
308 
309  TS_ASSERT_EQUALS( expected, mesh );
310  std::swap( mesh.m_triangles[0], mesh.m_triangles[1] );
311  TS_ASSERT_DIFFERS( expected, mesh );
312  }
313 
314  /**
315  * Decompose the following scene into seven components A, B, C, D, E, F, G.
316  \verbatim
317 
318  12 o-----o o----o
319  / \ / \ |\ /|
320  / \ / \ | \/ |
321  11 o-----o-----o | /\ |
322  \ / \ / |/ \|
323  10 \ / \ / o----o B
324  9 o-----o A
325 
326  8 o
327  7 o |\
328  / \ | \
329  / \ | \
330  6 o-----o--+--o\
331  5 \ o-+--o C
332  \ /
333  4 o D
334 
335  3 o E (degenerated)
336 
337  2 o-----o F (degenerated)
338 
339  1 o-----o G
340  \ /
341  \ /
342  0 o
343 
344  0 1 2 3 4 5 6 7
345 
346  \endverbatim
347  */
349  {
350  WTriangleMesh mesh( 25, 16 );
351 
352  mesh.addVertex( WPosition( 1, 0, 0 ) ); // 0
353  mesh.addVertex( WPosition( 0, 1, 0 ) ); // 1
354  mesh.addVertex( WPosition( 2, 1, 0 ) ); // 2
355  mesh.addVertex( WPosition( 0, 2, 0 ) ); // 3
356  mesh.addVertex( WPosition( 2, 2, 0 ) ); // 4
357  mesh.addVertex( WPosition( 0, 3, 0 ) ); // 5
358  mesh.addVertex( WPosition( 3, 4, 0 ) ); // 6
359  mesh.addVertex( WPosition( 3, 5, 0 ) ); // 7
360  mesh.addVertex( WPosition( 5, 5, 0 ) ); // 8
361  mesh.addVertex( WPosition( 0, 6, 0 ) ); // 9
362  mesh.addVertex( WPosition( 2, 6, 0 ) ); // 10
363  mesh.addVertex( WPosition( 4, 6, 0 ) ); // 11
364  mesh.addVertex( WPosition( 1, 7, 0 ) ); // 12
365  mesh.addVertex( WPosition( 3, 8, 0 ) ); // 13
366  mesh.addVertex( WPosition( 1, 9, 0 ) ); // 14
367  mesh.addVertex( WPosition( 3, 9, 0 ) ); // 15
368  mesh.addVertex( WPosition( 6, 10, 0 ) ); // 16
369  mesh.addVertex( WPosition( 7, 10, 0 ) ); // 17
370  mesh.addVertex( WPosition( 0, 11, 0 ) ); // 18
371  mesh.addVertex( WPosition( 2, 11, 0 ) ); // 19
372  mesh.addVertex( WPosition( 4, 11, 0 ) ); // 20
373  mesh.addVertex( WPosition( 1, 12, 0 ) ); // 21
374  mesh.addVertex( WPosition( 3, 12, 0 ) ); // 23
375  mesh.addVertex( WPosition( 6, 12, 0 ) ); // 23
376  mesh.addVertex( WPosition( 7, 12, 0 ) ); // 24
377 
378  mesh.addTriangle( 0, 1, 2 ); // 0
379  mesh.addTriangle( 3, 4, 4 ); // 1
380  mesh.addTriangle( 5, 5, 5 ); // 2
381  mesh.addTriangle( 9, 10, 12 ); // 3
382  mesh.addTriangle( 10, 6, 11 ); // 4
383  mesh.addTriangle( 7, 8, 13 ); // 5
384  mesh.addTriangle( 18, 14, 19 ); // 6
385  mesh.addTriangle( 14, 15, 19 ); // 7
386  mesh.addTriangle( 15, 20, 19 ); // 8
387  mesh.addTriangle( 20, 22, 19 ); // 9
388  mesh.addTriangle( 22, 21, 19 ); // 10
389  mesh.addTriangle( 21, 18, 19 ); // 11
390  mesh.addTriangle( 16, 17, 23 ); // 12
391  mesh.addTriangle( 16, 17, 24 ); // 13
392  mesh.addTriangle( 16, 23, 24 ); // 14
393  mesh.addTriangle( 17, 23, 24 ); // 15
394 
395  boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > components = tm_utils::componentDecomposition( mesh );
396  TS_ASSERT_EQUALS( components->size(), 7 );
397 
398  std::list< boost::shared_ptr< WTriangleMesh > >::const_iterator cit = components->begin();
399  WTriangleMesh expected( 3, 1 );
400  expected.addVertex( WPosition( 1, 0, 0 ) );
401  expected.addVertex( WPosition( 0, 1, 0 ) );
402  expected.addVertex( WPosition( 2, 1, 0 ) );
403  expected.addTriangle( 0, 1, 2 );
404  TS_ASSERT_EQUALS( **cit, expected );
405 
406 // expected.resizeVertices( 2 );
407 // expected.m_vertices[ 0 ] = WPosition( 0, 2, 0 );
408 // expected.m_vertices[ 1 ] = WPosition( 2, 2, 0 );
409 // expected.resizeTriangles( 1 );
410 // Triangle x1 = { { 0, 1, 1 } }; // NOLINT
411 // expected.m_triangles[ 0 ] = x1;
412 // TS_ASSERT_EQUALS( **( ++cit ), expected );
413 //
414 // expected.resizeVertices( 1 );
415 // expected.m_vertices[ 0 ] = WPosition( 0, 3, 0 );
416 // expected.resizeTriangles( 1 );
417 // Triangle x2 = { { 0, 0, 0 } }; // NOLINT
418 // expected.m_triangles[ 0 ] = x2;
419 // TS_ASSERT_EQUALS( **( ++cit ), expected );
420 //
421 // expected.resizeVertices( 5 );
422 // expected.m_vertices[ 0 ] = WPosition( 0, 6, 0 );
423 // expected.m_vertices[ 1 ] = WPosition( 2, 6, 0 );
424 // expected.m_vertices[ 2 ] = WPosition( 1, 7, 0 );
425 // expected.m_vertices[ 3 ] = WPosition( 3, 4, 0 );
426 // expected.m_vertices[ 4 ] = WPosition( 4, 6, 0 );
427 // expected.resizeTriangles( 2 );
428 // Triangle x3 = { { 0, 1, 2 } }; // NOLINT
429 // Triangle x4 = { { 1, 3, 4 } }; // NOLINT
430 // expected.m_triangles[ 0 ] = x3;
431 // expected.m_triangles[ 1 ] = x4;
432 // TS_ASSERT_EQUALS( **( ++cit ), expected );
433  }
434 
435  /**
436  * On an empty mesh an empty list should be generated.
437  */
439  {
440  WTriangleMesh mesh( 0, 0 );
441  boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > result = tm_utils::componentDecomposition( mesh );
442  TS_ASSERT( result->empty() );
443  }
444 };
445 #endif // WTRIANGLEMESH_TEST_H