Official git repository: https://gitlab.com/Marc--Olivier/DataVisualization
The data visualization
project is a small project whose current goal is to display
4D data using isosurfaces. The project contains an implementation of the
marching cubes algorithm
to compute these isosurfaces.
The project is composed of the following modules:
third-parties
defines rules to download and compile some dependencies ( catch2, googletest, google/benchmark), and some small wrappers on top of them.utils
contains cache friendly data structures for tiny containers.marching-cubes
contains the classes that implement the marching cubes algorithm.gui
defines a simple Graphical User Interface that can display isosurfaces for either the function f(x,y,z)=x²+y²+z², or a DICOM file of your choice. To perform these tasks, the module depends on the libraries Qt5 and DCMTK that you must install separately.
Note that the gui
module mainly contains code I wrote in 2010 using Qt4. Although I updated
some parts of the code, some other parts require more work, especially the class
MCubesRenderer that displays the triangles using OpenGL,
or DicomReader that reads DICOM files. Actually, my plan
is rather to get rid of the gui
module at some point (after having extracted
DicomReader into a different module), and compile the code to
WebAssembly: would it not be convenient if you could visualise
your DICOM data in a web browser?
To build the whole project, you need to install the following components and libraries:
- CMake, version 3.8 or higher
- Ninja, if you want a build system much faster than Make
- DCMTK
- Qt5, preferrably a recent version (I use Qt 5.11.1)
Then, execute the following commands:
git clone https://gitlab.com/Marc--Olivier/DataVisualization.git
cd DataVisualization
mkdir -p build/release
cd build/release
QT5_PATH=<path-to-your-installation-of-Qt5>
DCMTK_PATH=<path-to-your-installation-of-DCMTK>
# The following command will take some time:
# it downloads and compiles catch2, google-test and google/benchmark
cmake -G Ninja ../.. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$QT5_PATH;$DCMTK_PATH"
ninja
ninja test
# To run the application:
./gui/datavisualization
# Or ./gui/datavisualization.app/Contents/MacOS/datavisualization
# if you are using macos.
So far, I only tested on macos with clang 6.0.0
and
Apple LLVM version 10.0.0 (clang-1000.11.45.2)
.
One of my next step is to compile the code with (at least) gcc.
The goal of the marching cubes algorithm is to approximate the isosurface for a value viso of a function f(x,y,z). This approximated isosurface is composed of triangles.
The algorithm first breaks down the domain (x, y, z) of the function f(x,y,z) into cubes.
Figure 1: Decomposing the domain into cubes
Then, for each, the algorithm calculates a set of triangles that approximate the isosurface within the cube. Each vertex of one of these triangles is located on an edge of the cube. The number of triangles require to approximate the isosurface, and the edges where the vertices of these triangles are located, are determined by the sign of f(Vi) - viso at each cube vertex Vi. The set of signs sign(Vi) = (f(Vi) - viso ≥ 0) for a cube is called the cube configuration.
Figure 2: Triangle approximation of the isosurface within a cube
Figure 2 shows an example of one triangle approximating the isosurface within a cube
that has the configuration + - + + + + + +
.
Since V1 is the only 'negative' vertex of the cube, the vertices of this triangle
are on the edges connected to V1.
The exact positions of the intersection points depend on the value of f
at the vertices V0, V1, V3 and V5:
a linear interpolation is performed to calculate these exact positions.
The class marchingcubes::MarchingCubes is the entry point of the code that calculates the approximating triangles.
If cubeconfig is a cube configuration, the cube configuration flippedcubeconfiguration obtained by flipping each sign of cubeconfig produces the same set of triangles as cubeconfig. These are the only cube configurations that produce the same sets of triangles. Therefore, there are 28 / 2 = 128 different set of triangles. However, we don't need to implement the set of triangles for each of these 128 configurations, but we can calculate them from 15 base configurations described on Wikipedia by applying well chosen symmetries to these base configurations:
Figure 3: The originally published 15 cube configurations
from Wikipedia
Actually, generating the set of triangles for each cube configuration is not very expensive, but this should be rather done before the algorithm starts to loop over all the cubes. marchingcubes::MarchingCubes uses the class marchingcubes::ConfigsGenerator to create a marchingcubes::AllConfigs object that contains the set of triangles for each cube configuration.
- Add CI jobs that compile the code and run the tests using different compilers.
- Add support for
gcc
. - Compile the code to WebAssembly (except the
gui
module). This especially requires to compile the libraryDCMTK
to WebAssembly, library that depends on other libraries...
Issue https://gitlab.com/gitlab-org/gitlab-ce/issues/17276
I converted the svg images using Inkscape (see https://mijingo.com/blog/exporting-svg-from-the-command-line-with-inkscape.):
/Applications/Inkscape.app/Contents/Resources/bin/inkscape \
-z `pwd`/doc/images/grid.svg -e `pwd`/doc/images/grid.png
/Applications/Inkscape.app/Contents/Resources/bin/inkscape \
-z `pwd`/doc/images/cube_approximating_triangles.svg \
-e `pwd`/doc/images/cube_approximating_triangles.png
- On Medical Image Samples, you can open the ones from the Multiple frames section:
- DICOM images on Visus that can't be loaded yet. I have to investigate the issue.
- Collections mentioned on DCMTK website