OpenWalnut
1.4.0
|
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 WTRIANGLEMESH_TEST_H 00026 #define WTRIANGLEMESH_TEST_H 00027 00028 #include <algorithm> 00029 #include <list> 00030 #include <vector> 00031 00032 #include <cxxtest/TestSuite.h> 00033 00034 #include "../../common/math/linearAlgebra/WPosition.h" 00035 #include "../WTriangleMesh.h" 00036 #include "WTriangleMeshTraits.h" 00037 00038 /** 00039 * Testing the WTriangleMesh class. 00040 */ 00041 class WTriangleMeshTest : public CxxTest::TestSuite 00042 { 00043 public: 00044 // TODO(schurade): fix unit test from old triangle class 00045 // /** 00046 // * Ensure instatiation does not throw and does initialization right. 00047 // */ 00048 // void testInstatiation() 00049 // { 00050 // TS_ASSERT_THROWS_NOTHING( WTriangleMesh() ); 00051 // WTriangleMesh mesh; 00052 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); 00053 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); 00054 // } 00055 // 00056 // /** 00057 // * clearMesh should reset all members. 00058 // */ 00059 // void testClearMesh() 00060 // { 00061 // WTriangleMesh mesh; 00062 // mesh.m_fastAddVertId = 9; // just a number 00063 // mesh.m_fastAddTriangleId = 10; // just a number 00064 // mesh.m_vertices.resize( 11 ); // just some size 00065 // mesh.m_triangles.resize( 13 ); // just some size 00066 // 00067 // mesh.clearMesh(); 00068 // 00069 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); 00070 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); 00071 // TS_ASSERT_EQUALS( mesh.m_vertices.size(), 0 ); 00072 // TS_ASSERT_EQUALS( mesh.m_triangles.size(), 0 ); 00073 // } 00074 // 00075 // /** 00076 // * fastAddVert should increment the corresponding counter 00077 // */ 00078 // void testFastAddVert() 00079 // { 00080 // WTriangleMesh mesh; 00081 // mesh.resizeVertices( 2 ); 00082 // WPosition newVert; 00083 // 00084 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); 00085 // mesh.fastAddVert( newVert ); 00086 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 1 ); 00087 // mesh.fastAddVert( newVert ); 00088 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 2 ); 00089 // } 00090 // 00091 // /** 00092 // * fastAddTriangle should increment the corresponding counter 00093 // */ 00094 // void testFastAddTriangle() 00095 // { 00096 // WTriangleMesh mesh; 00097 // mesh.resizeTriangles( 2 ); 00098 // 00099 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); 00100 // mesh.fastAddTriangle( 0, 1, 2 ); 00101 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 1 ); 00102 // mesh.fastAddTriangle( 1, 2, 3 ); 00103 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 2 ); 00104 // } 00105 // 00106 // /** 00107 // * setVertices should set the fastAddId and resize the member 00108 // */ 00109 // void testSetVertices() 00110 // { 00111 // WTriangleMesh mesh; 00112 // std::vector< WPosition > vertices( 4 ); 00113 // 00114 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); 00115 // TS_ASSERT_EQUALS( mesh.m_vertices.size(), 0 ); 00116 // mesh.setVertices( vertices ); 00117 // TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 4 ); 00118 // TS_ASSERT_EQUALS( mesh.m_vertices.size(), 4 ); 00119 // } 00120 // 00121 // /** 00122 // * setTriangles should set the fastAddId and resize the member 00123 // */ 00124 // void testSetTriangles() 00125 // { 00126 // WTriangleMesh mesh; 00127 // std::vector< Triangle > triangles( 5 ); 00128 // 00129 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); 00130 // TS_ASSERT_EQUALS( mesh.m_triangles.size(), 0 ); 00131 // mesh.setTriangles( triangles ); 00132 // TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 5 ); 00133 // TS_ASSERT_EQUALS( mesh.m_triangles.size(), 5 ); 00134 // } 00135 // 00136 // /** 00137 // * Test getTriangleNormal 00138 // */ 00139 // void testgetTriangleNormal() 00140 // { 00141 // WTriangleMesh mesh; 00142 // 00143 // mesh.resizeVertices( 5 ); 00144 // WPosition newVert0( 0, 0, 0 ); 00145 // mesh.fastAddVert( newVert0 ); 00146 // 00147 // WPosition newVert1( 1.3, 2.25, 3.435 ); 00148 // mesh.fastAddVert( newVert1 ); 00149 // 00150 // WPosition newVert2( 1, 2, 3 ); 00151 // mesh.fastAddVert( newVert2 ); 00152 // 00153 // WPosition newVert3( 1.2, 1.5, 1.7 ); 00154 // mesh.fastAddVert( newVert3 ); 00155 // 00156 // WPosition newVert4( 1, 1, 1 ); 00157 // mesh.fastAddVert( newVert4 ); 00158 // 00159 // // one triangles 00160 // mesh.resizeTriangles( 1 ); 00161 // mesh.fastAddTriangle( 0, 2, 4 ); 00162 // 00163 // WVector3d expectedNormal( -0.40824829, 0.816496581, -0.40824829 ); 00164 // 00165 // double delta = 1e-7; 00166 // TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[0], expectedNormal[0], delta ); 00167 // TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[1], expectedNormal[1], delta ); 00168 // TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[2], expectedNormal[2], delta ); 00169 // } 00170 // 00171 // /** 00172 // * Test computeTriNormals 00173 // */ 00174 // void testComputeTriNormals() 00175 // { 00176 // WTriangleMesh mesh; 00177 // 00178 // mesh.resizeVertices( 5 ); 00179 // WPosition newVert0( 0, 0, 0 ); 00180 // mesh.fastAddVert( newVert0 ); 00181 // 00182 // WPosition newVert1( 1.3, 2.25, 3.435 ); 00183 // mesh.fastAddVert( newVert1 ); 00184 // 00185 // WPosition newVert2( 1, 2, 3 ); 00186 // mesh.fastAddVert( newVert2 ); 00187 // 00188 // WPosition newVert3( 1.2, 1.5, 1.7 ); 00189 // mesh.fastAddVert( newVert3 ); 00190 // 00191 // WPosition newVert4( 1, 1, 1 ); 00192 // mesh.fastAddVert( newVert4 ); 00193 // 00194 // // two triangles 00195 // mesh.resizeTriangles( 2 ); 00196 // mesh.fastAddTriangle( 0, 2, 4 ); 00197 // mesh.fastAddTriangle( 0, 1, 4 ); 00198 // 00199 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, false ); 00200 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 0 ); 00201 // 00202 // mesh.computeTriNormals(); 00203 // 00204 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, true ); 00205 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 2 ); 00206 // 00207 // double delta = 1e-7; 00208 // WVector3d expectedNormal( -0.40824829, 0.816496581, -0.40824829 ); 00209 // TS_ASSERT_DELTA( length( expectedNormal ), 1, delta ); // check ouu expectance :-) 00210 // 00211 // TS_ASSERT_DELTA( length( mesh.m_triNormals[0] ), 1, delta ); 00212 // TS_ASSERT_DELTA( mesh.m_triNormals[0][0], expectedNormal[0], delta ); 00213 // TS_ASSERT_DELTA( mesh.m_triNormals[0][1], expectedNormal[1], delta ); 00214 // TS_ASSERT_DELTA( mesh.m_triNormals[0][2], expectedNormal[2], delta ); 00215 // TS_ASSERT_DELTA( length( mesh.m_triNormals[1] ), 1, delta ); 00216 // }; 00217 // 00218 // /** 00219 // * Test computeVertNormals 00220 // */ 00221 // void testComputeVertNormals() 00222 // { 00223 // WTriangleMesh mesh; 00224 // 00225 // mesh.resizeVertices( 5 ); 00226 // WPosition newVert0( 0, 0, 0 ); 00227 // mesh.fastAddVert( newVert0 ); 00228 // 00229 // WPosition newVert1( 1.3, 2.25, 3.435 ); 00230 // mesh.fastAddVert( newVert1 ); 00231 // 00232 // WPosition newVert2( 1, 2, 3 ); 00233 // mesh.fastAddVert( newVert2 ); 00234 // 00235 // WPosition newVert3( 1.2, 1.5, 1.7 ); 00236 // mesh.fastAddVert( newVert3 ); 00237 // 00238 // WPosition newVert4( 1, 1, 1 ); 00239 // mesh.fastAddVert( newVert4 ); 00240 // 00241 // // two triangles 00242 // mesh.resizeTriangles( 2 ); 00243 // mesh.fastAddTriangle( 0, 2, 4 ); 00244 // mesh.fastAddTriangle( 0, 1, 4 ); 00245 // 00246 // TS_ASSERT_EQUALS( mesh.m_computedVertNormals, false ); 00247 // TS_ASSERT_EQUALS( mesh.m_vertNormals.size(), 0 ); 00248 // 00249 // // check this too. We need the tri normals for the vert normals 00250 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, false ); 00251 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 0 ); 00252 // 00253 // // call the funtion itself 00254 // mesh.computeVertNormals(); 00255 // 00256 // // what we expect 00257 // WVector3d expectedNormal0( -0.40824829, 0.816496581, -0.40824829 ); 00258 // WVector3d expectedNormal1( -0.452271958, 0.814852852, -0.362580895 ); 00259 // double delta = 1e-7; 00260 // 00261 // // check this triangle stuff too. We need the tri normals for the vert normals 00262 // TS_ASSERT_EQUALS( mesh.m_computedTriNormals, true ); 00263 // TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 2 ); 00264 // TS_ASSERT_DELTA( length( mesh.m_triNormals[0] ), 1, delta ); 00265 // TS_ASSERT_DELTA( mesh.m_triNormals[0][0], expectedNormal0[0], delta ); 00266 // TS_ASSERT_DELTA( mesh.m_triNormals[0][1], expectedNormal0[1], delta ); 00267 // TS_ASSERT_DELTA( mesh.m_triNormals[0][2], expectedNormal0[2], delta ); 00268 // TS_ASSERT_DELTA( mesh.m_triNormals[1][0], expectedNormal1[0], delta ); 00269 // TS_ASSERT_DELTA( mesh.m_triNormals[1][1], expectedNormal1[1], delta ); 00270 // TS_ASSERT_DELTA( mesh.m_triNormals[1][2], expectedNormal1[2], delta ); 00271 // 00272 // // check the vertex stuff 00273 // TS_ASSERT_EQUALS( mesh.m_computedVertNormals, true ); 00274 // TS_ASSERT_EQUALS( mesh.m_vertNormals.size(), 5 ); 00275 // // vertex 2 belongs only to one triangle so it should have the normal of the triangle 00276 // TS_ASSERT_DELTA( mesh.m_vertNormals[2][0], expectedNormal0[0], delta ); 00277 // TS_ASSERT_DELTA( mesh.m_vertNormals[2][1], expectedNormal0[1], delta ); 00278 // TS_ASSERT_DELTA( mesh.m_vertNormals[2][2], expectedNormal0[2], delta ); 00279 // // vertex 1 belongs only to one triangle so it should have the normal of the triangle 00280 // TS_ASSERT_DELTA( mesh.m_vertNormals[1][0], expectedNormal1[0], delta ); 00281 // TS_ASSERT_DELTA( mesh.m_vertNormals[1][1], expectedNormal1[1], delta ); 00282 // TS_ASSERT_DELTA( mesh.m_vertNormals[1][2], expectedNormal1[2], delta ); 00283 // 00284 // // vertex 0 belongs to two triangles so it should have the average normal of the two triangles 00285 // WVector3d expectedVertNormal = 0.5 * ( expectedNormal0 + expectedNormal1 ); 00286 // expectedVertNormal.normalize(); 00287 // TS_ASSERT_DELTA( mesh.m_vertNormals[0][0], expectedVertNormal[0], delta ); 00288 // TS_ASSERT_DELTA( mesh.m_vertNormals[0][1], expectedVertNormal[1], delta ); 00289 // TS_ASSERT_DELTA( mesh.m_vertNormals[0][2], expectedVertNormal[2], delta ); 00290 // } 00291 00292 /** 00293 * Two WTriangleMeshes are considered to be equal only if they have the same 00294 * points in same order and the same indices of points for the triangles also 00295 * in same order. 00296 * From an objective point of view there might be different ordering resuling 00297 * in the same structure, but this is to expensive to compute. 00298 */ 00299 void testEqualityOperator( void ) 00300 { 00301 WTriangleMesh mesh( 3, 1 ); 00302 mesh.addVertex( WPosition( 1, 0, 0 ) ); 00303 mesh.addVertex( WPosition( 0, 1, 0 ) ); 00304 mesh.addVertex( WPosition( 1, 0, 0 ) ); 00305 mesh.addTriangle( 0, 1, 2 ); 00306 00307 WTriangleMesh expected( mesh ); 00308 00309 TS_ASSERT_EQUALS( expected, mesh ); 00310 std::swap( mesh.m_triangles[0], mesh.m_triangles[1] ); 00311 TS_ASSERT_DIFFERS( expected, mesh ); 00312 } 00313 00314 /** 00315 * Decompose the following scene into seven components A, B, C, D, E, F, G. 00316 \verbatim 00317 00318 12 o-----o o----o 00319 / \ / \ |\ /| 00320 / \ / \ | \/ | 00321 11 o-----o-----o | /\ | 00322 \ / \ / |/ \| 00323 10 \ / \ / o----o B 00324 9 o-----o A 00325 00326 8 o 00327 7 o |\ 00328 / \ | \ 00329 / \ | \ 00330 6 o-----o--+--o\ 00331 5 \ o-+--o C 00332 \ / 00333 4 o D 00334 00335 3 o E (degenerated) 00336 00337 2 o-----o F (degenerated) 00338 00339 1 o-----o G 00340 \ / 00341 \ / 00342 0 o 00343 00344 0 1 2 3 4 5 6 7 00345 00346 \endverbatim 00347 */ 00348 void testComponentDecomposition( void ) 00349 { 00350 WTriangleMesh mesh( 25, 16 ); 00351 00352 mesh.addVertex( WPosition( 1, 0, 0 ) ); // 0 00353 mesh.addVertex( WPosition( 0, 1, 0 ) ); // 1 00354 mesh.addVertex( WPosition( 2, 1, 0 ) ); // 2 00355 mesh.addVertex( WPosition( 0, 2, 0 ) ); // 3 00356 mesh.addVertex( WPosition( 2, 2, 0 ) ); // 4 00357 mesh.addVertex( WPosition( 0, 3, 0 ) ); // 5 00358 mesh.addVertex( WPosition( 3, 4, 0 ) ); // 6 00359 mesh.addVertex( WPosition( 3, 5, 0 ) ); // 7 00360 mesh.addVertex( WPosition( 5, 5, 0 ) ); // 8 00361 mesh.addVertex( WPosition( 0, 6, 0 ) ); // 9 00362 mesh.addVertex( WPosition( 2, 6, 0 ) ); // 10 00363 mesh.addVertex( WPosition( 4, 6, 0 ) ); // 11 00364 mesh.addVertex( WPosition( 1, 7, 0 ) ); // 12 00365 mesh.addVertex( WPosition( 3, 8, 0 ) ); // 13 00366 mesh.addVertex( WPosition( 1, 9, 0 ) ); // 14 00367 mesh.addVertex( WPosition( 3, 9, 0 ) ); // 15 00368 mesh.addVertex( WPosition( 6, 10, 0 ) ); // 16 00369 mesh.addVertex( WPosition( 7, 10, 0 ) ); // 17 00370 mesh.addVertex( WPosition( 0, 11, 0 ) ); // 18 00371 mesh.addVertex( WPosition( 2, 11, 0 ) ); // 19 00372 mesh.addVertex( WPosition( 4, 11, 0 ) ); // 20 00373 mesh.addVertex( WPosition( 1, 12, 0 ) ); // 21 00374 mesh.addVertex( WPosition( 3, 12, 0 ) ); // 23 00375 mesh.addVertex( WPosition( 6, 12, 0 ) ); // 23 00376 mesh.addVertex( WPosition( 7, 12, 0 ) ); // 24 00377 00378 mesh.addTriangle( 0, 1, 2 ); // 0 00379 mesh.addTriangle( 3, 4, 4 ); // 1 00380 mesh.addTriangle( 5, 5, 5 ); // 2 00381 mesh.addTriangle( 9, 10, 12 ); // 3 00382 mesh.addTriangle( 10, 6, 11 ); // 4 00383 mesh.addTriangle( 7, 8, 13 ); // 5 00384 mesh.addTriangle( 18, 14, 19 ); // 6 00385 mesh.addTriangle( 14, 15, 19 ); // 7 00386 mesh.addTriangle( 15, 20, 19 ); // 8 00387 mesh.addTriangle( 20, 22, 19 ); // 9 00388 mesh.addTriangle( 22, 21, 19 ); // 10 00389 mesh.addTriangle( 21, 18, 19 ); // 11 00390 mesh.addTriangle( 16, 17, 23 ); // 12 00391 mesh.addTriangle( 16, 17, 24 ); // 13 00392 mesh.addTriangle( 16, 23, 24 ); // 14 00393 mesh.addTriangle( 17, 23, 24 ); // 15 00394 00395 boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > components = tm_utils::componentDecomposition( mesh ); 00396 TS_ASSERT_EQUALS( components->size(), 7 ); 00397 00398 std::list< boost::shared_ptr< WTriangleMesh > >::const_iterator cit = components->begin(); 00399 WTriangleMesh expected( 3, 1 ); 00400 expected.addVertex( WPosition( 1, 0, 0 ) ); 00401 expected.addVertex( WPosition( 0, 1, 0 ) ); 00402 expected.addVertex( WPosition( 2, 1, 0 ) ); 00403 expected.addTriangle( 0, 1, 2 ); 00404 TS_ASSERT_EQUALS( **cit, expected ); 00405 00406 // expected.resizeVertices( 2 ); 00407 // expected.m_vertices[ 0 ] = WPosition( 0, 2, 0 ); 00408 // expected.m_vertices[ 1 ] = WPosition( 2, 2, 0 ); 00409 // expected.resizeTriangles( 1 ); 00410 // Triangle x1 = { { 0, 1, 1 } }; // NOLINT 00411 // expected.m_triangles[ 0 ] = x1; 00412 // TS_ASSERT_EQUALS( **( ++cit ), expected ); 00413 // 00414 // expected.resizeVertices( 1 ); 00415 // expected.m_vertices[ 0 ] = WPosition( 0, 3, 0 ); 00416 // expected.resizeTriangles( 1 ); 00417 // Triangle x2 = { { 0, 0, 0 } }; // NOLINT 00418 // expected.m_triangles[ 0 ] = x2; 00419 // TS_ASSERT_EQUALS( **( ++cit ), expected ); 00420 // 00421 // expected.resizeVertices( 5 ); 00422 // expected.m_vertices[ 0 ] = WPosition( 0, 6, 0 ); 00423 // expected.m_vertices[ 1 ] = WPosition( 2, 6, 0 ); 00424 // expected.m_vertices[ 2 ] = WPosition( 1, 7, 0 ); 00425 // expected.m_vertices[ 3 ] = WPosition( 3, 4, 0 ); 00426 // expected.m_vertices[ 4 ] = WPosition( 4, 6, 0 ); 00427 // expected.resizeTriangles( 2 ); 00428 // Triangle x3 = { { 0, 1, 2 } }; // NOLINT 00429 // Triangle x4 = { { 1, 3, 4 } }; // NOLINT 00430 // expected.m_triangles[ 0 ] = x3; 00431 // expected.m_triangles[ 1 ] = x4; 00432 // TS_ASSERT_EQUALS( **( ++cit ), expected ); 00433 } 00434 00435 /** 00436 * On an empty mesh an empty list should be generated. 00437 */ 00438 void testComponentDecompositionOnEmptyMesh( void ) 00439 { 00440 WTriangleMesh mesh( 0, 0 ); 00441 boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > result = tm_utils::componentDecomposition( mesh ); 00442 TS_ASSERT( result->empty() ); 00443 } 00444 }; 00445 #endif // WTRIANGLEMESH_TEST_H