5. Mesh Voxelisation#

5.1. Introduction#

3D polygon meshes are a common and memory efficient way to represent 3D objects for use in CAD software. However there exist other ways to represent objects in 3D space. One common method is known as voxelisation (commonly spelled voxelization). This involves representing the object as a grid of 3D pixels (voxels). The voxels can be assigned different values to represent a certain characteristic, for example a material type or temperature. The voxel grid can be visualised with the values assigned to a colour or greyscale. The voxels can be stored as a numerical array or as a series of 2D images (or a single virtual tiff stack in the case of CAD2Vox) with each image representing a slice along a particular axis.

VirtualLab integrates an internally developed python package called CAD2Vox that provides an interface for converting many different types of CAD mesh formats into a voxel-based representation in parallel. The calculations can be done either with threading on multi-core CPUs using OpenMP or on a Nvidia GPU using CUDA.

The CAD2Vox integration with VirtualLab allows us to run CAD2Vox as the final step in some analysis to generate a voxel representation of the CAD mesh that is generated by Salome. However, you can also use it standalone on any of the 30 or so mesh formats supported by meshio.

5.2. Prerequisites#

The examples provided here are mostly self-contained. However, in order to understand this tutorial, at a minimum you will need to have completed the first tutorial to obtain a grounding in how VirtualLab is setup. Also, although not strictly necessary, we also recommend completing the third tutorial because we will be using the Salome mesh generated from the HIVE analysis as part of one of the examples. All the other tutorials (that is tutorials 2 and 4) are useful but not required if your only interest is the voxelisation features.

5.3. Example 1: Running in an existing analysis workflow#

In this first example we will use the same analysis performed in Tutorial 1 using a dog-bone component in a tensile test.

Action

The RunFile RunTutorials.py should be set up as follows to run this simulation:

Simulation='Tensile'
Project='Tutorials'
Parameters_Master='TrainingParameters_Cad2Vox'
Parameters_Var=None

 VirtualLab=VLSetup(
            Simulation,
            Project
            )

 VirtualLab.Settings(
            Mode='Interactive',
            Launcher='Process',
            NbJobs=1
            )

 VirtualLab.Parameters(
            Parameters_Master,
            Parameters_Var,
            RunMesh=True,
            RunSim=True,
            RunVoxelise=True,
            RunDA=True
            )

 VirtualLab.Mesh(
            ShowMesh=False,
            MeshCheck=None
            )

 VirtualLab.Sim(
            RunPreAster=True,
            RunAster=True,
            RunPostAster=True,
            ShowRes=True
            )

 VirtualLab.DA()
 VirtualLab.Voxelise()

Launch VirtualLab using the following command:

VirtualLab -f RunFiles/RunTutorials.py

The main change to note in the Runfile is the call to VirtualLab.Voxelise(). This is the function that initiates the voxelisation using the parameters defined in Parameters_Master*`` and Parameters_Var. Additionally, within the Environment section, RunVoxelise is explicitly set to run with True in VirtualLab.Parameters. This isn’t technically necessary because the inclusion of VirtualLab.Voxelise() in the methods section means it is True by default, but explicitly stating this is good practice.

Looking at the file Input/Tensile/Tutorials/TrainingParameters_Cad2Vox.py you will notice that the Namespaces Mesh and Sim are setup the same as in the previous tutorial. That is, they generate the CAD geometry and mesh using Scripts/Experiments/Tensile/Mesh/DogBone.py and then run two simulations, first force controlled then displacement controlled. Also, since DA is not defined in Parameters_Master, no data analysis will take place.

You will also notice the Parameters file has a new Namespace Vox. This contains the parameters used to control the voxelisation. The file is setup with some sensible default values.

The only values that are strictly required are:

  • Vox.Name: Label for the CAD2Vox run(s), this can be anything you like. This doubles up as the name of the output file(s), therefore you probably want it to be something descriptive.

  • Vox.mesh: The name of the mesh(es) you wish to voxelise. These are assumed to be in the simulation Meshes directory, in this case Output/Tensile/Tutorials/Meshes/. The code also assumes a file extension of .med if none is given.

  • Vox.gridsize: Number of voxels in each dimension.

We have also included a few optional parameters:

  • Vox.cpu : The default behaviour is to first check for CUDA and a compatible GPU and if they cannot be found it will fall back to CPU. This flag allows us to skip the check and just use the CPU.

  • Vox.use_tetra: This tells CAD2Vox we are using a mesh with Tetrahedron data instead of the default Triangles.

There are also a number of options we have not used in this file. They are listed here for reference:

  • Vox.solid: Auto fill interior volume when using triangle (surface) data.

  • Vox.unit_length: You can use this instead of Vox.gridsize to define the length/width/height of a single cubic voxel in Mesh-space. CAD2Vox then automatically calculates the number of voxels in each dimension using the min and max of the mesh geometry. Hence you don’t specify gridsize when using this option.

  • Vox.greyscale_file: You can use this option to specify a custom name and path for the .csv file that contains materials and associated greyscale values. If the .csv file does not exist, the code will automatically generate a new file and populate it with values read from the mesh file. If this is not set the code defaults to the filename greyscale_{Vox.Name}.csv and assumes it’s in the simulation output directory (again automatically generating the .csv file if it does not exist).

  • Vox.Num_Threads: This sets the Number of OMP Threads to use for voxelisation (only needed for CPU). OpenMP by default automatically detects the number of CPUs on the system and uses the maximum it can. This setting allows you to change the number of threads if desired.

  • Vox.image_format: This option allows you to select the image format for the final output. If it is omitted (or set to None) the output defaults to a tiff virtual stack. However, when this option is set the code outputs each slice in z as a separate image in any format supported by Pillow (see the PILLOW docs for the full list). Simply specify the format you require as a string, e.g., Vox.image_format="png".

  • Vox.Orientation: This option allows you to quickly change the Orientation of the generated output. The default is “XY” but this can be any of “XY, “YZ” or “XZ”.

  • Vox.Output_Resolution : This option allows you to change the size of the final output. By default a bounding box is drawn tightly around the mesh with the exact size calculated using either unit_length or Gridsize. This option allows you to crop or pad with 0’s the final output images by specifying a list of 3 ints as [pix_X,pix_Y,number_of_images].

  • Vox.Nikon_file: You can use this option to the read the voxel unit length from a Nikon xtect file. This can either be the name of the file (including the file extension), if it is in the Input directory. or the absolute path to the file (again including the file extension).

Advanced tip

All these parameters work in the same manner as with Mesh and Sim. Whereby using lists in Parameters_Var will initiate multiple runs with different parameters.

With this in mind Vox.Gridsize accepts the value 0 to skip it when using in conjunction with Vox.unit_length and, conversely, Vox.unit_length accepts [0.0,0.0,0.0] for the reverse effect (i.e., skip it when using Vox.Gridsize).

This is useful if, for example, you wish to run two different cases one after the other. The first with a gridsize of 500 and a second with a unit length of 5.0. In that case you could set Vox.Gridsize=[[500,500,500],[0,0,0]] and Vox.unit_length=[[0.0,0.0,0.0],[5.0,5.0,5.0]] inside Parameters_Var to achieve this.

The output from the voxelisation can now be found under Output/Tensile/Tutorials/Voxel-Images/Notch1.tiff this can be viewed with appropriate software such as ImageJ, see Fig. 5.1.

In this folder you will also find the file greyscale_Notch1.csv. This file contains in csv format all the materials that were read from the mesh file and the corresponding 8-bit greyscale values used in the output images. We will go into this file in detail with the next example because it’s not really interesting in this case due to there only being one material, that is “Copper”. Hence, the entire dog-bone is coloured white (that is, the max greyscale value of 255 for an 8-bit dataset). Please note that the first column is the region name as read from the mesh file by CAD2Vox, in this case there is only one region. Therfore, you should see Un-Defined in the first column. See the next example for further details.

https://gitlab.com/ibsim/media/-/raw/master/images/docs/screenshots/ImageJ_01.png

Fig. 5.1 Slice from the tiff stack generated by CAD2Vox as visualised by ImageJ.#

Action

We encourage you to have play around with the various parameters set in the Vox Namespace.

Here are some Specific things you could do:

  • Try Increasing the value Vox.Gridsize from 200 to 500 or even 1000. How does this effect the quality of the image and the run-time?

  • Try swapping Vox.Gridsize with Vox.unit_length. What effect does this have?

  • Try changing the format of the output to jpeg using Vox.image_format

  • If you have CUDA installed and access to a GPU try using it to see how it effects the run time.

5.4. Example 2: Running CAD2Vox Standalone#

CAD2Vox can be run on an existing mesh file separate from any other analysis within VirtualLab. This may be useful if, for example, you have previously performed some long running simulation and now wish to voxelise the CAD mesh without having to needlessly repeat the work in Code_Aster.

For this example we will voxelise the AMAZE mesh that was previously generated from the HIVE analysis in tutorial 3. If you have previously completed exercise 3 the mesh should be located in Output/HIVE/Tutorials/Meshes/AMAZE_Sample.med. If you have not completed tutorial 3 you can either do so, or you can run the following command:

VirtualLab -f RunFiles/Tutorials/Mesh_Voxelisation/Task2_Pre-setup.py

This performs the meshing and a bare bones simulation (in non-interactive mode) to generate the necessary output files (which are used as inputs for this tutorial).

Action

The RunFile RunTutorials.py should be set up as follows to just perform the voxelisation:

Simulation='HIVE'
Project='Tutorials'
Parameters_Master='TrainingParameters_Cad2Vox'
Parameters_Var=None

VirtualLab=VLSetup(
           Simulation,
           Project
           )

VirtualLab.Settings(
           Mode='Interactive',
           Launcher='Process',
           NbThreads=1
           )

VirtualLab.Parameters(
           Parameters_Master,
           Parameters_Var,
           RunMesh=False,
           RunSim=False,
           RunDA=False
           )

     VirtualLab.Voxelise()

Launch VirtualLab using the following command:

VirtualLab -f RunFiles/RunTutorials.py

In this example you can see that we have turned off Salome and Code_Aster by setting RunMesh=False, RunSim=False, and RunDA=False. Therefore, only the voxelisation method will now take place.

Once again the file Input/HIVE/Tutorials/TrainingParameters_Cad2Vox.py is setup with some sensible default values using the Vox Namespace. The output from the voxelisation can be found in Output/HIVE/Tutorials/Voxel-Images/AMAZE_Sample.tiff.

Unlike the previous example this mesh has 3 regions representing 2 different materials, tungsten and copper (see Sim.Materials in training_parameters.py. In this case the regions are labelled as: Block Sample, Pipe Sample, and Sample Tile. These have been automatically read in from the mesh by CAD2Vox and each region has different greyscale values applied to make them visually distinct from one another.

The greyscale values used for each region can be seen in the file Output/HIVE/Tutorials/Voxel-Images/greyscale_AMAZE.csv. This file contains a simple csv table with 3 columns of data separated by commas. First is the region name, as read from the mesh file by CAD2Vox, second is the region index assigned by Salome, and the third is the greyscale value used in the output.

When first generated the greyscale values are evenly spread from 1 to 255 across all regions found, see Fig. 5.2. These can be changed in this file to whatever values you wish and will be read in on subsequent runs. You can also change the region names if desired. However, we do not recommend changing the region index as this is used internally by CAD2Vox to generate the voxel image slices and may produce unexpected results.

Unfortunately, Salome does not use the most descriptive names for each region of the mesh (it just uses the keys from Sim.Materials). Also, the mesh file may contain objects that Salome uses internally (e.g., planes for calculating force/displacment etc.) with no easy way of distinguishing them automatically from the material regions. Therefore, you may need to play around with the greyscale values of a small number of regions to work out what the labels refer to. You can then rename them to something more appropriate and set the greyscale for any region you don’t want to see in the final output to 0.

https://gitlab.com/ibsim/media/-/raw/master/images/docs/screenshots/ImageJ_02.png

Fig. 5.2 3D visualisation of the voxelised grid generated by CAD2Vox as visualised by ImageJ.#

Tip

If you wish to change where the greyscale file is located you can use the previously mentioned parameter Vox.greyscale_file to set a custom path, remembering to include the .csv extension. Also if you mess up the file and want to regenerate the greyscale file simply delete the greyscale_AMAZE.csv file (or move it to another location) and re-run CAD2Vox.

Tip

If you want to use a custom directory to store input meshes for standalone use, you can define Vox.mesh to be a string that is the absolute path to the mesh file you wish to use. However, you will need to ensure you include the .med file extension. On Windows, absolute paths usually start with C:\ (although, depending on your exact system, they can be any other drive letter) on MacOS and Linux they always start with /.

Action

As mentioned previously, the labels for the mesh regions are not the most useful. Therefore, here are some specific things you could try to rectify this:

  • rename each region in the greyscale file to better describe what it represents (e.g. changing “Pipe sample” to “Copper Pipe”).

  • Set the greyscale values so the regions are distinct from one another.

5.5. Example 3: Using non Salome med mesh files#

This example involves using mesh formats other than Salome med. CAD2Vox itself actually uses the python package meshio. to read in mesh data. This package officially supports more than 30 common mesh formats. Therefore, if you have your mesh geometry in another format there is a good chance CAD2Vox will work ‘out-of-the-box’.

There are however, 3 caveats to bear in mind:

  1. We have not tested every possible format. We know that .med, .stl, .ply, and .obj all work as expected. You are welcome to try other formats as they should work however, your results may vary.

  2. CAD2Vox can only work on meshes containing Triangles or Tetrahedrons. No other cell shapes are currently supported.

  3. Greyscale values from material data are only officially supported with .med since .obj, .ply and .stl meshes don’t contain material data. As such, for other mesh formats the greyscale is just set to white (255) for the entire mesh. You can change this value in greyscale_Welsh-Dragon.csv where you will find the “region” listed as “Undefined”.

With these in mind, using a different mesh format through VirtualLab is as simple as setting Vox.mesh to a string containing the name of the file you wish to use including the file extension. You can then place the mesh in the same default directory as you would for a .med mesh. Or, as discussed earlier, you can use the absolute path to the file, again including the extension.

For our example we will use the Welsh Dragon Model which was released by Bangor university, UK, for Eurographics 2011. The model can be downloaded from here. This file should be placed in Output/Examples/Dragon/Meshes .

Action

The RunFile RunTutorials.py should be set up as follows to perform the voxelisation:

Simulation='Examples'
Project='Dragon'
Parameters_Master='TrainingParameters_Dragon'
Parameters_Var=None

VirtualLab=VLSetup(
           Simulation,
           Project
           )

VirtualLab.Settings(
           Mode='Interactive',
           Launcher='Process',
           NbThreads=1
           )

VirtualLab.Parameters(
           Parameters_Master,
           Parameters_Var,
           RunMesh=False,
           RunSim=False,
           RunDA=False
           )

VirtualLab.Voxelise()

We can then once again launch VirtualLab using the following command:

VirtualLab -f RunFiles/RunTutorials.py

The output is located in Output/Examples/Dragon/Voxel-Images/Welsh-Dragon.Tiff. You may notice that, since this mesh only contains triangle data, the resulting voxel image only contains coloured voxels on the surface of the model, see Fig. 5.3. You will also notice that, much like the dog bone in example 1, the model surface defaults to white (greyscale value of 255). This is because .stl files contain no information on materials. Therefore, as such, the entire mesh is set to a single greyscale value. Once again you can change this value in greyscale_Welsh-Dragon.csv if desired.

https://gitlab.com/ibsim/media/-/raw/master/images/docs/screenshots/ImageJ_03.png

Fig. 5.3 3D visualisation of the voxelised grid generated by CAD2Vox as visualised by ImageJ.#

Auto-filling surface meshes

Because this final example uses a triangle mesh, one final thing you can try is changing the option Vox.solid to True. This will use a different algorithm to auto-fill the interior volume. This works well on this particular mesh. However, if you wish to use this on your own surface meshes you will need to be aware of a few caveats:

  1. The algorithm used is not robust. Therefore, depending on the geometry, it may work well but can sometimes leave holes in the mesh.

  2. The algorithm used is also much slower than the normal surface algorithm.

  3. In the current version of CAD2Vox materials are not implemented when using solid. This means that the voxels in the model will always have a greyscale value of 255. The code will also not generate a greyscale csv file and will simply ignore any that already exist.