Truncation

The function of this code is to create a lung geometry that has been labeled for generation and pressure boundaries.  To achieve this, the program uses the two output files of the Gulkiz Amira script:  an unlabeled lung geometry in stereolithography file format (stl) and and skeleton data file (dat) composed of those airways centerlines, generation numbers, and airway radii.  This script uses the values found in the skeleton file and modifies them per user specifications to output the desired geometry in stl file format containing labeled airway generations and pressure boundary outlets at the stop generation.

How it works

The keys for labeling generations and creating pressure boundaries are found in the skeleton data file.  This file contains the values for points along the centerlines for the individual airways as well as their generation number and average radius.  A typical user input file is featured below and these exact specifications will be used later in the tutorial.

> more truncation.txt

3 2

0 0.9 1.5

1 0.9 1.5

2 0.9 2

In every line after the first, there are 3 values.  The first must be an integer and represents the generation that the next two values will affect.  The second value defines the fractional length of the airway that the generation will be truncated at relative to the centerline as defined in the skeleton; 1.0 would be endpoint for the skeleton centerline, and 0.5 would be the middle.  These values will vary by individual physiology, and generation depending on the relative locations of the start of the bifurcation to the end of the airway centerline.  The most common need for this value is to reduce it further when the generation being truncated has a very short length paired with a relatively larger radius, otherwise the generation after this will look like a “V” or worse a “\ /” rather than a “Y.”  At this truncation point, a flat plane is created to find the edges of the lung geometry that span the boundary between generations.  In every generation before the stop generation, these faces are kept unchanged and left as part of the generation they originally served as a boundary barrier.  A generation by generation animation of generation labeling can be viewed here.   In the stop generation however, these faces are cleaved at the boundary plane and more triangular faces are created by using the vertices on their edges that touched the boundary plane and the remaining vertices that were positioned before the boundary plane.  These newly created vertices are then used to create a series of triangular faces linking them to the user defined endpoint of the centerline which will inherently be on the boundary plane, assuring that all of the newly created faces will also reside on the boundary plane.  Below is a sample pressure output.

001

However as this boundary plane is an infinite plane, faces on other airways will also span the boundary plane and must be ignored when deleting and creating boundary faces.  This is achieved with the third value which is used to correct for closely positioned airways when finding the faces that will create the boundary between two generations.  This value is multiplied against the airway’s radius to limit the number of faces that our labeled as possible boundary faces.  This section of the code is designed to find a series of faces that border two other faces, that border two other faces, etcetera…, and the ring of connected faces that is found is what the generational boundary is set to.  If this value is too large than other false rings can be created where the plane passes through other airways; and if the value is too small, then the desired ring might not be found as airway cross-sections can become fairly elliptical

Tutorial for stlwrite.c

First if the code has not been compiled to an executable, do that now:

> gcc stlwrite.c -o stlwrite.exe -lm

This program truncates a stereolithography (stl) file using its associated airway centerline skeleton data file, so these files need be in the same directory as your executable and labeled Lung.stl and Lung_skeleton.dat respectively. The third file needed is truncation.txt and it follows a simple format, which is sampled below:

> more truncation.txt

3 2

0 0.9 1.5

1 0.9 1.5

2 0.9 2

The first line contains 2 integers: the first is the stop generation that will be used to set the final boundary, and the second is a variable “boundaryerror” that can be set to 2 for a standard run, or 1 or 0 for troubleshooting modes. It is important to note that the generation numbering is setup with the trachea representing the 0th generation, so setting it to 3 as seen above will result in generations 0, 1, and 2 being output. Also note that setting boundaryerror=2 will tell the program to output generations 0 to 2 and planar pressure boundary set at the start of generation 3. If boundaryerror=1 was set instead, the program will run identically as before except in the stl output that the faces adjacent to the final boundary will be marked as the boundary and not the last generation. Setting boundaryerror=0 will be very similar to the previous case except that no boundary or pressure faces will be output; only the generations desired.

Save the above to truncation.txt and run the executable:

> ./stlwrite.exe

Note that if this script is run again, it will overwrite the previous files, so your outputted test.stl will not be saved unless you rename or move it between runs. Modify the boundaryerror mode defined in truncation.txt to 1 and rename test.stl to test_be2.stl before running the executable again; repeat this again by renaming the previous output to test_be1.stl and setting boundarerror mode to 0. Rename this final output to test_be0.stl. Open software capable of viewing a stl (such as Icem, Harpoon, Ensight, or Paraview) and compare the differences between files. Below are screenshots of selected pressure boundaries that were created while using the above truncation.txt and having boundary error set to 2, 1, and 0 respectively.

001

boundaryerror=2

001

boundaryerror=1

001

boundaryerror=0

Panning out further, an overlay of the stl generated by setting boundaryerror=1 above can be seen, along with an image of it overlayed the original lung stl file, and a further panned out view of that.

001

just boundaryerror=1

001

boundaryerror=1 overlayed on original lung stl

001

further panned out view of boundaryerror=1 overlayed on original lung stl