1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
#!/usr/bin/env python
import sys
import math
import numpy
import vtk
from vmtk import pypes
from vmtk import vmtkscripts
vmtksurfaceextractinnercylinder = 'VmtkSurfaceExtractInnerCylinder'
class VmtkSurfaceExtractInnerCylinder(pypes.pypeScript):
def __init__(self):
pypes.pypeScript.__init__(self)
self.SetScriptName(vmtksurfaceextractinnercylinder)
self.SetScriptDoc('Extract inner surface from an annular-cylindric volume.')
# Define members
self.Surface = None
self.DoubleSurface = None
self.ColoredSurface = None
self.InnerSurface = None
self.CellEntityIdsArrayName = 'CellEntityIds'
self.EndcapsThresholdLow = 0
self.EndcapsThresholdHigh = 1
# Potential output values
self.InnerRegionId = None
# Member info: name, cmdlinename, typename, num, default, desc[, defaultpipetoscript]
self.SetInputMembers([
['Surface', 'i', 'vtkPolyData', 1, '',
'the input surface', 'vmtksurfacereader'],
['CellEntityIdsArrayName', 'entityidsarray', 'str', 1, '',
'name of the array where entity ids have been stored'],
['EndcapsThresholdLow', 'lowthreshold', 'int', 1, '',
'lower threshold for encaps filtering', ''],
['EndcapsThresholdHigh', 'highthreshold', 'int', 1, '',
'higher threshold for encaps filtering', ''],
])
self.SetOutputMembers([
['DoubleSurface', 'doublesurface', 'vtkPolyData', 1, '',
'the double surface without caps', 'vmtksurfacewriter'],
['ColoredSurface', 'coloredsurface', 'vtkPolyData', 1, '',
'the colored surface', 'vmtksurfacewriter'],
['InnerSurface', 'o', 'vtkPolyData', 1, '',
'the innermost surface', 'vmtksurfacewriter'],
['CellEntityIdsArrayName', 'entityidsarray', 'str', 1, '',
'name of the array where entity ids have been stored'],
])
def Execute(self):
if self.Surface == None:
self.PrintError('Error: No Surface.')
self.removeEndCaps()
self.colorSurfaceRegions()
self.extractInnerSurface()
def removeEndCaps(self):
self.PrintLog("Using thresholding to remove endcaps.")
th = vtk.vtkThreshold()
th.SetInput(self.Surface)
th.SetInputArrayToProcess(0, 0, 0, 1, self.CellEntityIdsArrayName)
th.ThresholdBetween(self.EndcapsThresholdLow, self.EndcapsThresholdHigh)
th.Update()
gf = vtk.vtkGeometryFilter()
gf.SetInput(th.GetOutput())
gf.Update()
self.DoubleSurface = gf.GetOutput()
def colorSurfaceRegions(self):
self.PrintLog("Coloring surface regions.")
connectivityFilter = vtk.vtkPolyDataConnectivityFilter()
connectivityFilter.SetInput(self.DoubleSurface)
connectivityFilter.ColorRegionsOn()
connectivityFilter.SetExtractionModeToAllRegions()
connectivityFilter.Update()
assert connectivityFilter.GetNumberOfExtractedRegions() == 2
self.ColoredSurface = connectivityFilter.GetOutput()
def extractInnerSurface(self):
self.PrintLog("Extracting inner surface.")
def bnorm(data):
bounds = data.GetBounds()
return math.sqrt(sum((bounds[2*i+1]-bounds[2*i])**2 for i in range(3)))
# Get bounds of entire surface
bounds_norm = bnorm(self.Surface)
# Currently assuming that this is the region numbers that were produced by coloring!
# TODO: If necessary, get from array to be more robust.
region_ids = (0, 1)
# Extract each surface in turn to find the smallest one
for k in region_ids:
connectivityFilter = vtk.vtkPolyDataConnectivityFilter()
connectivityFilter.SetInput(self.ColoredSurface)
connectivityFilter.SetExtractionModeToSpecifiedRegions()
connectivityFilter.AddSpecifiedRegion(k)
connectivityFilter.ColorRegionsOff()
connectivityFilter.SetScalarConnectivity(0)
connectivityFilter.Update()
subsurface = connectivityFilter.GetOutput()
# The inner surface has smaller bounds
if bnorm(subsurface) < bounds_norm - 1e-12:
self.InnerRegionId = k
self.InnerSurface = subsurface
break
assert self.InnerRegionId in region_ids
if __name__ == '__main__':
main = pypes.pypeMain()
main.Arguments = sys.argv
main.Execute()
|