//--------------------------------------------------------------------------- // // Project: OpenWalnut ( http://www.openwalnut.org ) // // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS // For more information see http://www.openwalnut.org/copying // // This file is part of OpenWalnut. // // OpenWalnut is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OpenWalnut is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with OpenWalnut. If not, see . // //--------------------------------------------------------------------------- #ifndef WTRIANGLEMESH_TEST_H #define WTRIANGLEMESH_TEST_H #include #include #include #include #include "../../math/WVector3D.h" #include "../WTriangleMesh.h" #include "WTriangleMeshTraits.h" /** * Testing the WTriangleMesh class. */ class WTriangleMeshTest : public CxxTest::TestSuite { public: /** * Ensure instatiation does not throw and does initialization right. */ void testInstatiation() { TS_ASSERT_THROWS_NOTHING( WTriangleMesh() ); WTriangleMesh mesh; TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); } /** * clearMesh should reset all members. */ void testClearMesh() { WTriangleMesh mesh; mesh.m_fastAddVertId = 9; // just a number mesh.m_fastAddTriangleId = 10; // just a number mesh.m_vertices.resize( 11 ); // just some size mesh.m_triangles.resize( 13 ); // just some size mesh.clearMesh(); TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); TS_ASSERT_EQUALS( mesh.m_vertices.size(), 0 ); TS_ASSERT_EQUALS( mesh.m_triangles.size(), 0 ); } /** * fastAddVert should increment the corresponding counter */ void testFastAddVert() { WTriangleMesh mesh; mesh.resizeVertices( 2 ); wmath::WPosition newVert; TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); mesh.fastAddVert( newVert ); TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 1 ); mesh.fastAddVert( newVert ); TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 2 ); } /** * fastAddTriangle should increment the corresponding counter */ void testFastAddTriangle() { WTriangleMesh mesh; mesh.resizeTriangles( 2 ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); mesh.fastAddTriangle( 0, 1, 2 ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 1 ); mesh.fastAddTriangle( 1, 2, 3 ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 2 ); } /** * setVertices should set the fastAddId and resize the member */ void testSetVertices() { WTriangleMesh mesh; std::vector< wmath::WPosition > vertices( 4 ); TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 0 ); TS_ASSERT_EQUALS( mesh.m_vertices.size(), 0 ); mesh.setVertices( vertices ); TS_ASSERT_EQUALS( mesh.m_fastAddVertId, 4 ); TS_ASSERT_EQUALS( mesh.m_vertices.size(), 4 ); } /** * setTriangles should set the fastAddId and resize the member */ void testSetTriangles() { WTriangleMesh mesh; std::vector< Triangle > triangles( 5 ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 0 ); TS_ASSERT_EQUALS( mesh.m_triangles.size(), 0 ); mesh.setTriangles( triangles ); TS_ASSERT_EQUALS( mesh.m_fastAddTriangleId, 5 ); TS_ASSERT_EQUALS( mesh.m_triangles.size(), 5 ); } /** * Test getTriangleNormal */ void testgetTriangleNormal() { WTriangleMesh mesh; mesh.resizeVertices( 5 ); wmath::WPosition newVert0( 0, 0, 0 ); mesh.fastAddVert( newVert0 ); wmath::WPosition newVert1( 1.3, 2.25, 3.435 ); mesh.fastAddVert( newVert1 ); wmath::WPosition newVert2( 1, 2, 3 ); mesh.fastAddVert( newVert2 ); wmath::WPosition newVert3( 1.2, 1.5, 1.7 ); mesh.fastAddVert( newVert3 ); wmath::WPosition newVert4( 1, 1, 1 ); mesh.fastAddVert( newVert4 ); // one triangles mesh.resizeTriangles( 1 ); mesh.fastAddTriangle( 0, 2, 4 ); wmath::WVector3D expectedNormal( -0.40824829, 0.816496581, -0.40824829 ); double delta = 1e-7; TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[0], expectedNormal[0], delta ); TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[1], expectedNormal[1], delta ); TS_ASSERT_DELTA( mesh.getTriangleNormal( 0 )[2], expectedNormal[2], delta ); } /** * Test computeTriNormals */ void testComputeTriNormals() { WTriangleMesh mesh; mesh.resizeVertices( 5 ); wmath::WPosition newVert0( 0, 0, 0 ); mesh.fastAddVert( newVert0 ); wmath::WPosition newVert1( 1.3, 2.25, 3.435 ); mesh.fastAddVert( newVert1 ); wmath::WPosition newVert2( 1, 2, 3 ); mesh.fastAddVert( newVert2 ); wmath::WPosition newVert3( 1.2, 1.5, 1.7 ); mesh.fastAddVert( newVert3 ); wmath::WPosition newVert4( 1, 1, 1 ); mesh.fastAddVert( newVert4 ); // two triangles mesh.resizeTriangles( 2 ); mesh.fastAddTriangle( 0, 2, 4 ); mesh.fastAddTriangle( 0, 1, 4 ); TS_ASSERT_EQUALS( mesh.m_computedTriNormals, false ); TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 0 ); mesh.computeTriNormals(); TS_ASSERT_EQUALS( mesh.m_computedTriNormals, true ); TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 2 ); double delta = 1e-7; wmath::WVector3D expectedNormal( -0.40824829, 0.816496581, -0.40824829 ); TS_ASSERT_DELTA( expectedNormal.norm(), 1, delta ); // check ouu expectance :-) TS_ASSERT_DELTA( mesh.m_triNormals[0].norm(), 1, delta ); TS_ASSERT_DELTA( mesh.m_triNormals[0][0], expectedNormal[0], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[0][1], expectedNormal[1], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[0][2], expectedNormal[2], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[1].norm(), 1, delta ); }; /** * Test computeVertNormals */ void testComputeVertNormals() { WTriangleMesh mesh; mesh.resizeVertices( 5 ); wmath::WPosition newVert0( 0, 0, 0 ); mesh.fastAddVert( newVert0 ); wmath::WPosition newVert1( 1.3, 2.25, 3.435 ); mesh.fastAddVert( newVert1 ); wmath::WPosition newVert2( 1, 2, 3 ); mesh.fastAddVert( newVert2 ); wmath::WPosition newVert3( 1.2, 1.5, 1.7 ); mesh.fastAddVert( newVert3 ); wmath::WPosition newVert4( 1, 1, 1 ); mesh.fastAddVert( newVert4 ); // two triangles mesh.resizeTriangles( 2 ); mesh.fastAddTriangle( 0, 2, 4 ); mesh.fastAddTriangle( 0, 1, 4 ); TS_ASSERT_EQUALS( mesh.m_computedVertNormals, false ); TS_ASSERT_EQUALS( mesh.m_vertNormals.size(), 0 ); // check this too. We need the tri normals for the vert normals TS_ASSERT_EQUALS( mesh.m_computedTriNormals, false ); TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 0 ); // call the funtion itself mesh.computeVertNormals(); // what we expect wmath::WVector3D expectedNormal0( -0.40824829, 0.816496581, -0.40824829 ); wmath::WVector3D expectedNormal1( -0.452271958, 0.814852852, -0.362580895 ); double delta = 1e-7; // check this triangle stuff too. We need the tri normals for the vert normals TS_ASSERT_EQUALS( mesh.m_computedTriNormals, true ); TS_ASSERT_EQUALS( mesh.m_triNormals.size(), 2 ); TS_ASSERT_DELTA( mesh.m_triNormals[0].norm(), 1, delta ); TS_ASSERT_DELTA( mesh.m_triNormals[0][0], expectedNormal0[0], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[0][1], expectedNormal0[1], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[0][2], expectedNormal0[2], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[1][0], expectedNormal1[0], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[1][1], expectedNormal1[1], delta ); TS_ASSERT_DELTA( mesh.m_triNormals[1][2], expectedNormal1[2], delta ); // check the vertex stuff TS_ASSERT_EQUALS( mesh.m_computedVertNormals, true ); TS_ASSERT_EQUALS( mesh.m_vertNormals.size(), 5 ); // vertex 2 belongs only to one triangle so it should have the normal of the triangle TS_ASSERT_DELTA( mesh.m_vertNormals[2][0], expectedNormal0[0], delta ); TS_ASSERT_DELTA( mesh.m_vertNormals[2][1], expectedNormal0[1], delta ); TS_ASSERT_DELTA( mesh.m_vertNormals[2][2], expectedNormal0[2], delta ); // vertex 1 belongs only to one triangle so it should have the normal of the triangle TS_ASSERT_DELTA( mesh.m_vertNormals[1][0], expectedNormal1[0], delta ); TS_ASSERT_DELTA( mesh.m_vertNormals[1][1], expectedNormal1[1], delta ); TS_ASSERT_DELTA( mesh.m_vertNormals[1][2], expectedNormal1[2], delta ); // vertex 0 belongs to two triangles so it should have the average normal of the two triangles wmath::WVector3D expectedVertNormal = 0.5 * ( expectedNormal0 + expectedNormal1 ); expectedVertNormal.normalize(); TS_ASSERT_DELTA( mesh.m_vertNormals[0][0], expectedVertNormal[0], delta ); TS_ASSERT_DELTA( mesh.m_vertNormals[0][1], expectedVertNormal[1], delta ); TS_ASSERT_DELTA( mesh.m_vertNormals[0][2], expectedVertNormal[2], delta ); } /** * Two WTriangleMeshes are considered to be equal only if they have the same * points in same order and the same indices of points for the triangles also * in same order. * From an objective point of view there might be different ordering resuling * in the same structure, but this is to expensive to compute. */ void testEqualityOperator( void ) { WTriangleMesh mesh; mesh.resizeVertices( 3 ); mesh.fastAddVert( wmath::WPosition( 1, 0, 0 ) ); mesh.fastAddVert( wmath::WPosition( 0, 1, 0 ) ); mesh.fastAddVert( wmath::WPosition( 1, 0, 0 ) ); mesh.resizeTriangles( 1 ); mesh.fastAddTriangle( 0, 1, 2 ); WTriangleMesh expected( mesh ); TS_ASSERT_EQUALS( expected, mesh ); std::swap( mesh.m_triangles[0].pointID[0], mesh.m_triangles[0].pointID[1] ); TS_ASSERT_DIFFERS( expected, mesh ); } /** * Decompose the following scene into seven components A, B, C, D, E, F, G. \verbatim 12 o-----o o----o / \ / \ |\ /| / \ / \ | \/ | 11 o-----o-----o | /\ | \ / \ / |/ \| 10 \ / \ / o----o B 9 o-----o A 8 o 7 o |\ / \ | \ / \ | \ 6 o-----o--+--o\ 5 \ o-+--o C \ / 4 o D 3 o E (degenerated) 2 o-----o F (degenerated) 1 o-----o G \ / \ / 0 o 0 1 2 3 4 5 6 7 \endverbatim */ void testComponentDecomposition( void ) { WTriangleMesh mesh; mesh.resizeVertices( 25 ); mesh.fastAddVert( wmath::WPosition( 1, 0, 0 ) ); // 0 mesh.fastAddVert( wmath::WPosition( 0, 1, 0 ) ); // 1 mesh.fastAddVert( wmath::WPosition( 2, 1, 0 ) ); // 2 mesh.fastAddVert( wmath::WPosition( 0, 2, 0 ) ); // 3 mesh.fastAddVert( wmath::WPosition( 2, 2, 0 ) ); // 4 mesh.fastAddVert( wmath::WPosition( 0, 3, 0 ) ); // 5 mesh.fastAddVert( wmath::WPosition( 3, 4, 0 ) ); // 6 mesh.fastAddVert( wmath::WPosition( 3, 5, 0 ) ); // 7 mesh.fastAddVert( wmath::WPosition( 5, 5, 0 ) ); // 8 mesh.fastAddVert( wmath::WPosition( 0, 6, 0 ) ); // 9 mesh.fastAddVert( wmath::WPosition( 2, 6, 0 ) ); // 10 mesh.fastAddVert( wmath::WPosition( 4, 6, 0 ) ); // 11 mesh.fastAddVert( wmath::WPosition( 1, 7, 0 ) ); // 12 mesh.fastAddVert( wmath::WPosition( 3, 8, 0 ) ); // 13 mesh.fastAddVert( wmath::WPosition( 1, 9, 0 ) ); // 14 mesh.fastAddVert( wmath::WPosition( 3, 9, 0 ) ); // 15 mesh.fastAddVert( wmath::WPosition( 6, 10, 0 ) ); // 16 mesh.fastAddVert( wmath::WPosition( 7, 10, 0 ) ); // 17 mesh.fastAddVert( wmath::WPosition( 0, 11, 0 ) ); // 18 mesh.fastAddVert( wmath::WPosition( 2, 11, 0 ) ); // 19 mesh.fastAddVert( wmath::WPosition( 4, 11, 0 ) ); // 20 mesh.fastAddVert( wmath::WPosition( 1, 12, 0 ) ); // 21 mesh.fastAddVert( wmath::WPosition( 3, 12, 0 ) ); // 23 mesh.fastAddVert( wmath::WPosition( 6, 12, 0 ) ); // 23 mesh.fastAddVert( wmath::WPosition( 7, 12, 0 ) ); // 24 mesh.resizeTriangles( 16 ); mesh.fastAddTriangle( 0, 1, 2 ); // 0 mesh.fastAddTriangle( 3, 4, 4 ); // 1 mesh.fastAddTriangle( 5, 5, 5 ); // 2 mesh.fastAddTriangle( 9, 10, 12 ); // 3 mesh.fastAddTriangle( 10, 6, 11 ); // 4 mesh.fastAddTriangle( 7, 8, 13 ); // 5 mesh.fastAddTriangle( 18, 14, 19 ); // 6 mesh.fastAddTriangle( 14, 15, 19 ); // 7 mesh.fastAddTriangle( 15, 20, 19 ); // 8 mesh.fastAddTriangle( 20, 22, 19 ); // 9 mesh.fastAddTriangle( 22, 21, 19 ); // 10 mesh.fastAddTriangle( 21, 18, 19 ); // 11 mesh.fastAddTriangle( 16, 17, 23 ); // 12 mesh.fastAddTriangle( 16, 17, 24 ); // 13 mesh.fastAddTriangle( 16, 23, 24 ); // 14 mesh.fastAddTriangle( 17, 23, 24 ); // 15 boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > components = tm_utils::componentDecomposition( mesh ); TS_ASSERT_EQUALS( components->size(), 7 ); std::list< boost::shared_ptr< WTriangleMesh > >::const_iterator cit = components->begin(); WTriangleMesh expected; expected.resizeVertices( 3 ); expected.fastAddVert( wmath::WPosition( 1, 0, 0 ) ); expected.fastAddVert( wmath::WPosition( 0, 1, 0 ) ); expected.fastAddVert( wmath::WPosition( 2, 1, 0 ) ); expected.resizeTriangles( 1 ); expected.fastAddTriangle( 0, 1, 2 ); TS_ASSERT_EQUALS( **cit, expected ); expected.resizeVertices( 2 ); expected.m_vertices[ 0 ] = wmath::WPosition( 0, 2, 0 ); expected.m_vertices[ 1 ] = wmath::WPosition( 2, 2, 0 ); expected.resizeTriangles( 1 ); Triangle x = { { 0, 1, 1 } }; // NOLINT expected.m_triangles[ 0 ] = x; TS_ASSERT_EQUALS( **( ++cit ), expected ); } }; #endif // WTRIANGLEMESH_TEST_H