Commit e31a3146 authored by Ján Bobot's avatar Ján Bobot Committed by Jakub Klinkovský
Browse files

Added new functions into Meshes/Geometry:

- modified getEntityMeasure specialization for polyhedrons to remove restriction regarding the ordering of vertices, but now it only works for convex polyhedrons
- added function for decomposing polygonal mesh into triangular mesh
- added function for decomposing polyhedral mesh into tetrahedral mesh
parent 5308a150
Loading
Loading
Loading
Loading
+621 −0

File added.

Preview size limit exceeded, changes collapsed.

+31 −1
Original line number Diff line number Diff line
@@ -189,6 +189,10 @@ getPolygon2DArea( const Mesh< MeshConfig, Device > & mesh,
{
    // http://geomalgorithms.com/code.html (function area2D_Polygon)

    static_assert( Coord1 >= 0 && Coord1 <= 2 &&
                   Coord2 >= 0 && Coord2 <= 2 &&
                   Coord1 != Coord2, "Coord1 and Coord2 must be different integers with possible values {0, 1, 2}." );

    using Real = typename MeshConfig::RealType;
    using Index = typename MeshConfig::LocalIndexType;

@@ -315,7 +319,7 @@ getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
}

// Polyhedron
template< typename MeshConfig,
/*template< typename MeshConfig,
          typename Device >
__cuda_callable__
typename MeshConfig::RealType
@@ -347,6 +351,32 @@ getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
        }
    }
    return Real{ 1.0 / 6.0 } * TNL::abs( volume );
}*/

template< typename MeshConfig,
          typename Device >
__cuda_callable__
typename MeshConfig::RealType
getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
                  const MeshEntity< MeshConfig, Device, Topologies::Polyhedron > & entity )
{
    using Real = typename MeshConfig::RealType;
    using Index = typename MeshConfig::LocalIndexType;
    Real volume{ 0.0 };
    const Index facesCount = entity.template getSubentitiesCount< 2 >();
    const auto& v3 = mesh.getPoint( entity.template getSubentityIndex< 0 >( 0 ) );
    for( Index faceIdx = 0; faceIdx < facesCount; faceIdx++ ) {
        const auto face = mesh.template getEntity< 2 >( entity.template getSubentityIndex< 2 >( faceIdx ) );
        const Index verticesCount = face.template getSubentitiesCount< 0 >();
        const auto& v0 = mesh.getPoint( face.template getSubentityIndex< 0 >( 0 ) );
        for( Index i = 1, j = 2; j < verticesCount; i++, j++ ) {
            const auto& v1 = mesh.getPoint( face.template getSubentityIndex< 0 >( i ) );
            const auto& v2 = mesh.getPoint( face.template getSubentityIndex< 0 >( j ) );
            // Partition polyhedron into tetrahedrons by triangulating faces and connecting each triangle to one point of the polyhedron.
            volume += getTetrahedronVolume( v3 - v0, v2 - v0, v1 - v0 );
        }
    }
    return volume;
}

} // namespace Meshes
+415 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@

#include <TNL/Meshes/Geometry/getEntityMeasure.h>
#include <TNL/Meshes/Geometry/isPlanar.h>
#include <TNL/Meshes/Geometry/getDecomposedMesh.h>

#include <TNL/Meshes/Writers/VTKWriter.h>

namespace MeshGeometryTest {

@@ -452,6 +455,418 @@ TEST( MeshGeometryTest, Polygon3DIsPlanarTest )
   EXPECT_EQ( isPlanar( mesh, mesh.template getEntity< 2 >( 5 ), 1e-4 ), false );
}

TEST( MeshGeometryTest, PolygonDecompositionTest )
{
   using PolygonTestMesh = Mesh< TestPolygon2DMeshConfig >;
   using PolygonMeshEntityType = MeshEntity< TestPolygon2DMeshConfig, Devices::Host, Topologies::Polygon >;
   using VertexMeshEntityType = typename PolygonMeshEntityType::SubentityTraits< 0 >::SubentityType;
   using PointType = typename VertexMeshEntityType::PointType;

   PolygonTestMesh mesh;
   MeshBuilder< PolygonTestMesh > meshBuilder;

   meshBuilder.setPointsCount( 16 );
   meshBuilder.setPoint(  0, PointType( 0.250, 0.150 ) );
   meshBuilder.setPoint(  1, PointType( 0.150, 0.250 ) );
   meshBuilder.setPoint(  2, PointType( 0.900, 0.500 ) );
   meshBuilder.setPoint(  3, PointType( 0.750, 0.275 ) );
   meshBuilder.setPoint(  4, PointType( 0.500, 0.900 ) );
   meshBuilder.setPoint(  5, PointType( 0.275, 0.750 ) );
   meshBuilder.setPoint(  6, PointType( 0.000, 0.250 ) );
   meshBuilder.setPoint(  7, PointType( 0.250, 0.000 ) );
   meshBuilder.setPoint(  8, PointType( 0.000, 0.000 ) );
   meshBuilder.setPoint(  9, PointType( 0.750, 0.000 ) );
   meshBuilder.setPoint( 10, PointType( 0.000, 0.750 ) );
   meshBuilder.setPoint( 11, PointType( 1.000, 0.500 ) );
   meshBuilder.setPoint( 12, PointType( 1.000, 0.000 ) );
   meshBuilder.setPoint( 13, PointType( 0.500, 1.000 ) );
   meshBuilder.setPoint( 14, PointType( 1.000, 1.000 ) );
   meshBuilder.setPoint( 15, PointType( 0.000, 1.000 ) );

   /****
    * Setup the following polygons:
    *
    *   1     0     3     2     4     5
    *   8     7     0     1     6
    *   9     3     0     7
    *   6     1     5    10
    *  12    11     2     3     9
    *  13     4     2    11    14
    *  10     5     4    13    15
    */

   meshBuilder.setCellsCount( 7 );
   
   //   1     0     3     2     4     5
   meshBuilder.getCellSeed( 0 ).setCornersCount( 6 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 0,  1 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 1,  0 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 2,  3 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 3,  2 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 4,  4 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 5,  5 );

   //   8     7     0     1     6
   meshBuilder.getCellSeed( 1 ).setCornersCount( 5 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 0,  8 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 1,  7 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 2,  0 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 3,  1 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 4,  6 );

   //   9     3     0     7
   meshBuilder.getCellSeed( 2 ).setCornersCount( 4 );
   meshBuilder.getCellSeed( 2 ).setCornerId( 0,  9 );
   meshBuilder.getCellSeed( 2 ).setCornerId( 1,  3 );
   meshBuilder.getCellSeed( 2 ).setCornerId( 2,  0 );
   meshBuilder.getCellSeed( 2 ).setCornerId( 3,  7 );

   //   6     1     5    10
   meshBuilder.getCellSeed( 3 ).setCornersCount( 4 );
   meshBuilder.getCellSeed( 3 ).setCornerId( 0,  6 );
   meshBuilder.getCellSeed( 3 ).setCornerId( 1,  1 );
   meshBuilder.getCellSeed( 3 ).setCornerId( 2,  5 );
   meshBuilder.getCellSeed( 3 ).setCornerId( 3, 10 );

   //  12    11     2     3     9
   meshBuilder.getCellSeed( 4 ).setCornersCount( 5 );
   meshBuilder.getCellSeed( 4 ).setCornerId( 0, 12 );
   meshBuilder.getCellSeed( 4 ).setCornerId( 1, 11 );
   meshBuilder.getCellSeed( 4 ).setCornerId( 2,  2 );
   meshBuilder.getCellSeed( 4 ).setCornerId( 3,  3 );
   meshBuilder.getCellSeed( 4 ).setCornerId( 4,  9 );

   //  13     4     2    11    14
   meshBuilder.getCellSeed( 5 ).setCornersCount( 5 );
   meshBuilder.getCellSeed( 5 ).setCornerId( 0, 13 );
   meshBuilder.getCellSeed( 5 ).setCornerId( 1,  4 );
   meshBuilder.getCellSeed( 5 ).setCornerId( 2,  2 );
   meshBuilder.getCellSeed( 5 ).setCornerId( 3, 11 );
   meshBuilder.getCellSeed( 5 ).setCornerId( 4, 14 );
   
   //  10     5     4    13    15
   meshBuilder.getCellSeed( 6 ).setCornersCount( 5 );
   meshBuilder.getCellSeed( 6 ).setCornerId( 0, 10 );
   meshBuilder.getCellSeed( 6 ).setCornerId( 1,  5 );
   meshBuilder.getCellSeed( 6 ).setCornerId( 2,  4 );
   meshBuilder.getCellSeed( 6 ).setCornerId( 3, 13 );
   meshBuilder.getCellSeed( 6 ).setCornerId( 4, 15 );
   
   ASSERT_TRUE( meshBuilder.build( mesh ) );

   // Write original mesh
   {
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( mesh ) >;
      std::ofstream file( "polygonTest_orig.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( mesh );
   }

   // Write decomposed mesh using 1st version
   {
      auto triangleMesh = getDecomposedMesh< GetTriangleMeshVersion::V1 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( triangleMesh ) >;
      std::ofstream file( "polygonTest_v1.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( triangleMesh );
   }

   // Write decomposed mesh using 2nd version
   {
      auto triangleMesh = getDecomposedMesh< GetTriangleMeshVersion::V2 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( triangleMesh ) >;
      std::ofstream file( "polygonTest_v2.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( triangleMesh );
   }
}

TEST( MeshGeometryTest, PolyhedronDecompositionTest )
{
   using PolyhedronTestMesh = Mesh< TestPolyhedronMeshConfig >;
   using PolyhedronMeshEntityType = MeshEntity< TestPolyhedronMeshConfig, Devices::Host, Topologies::Polyhedron >;
   using VertexMeshEntityType = typename PolyhedronMeshEntityType::SubentityTraits< 0 >::SubentityType;
   using PointType = typename VertexMeshEntityType::PointType;

   PointType point0 ( -1.25000, 1.16650, 1.20300 ),
             point1 ( -1.20683, 1.16951, 1.20537 ),
             point2 ( -1.16843, 1.19337, 1.17878 ),
             point3 ( -1.21025, 1.21901, 1.15383 ),
             point4 ( -1.25000, 1.21280, 1.15670 ),
             point5 ( -1.20816, 1.25000, 1.16756 ),
             point6 ( -1.25000, 1.25000, 1.18056 ),
             point7 ( -1.14802, 1.21553, 1.21165 ),
             point8 ( -1.16186, 1.25000, 1.21385 ),
             point9 ( -1.20307, 1.17486, 1.25000 ),
             point10( -1.25000, 1.18056, 1.25000 ),
             point11( -1.15677, 1.22115, 1.25000 ),
             point12( -1.18056, 1.25000, 1.25000 ),
             point13( -1.25000, 1.25000, 1.25000 ),
             point14( -1.09277, 1.20806, 1.19263 ),
             point15( -1.07219, 1.22167, 1.17994 ),
             point16( -1.07215, 1.25000, 1.18679 ),
             point17( -1.05697, 1.21124, 1.19697 ),
             point18( -1.04607, 1.21508, 1.22076 ),
             point19( -1.02140, 1.25000, 1.22293 ),
             point20( -1.06418, 1.22115, 1.25000 ),
             point21( -1.04167, 1.25000, 1.25000 );

   PolyhedronTestMesh mesh;
   MeshBuilder< PolyhedronTestMesh > meshBuilder;

   meshBuilder.setPointsCount( 22 );
   meshBuilder.setPoint(  0, point0  );
   meshBuilder.setPoint(  1, point1  );
   meshBuilder.setPoint(  2, point2  );
   meshBuilder.setPoint(  3, point3  );
   meshBuilder.setPoint(  4, point4  );
   meshBuilder.setPoint(  5, point5  );
   meshBuilder.setPoint(  6, point6  );
   meshBuilder.setPoint(  7, point7  );
   meshBuilder.setPoint(  8, point8  );
   meshBuilder.setPoint(  9, point9  );
   meshBuilder.setPoint( 10, point10 );
   meshBuilder.setPoint( 11, point11 );
   meshBuilder.setPoint( 12, point12 );
   meshBuilder.setPoint( 13, point13 );
   meshBuilder.setPoint( 14, point14 );
   meshBuilder.setPoint( 15, point15 );
   meshBuilder.setPoint( 16, point16 );
   meshBuilder.setPoint( 17, point17 );
   meshBuilder.setPoint( 18, point18 );
   meshBuilder.setPoint( 19, point19 );
   meshBuilder.setPoint( 20, point20 );
   meshBuilder.setPoint( 21, point21 );

   /****
    * Setup the following faces (polygons):
    *
    *   0     1     2     3     4
    *   4     3     5     6
    *   5     3     2     7     8
    *   9     1     0    10
    *  11     7     2     1     9
    *   8     7    11    12
    *  13    12    11     9    10
    *  13    10     0     4     6
    *  13     6     5     8    12
    *   8     7    14    15    16
    *  16    15    17    18    19
    *  20    18    17    14     7    11
    *  17    15    14
    *  21    19    18    20
    *  21    20    11    12
    *  12     8    16    19    21
    * 
    * NOTE: indeces refer to the points
    */

   meshBuilder.setFacesCount( 16 );

   //   0     1     2     3     4
   meshBuilder.getFaceSeed( 0 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 0 ).setCornerId( 0, 0 );
   meshBuilder.getFaceSeed( 0 ).setCornerId( 1, 1 );
   meshBuilder.getFaceSeed( 0 ).setCornerId( 2, 2 );
   meshBuilder.getFaceSeed( 0 ).setCornerId( 3, 3 );
   meshBuilder.getFaceSeed( 0 ).setCornerId( 4, 4 );
   
   //   4     3     5     6
   meshBuilder.getFaceSeed( 1 ).setCornersCount( 4 );
   meshBuilder.getFaceSeed( 1 ).setCornerId( 0, 4 );
   meshBuilder.getFaceSeed( 1 ).setCornerId( 1, 3 );
   meshBuilder.getFaceSeed( 1 ).setCornerId( 2, 5 );
   meshBuilder.getFaceSeed( 1 ).setCornerId( 3, 6 );

   //   5     3     2     7     8
   meshBuilder.getFaceSeed( 2 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 2 ).setCornerId( 0, 5 );
   meshBuilder.getFaceSeed( 2 ).setCornerId( 1, 3 );
   meshBuilder.getFaceSeed( 2 ).setCornerId( 2, 2 );
   meshBuilder.getFaceSeed( 2 ).setCornerId( 3, 7 );
   meshBuilder.getFaceSeed( 2 ).setCornerId( 4, 8 );
   
   //   9     1     0    10
   meshBuilder.getFaceSeed( 3 ).setCornersCount( 4 );
   meshBuilder.getFaceSeed( 3 ).setCornerId( 0, 9 );
   meshBuilder.getFaceSeed( 3 ).setCornerId( 1, 1 );
   meshBuilder.getFaceSeed( 3 ).setCornerId( 2, 0 );
   meshBuilder.getFaceSeed( 3 ).setCornerId( 3, 10 );

   //  11     7     2     1     9
   meshBuilder.getFaceSeed( 4 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 4 ).setCornerId( 0, 11 );
   meshBuilder.getFaceSeed( 4 ).setCornerId( 1, 7 );
   meshBuilder.getFaceSeed( 4 ).setCornerId( 2, 2 );
   meshBuilder.getFaceSeed( 4 ).setCornerId( 3, 1 );
   meshBuilder.getFaceSeed( 4 ).setCornerId( 4, 9 );

   //   8     7    11    12
   meshBuilder.getFaceSeed( 5 ).setCornersCount( 4 );
   meshBuilder.getFaceSeed( 5 ).setCornerId( 0, 8 );
   meshBuilder.getFaceSeed( 5 ).setCornerId( 1, 7 );
   meshBuilder.getFaceSeed( 5 ).setCornerId( 2, 11 );
   meshBuilder.getFaceSeed( 5 ).setCornerId( 3, 12 );

   //  13    12    11     9    10
   meshBuilder.getFaceSeed( 6 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 6 ).setCornerId( 0, 13 );
   meshBuilder.getFaceSeed( 6 ).setCornerId( 1, 12 );
   meshBuilder.getFaceSeed( 6 ).setCornerId( 2, 11 );
   meshBuilder.getFaceSeed( 6 ).setCornerId( 3, 9 );
   meshBuilder.getFaceSeed( 6 ).setCornerId( 4, 10 );

   //  13    10     0     4     6
   meshBuilder.getFaceSeed( 7 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 7 ).setCornerId( 0, 13 );
   meshBuilder.getFaceSeed( 7 ).setCornerId( 1, 10 );
   meshBuilder.getFaceSeed( 7 ).setCornerId( 2, 0 );
   meshBuilder.getFaceSeed( 7 ).setCornerId( 3, 4 );
   meshBuilder.getFaceSeed( 7 ).setCornerId( 4, 6 );

   //  13     6     5     8    12
   meshBuilder.getFaceSeed( 8 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 8 ).setCornerId( 0, 13 );
   meshBuilder.getFaceSeed( 8 ).setCornerId( 1, 6 );
   meshBuilder.getFaceSeed( 8 ).setCornerId( 2, 5 );
   meshBuilder.getFaceSeed( 8 ).setCornerId( 3, 8 );
   meshBuilder.getFaceSeed( 8 ).setCornerId( 4, 12 );

   //   8     7    14    15    16
   meshBuilder.getFaceSeed( 9 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 9 ).setCornerId( 0, 8 );
   meshBuilder.getFaceSeed( 9 ).setCornerId( 1, 7 );
   meshBuilder.getFaceSeed( 9 ).setCornerId( 2, 14 );
   meshBuilder.getFaceSeed( 9 ).setCornerId( 3, 15 );
   meshBuilder.getFaceSeed( 9 ).setCornerId( 4, 16 );

   //  16    15    17    18    19
   meshBuilder.getFaceSeed( 10 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 10 ).setCornerId( 0, 16 );
   meshBuilder.getFaceSeed( 10 ).setCornerId( 1, 15 );
   meshBuilder.getFaceSeed( 10 ).setCornerId( 2, 17 );
   meshBuilder.getFaceSeed( 10 ).setCornerId( 3, 18 );
   meshBuilder.getFaceSeed( 10 ).setCornerId( 4, 19 );

   //  20    18    17    14     7    11
   meshBuilder.getFaceSeed( 11 ).setCornersCount( 6 );
   meshBuilder.getFaceSeed( 11 ).setCornerId( 0, 20 );
   meshBuilder.getFaceSeed( 11 ).setCornerId( 1, 18 );
   meshBuilder.getFaceSeed( 11 ).setCornerId( 2, 17 );
   meshBuilder.getFaceSeed( 11 ).setCornerId( 3, 14 );
   meshBuilder.getFaceSeed( 11 ).setCornerId( 4, 7 );
   meshBuilder.getFaceSeed( 11 ).setCornerId( 5, 11 );

   //  17    15    14
   meshBuilder.getFaceSeed( 12 ).setCornersCount( 3 );
   meshBuilder.getFaceSeed( 12 ).setCornerId( 0, 17 );
   meshBuilder.getFaceSeed( 12 ).setCornerId( 1, 15 );
   meshBuilder.getFaceSeed( 12 ).setCornerId( 2, 14 );

   //  21    19    18    20
   meshBuilder.getFaceSeed( 13 ).setCornersCount( 4 );
   meshBuilder.getFaceSeed( 13 ).setCornerId( 0, 21 );
   meshBuilder.getFaceSeed( 13 ).setCornerId( 1, 19 );
   meshBuilder.getFaceSeed( 13 ).setCornerId( 2, 18 );
   meshBuilder.getFaceSeed( 13 ).setCornerId( 3, 20 );

   //  21    20    11    12
   meshBuilder.getFaceSeed( 14 ).setCornersCount( 4 );
   meshBuilder.getFaceSeed( 14 ).setCornerId( 0, 21 );
   meshBuilder.getFaceSeed( 14 ).setCornerId( 1, 20 );
   meshBuilder.getFaceSeed( 14 ).setCornerId( 2, 11 );
   meshBuilder.getFaceSeed( 14 ).setCornerId( 3, 12 );

   //  12     8    16    19    21
   meshBuilder.getFaceSeed( 15 ).setCornersCount( 5 );
   meshBuilder.getFaceSeed( 15 ).setCornerId( 0, 12 );
   meshBuilder.getFaceSeed( 15 ).setCornerId( 1, 8 );
   meshBuilder.getFaceSeed( 15 ).setCornerId( 2, 16 );
   meshBuilder.getFaceSeed( 15 ).setCornerId( 3, 19 );
   meshBuilder.getFaceSeed( 15 ).setCornerId( 4, 21 );

   /****
    * Setup the following cells (polyhedrons):
    *
    *   0     1     2     3     4     5      6     7     8
    *   9    10    11    12    13     5     14    15
    * 
    * NOTE: indeces refer to the faces
    */

   meshBuilder.setCellsCount( 2 );

   //   0     1     2     3     4     5      6     7     8
   meshBuilder.getCellSeed( 0 ).setCornersCount( 9 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 3, 3 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 4, 4 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 5, 5 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 6, 6 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 7, 7 );
   meshBuilder.getCellSeed( 0 ).setCornerId( 8, 8 );

   //   9    10    11    12    13     5     14    15
   meshBuilder.getCellSeed( 1 ).setCornersCount( 8 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 0, 9 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 1, 10 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 2, 11 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 3, 12 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 4, 13 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 5, 5 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 6, 14 );
   meshBuilder.getCellSeed( 1 ).setCornerId( 7, 15 );

   ASSERT_TRUE( meshBuilder.build( mesh ) );
   
   // Write decomposed mesh using 1st version
   {
      auto tetrahedronMesh = getDecomposedMesh< GetTetrahedronMeshVersion::V1 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( tetrahedronMesh ) >;
      std::ofstream file( "polyhedronTest_v1.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( tetrahedronMesh );
   }
   
   // Write decomposed mesh using 2nd version
   {
      auto tetrahedronMesh = getDecomposedMesh< GetTetrahedronMeshVersion::V2 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( tetrahedronMesh ) >;
      std::ofstream file( "polyhedronTest_v2.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( tetrahedronMesh );
   }

   // Write decomposed mesh using 3rd version
   {
      auto tetrahedronMesh = getDecomposedMesh< GetTetrahedronMeshVersion::V3 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( tetrahedronMesh ) >;
      std::ofstream file( "polyhedronTest_v3.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( tetrahedronMesh );
   }

   // Write decomposed mesh using 4th version
   {
      auto tetrahedronMesh = getDecomposedMesh< GetTetrahedronMeshVersion::V4 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( tetrahedronMesh ) >;
      std::ofstream file( "polyhedronTest_v4.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( tetrahedronMesh );
   }

   // Write decomposed mesh using 5th version
   {
      auto tetrahedronMesh = getDecomposedMesh< GetTetrahedronMeshVersion::V5 >( mesh );
      using VTKWriter = Meshes::Writers::VTKWriter< decltype( tetrahedronMesh ) >;
      std::ofstream file( "polyhedronTest_v5.vtk" );
      VTKWriter writer( file, VTK::FileFormat::ascii );
      writer.template writeEntities( tetrahedronMesh );
   }
}

} // namespace MeshTest

#endif