iMSTK
Interactive Medical Simulation Toolkit
Docs/Extras/Filtering.md
1 # Filtering
2 
3 The filtering module in iMSTK provides classes that take one or more input geometries and produces one or more output geometries. General usage looks something like the following:
4 
5 ```cpp
6 // mesh1 and mesh2 are instances of SurfaceMesh
7 AppendMesh appendMesh;
8 appendMesh.setInput(mesh1, 0);
9 appendMesh.setInput(mesh2, 1);
10 appendMesh.update(); // Perform the append operation
11 
12 auto results = std::dynamic_pointer_cast<SurfaceMesh>(appendMesh->getOutput());
13 
14 // Often convenience methods are provide to cast for you
15 results = appendMesh->getOutputMesh();
16 ```
17 
18 This particular filter takes two input SurfaceMeshes and combines/appends them.
19 
20 This pattern can be applied to many geometric operations. Many filters wrap 3rd party APIs (such as VTK) to achieve an operation. A full list can be found in files [here](https://gitlab.kitware.com/iMSTK/iMSTK/-/tree/master/Source/Filtering).
21 
22 ## Signed Distance Field Generation
23 
24 To generate a signed distance field (SDF) one can use the `ImageDistanceTransform` or `SurfaceMeshDistanceTransform` operation. SDFs are very useful for collision.
25 
26 ### SurfaceMeshDistanceTransform
27 
28 `SurfaceMeshDistanceTransform` takes an input triangle mesh and produces an output `ImageData` that represents the signed distance field. This input `SurfaceMesh` must be closed. If having trouble with it, it is recommended to use `CleanMesh` before running to ensure duplicate vertices are resolved. One can also adjust the tolerance of the floating point calculation.
29 
30 ```
31 SurfaceMeshDistanceTransform computeSdf;
32 computeSdf.setInputMesh(dragonSurfMesh);
33 computeSdf.setDimensions(100, 100, 100);
34 computeSdf.update();
35 auto myImageData = computeSdf.getOutputImage();
36 ```
37 
38 One can also supply it the input mesh and perform individual nearest distance queries.
39 
40 ```
41 SurfaceMeshDistanceTransform computeSdf;
42 computeSdf.setInputMesh(dragonSurfMesh);
43 computeSdf.setupDistFunc();
44 Vec3d nearestPtToMyPoint = computeSdf.getNearestPoint(myPoint);
45 ```
46 
47 <p align="center">
48  <img src="../media/FemurSDF.png" alt="femur signed distance field"/>
49 </p>
50 
51 ## SurfaceMeshFlyingEdges
52 
53 This is our fastest isosurface extraction method when the entire isosurface is needed.
54 
55 ## LocalMarchingCubes
56 
57 Local marching cubes does marching cubes in chunks on a single ImageData. This requires no reordering of the ImageData in memory, and no special accessors. It produces N SurfaceMesh's, one for each chunk. The purpose of LocalMarchingCubes is to avoid remeshing the entire domain reducing computational cost.
58 
59 To properly divide an image the dimensions - 1 must be divisible by the number of chunks. So if you're image is 100, 100, 100. Then you need to use divisors of 99, 99, 99. If inputs provided is not a divisor it will choose the next divisor and warn.
60 
61 ```cpp
62 LocalMarchingCubes isoExtract;
63 isoExtract.setInputImage(inputImage);
64 isoExtract.setIsoValue(0.0);
65 isoExtract.setNumberOfChunks(Vec3i(32, 9, 9));
66 isoExtract.update();
67 
68 // Output given, some chunks may have no vertices
69 for (int i = 0; i < 39 * 9 * 9; i++)
70 {
71  isoExtract->getOutput(i);
72 }
73 ```
74 
75 Below shows the level set cutting method with chunked marching cubes.
76 
77 <p align="center">
78  <img src="../media/localmc.gif" alt="local marching cubes"/>
79 </p>
80 
81 ## LineMeshCut & SurfaceMeshCut
82 
83 These cutting methods produce division of a mesh given an input analytic geometry.
84 
85 ## CollisionDetectionAlgorithm
86 
87 All of the `CollisionDetectionAlgorithm`'s stem from `GeometryAlgorithm`.