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