Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 76 additions & 18 deletions vmtkScripts/vmtksurfaceendclipper.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
## Note: this class was contributed by
## Simone Manini
## Orobix Srl
## And adapted and modified by
## Kurt Sansom

from __future__ import absolute_import #NEEDS TO STAY AS TOP LEVEL MODULE FOR Py2-3 COMPATIBILITY
import vtk
Expand All @@ -32,6 +34,7 @@ class vmtkSeedSelector(object):
def __init__(self):
self._Surface = None
self._SeedIds = None
self._MainBodySeedIds = vtk.vtkIdList()
self._SourceSeedIds = vtk.vtkIdList()
self._TargetSeedIds = vtk.vtkIdList()
self.PrintError = None
Expand All @@ -42,9 +45,13 @@ def __init__(self):

def SetSurface(self,surface):
self._Surface = surface

def GetSurface(self):
return self._Surface

def GetMainBodySeedIds(self):
return self._MainBodySeedIds

def GetSourceSeedIds(self):
return self._SourceSeedIds

Expand All @@ -63,6 +70,7 @@ def __init__(self):
self.vmtkRenderer = None
self.OwnRenderer = 0
self.Script = None
self.SetOutlets = 0

def UndoCallback(self, obj):
self.InitializeSeeds()
Expand Down Expand Up @@ -105,6 +113,7 @@ def Execute(self):
self.PrintError('vmtkPickPointSeedSelector Error: Surface not set.')
return

self._MainBodySeedIds.Initialize()
self._SourceSeedIds.Initialize()
self._TargetSeedIds.Initialize()

Expand Down Expand Up @@ -148,16 +157,29 @@ def Execute(self):
self.InitializeSeeds()
self.vmtkRenderer.Render()
any = self.PickedSeedIds.GetNumberOfIds()
self._SourceSeedIds.DeepCopy(self.PickedSeedIds)
self._MainBodySeedIds.DeepCopy(self.PickedSeedIds)

self.InputInfo('Please position the mouse and press space to add points at clip locations, \'u\' to undo\n')
if( self.SetOutlets ):
self.InputInfo('Please position the mouse and press space to add point on vessel wall near each Inlet location, \'u\' to undo\n')
else:
self.InputInfo('Please position the mouse and press space to add points at clip locations, \'u\' to undo\n')

any = 0
while any == 0:
self.InitializeSeeds()
self.vmtkRenderer.Render()
any = self.PickedSeedIds.GetNumberOfIds()
self._TargetSeedIds.DeepCopy(self.PickedSeedIds)
self._SourceSeedIds.DeepCopy(self.PickedSeedIds)

if(self.SetOutlets):
self.InputInfo('Please position the mouse and press space to add point on vessel wall near each Outlet location, \'u\' to undo\n')

any = 0
while any == 0:
self.InitializeSeeds()
self.vmtkRenderer.Render()
any = self.PickedSeedIds.GetNumberOfIds()
self._TargetSeedIds.DeepCopy(self.PickedSeedIds)

if self.OwnRenderer:
self.vmtkRenderer.Deallocate()
Expand All @@ -169,6 +191,10 @@ def __init__(self):

pypes.pypeScript.__init__(self)

self.Centerlines = None
self.CenterlineNormals = 0
self.FrenetTangentArrayName = 'FrenetTangent'

self.Surface = None
self.vmtkRenderer = None
self.OwnRenderer = 0
Expand All @@ -181,9 +207,16 @@ def __init__(self):
self.CleanOutput = 1

self.SetScriptName('vmtksurfaceendclipper')
self.SetScriptDoc('interactively clip a tubular surface with normals estimated at seed locations')
self.SetScriptDoc('interactively clip a tubular surface with normals estimated at seed locations. It is \
recomended that the option to clip based on centerlines normals is enabled to increase \
the accuracy of the clipping. If desired, a centerline containing the Frenet Tangent Array \
must be fed in along with the surface. This is generated by passing a centerline through the \
vmtkcenterlinegeometry script.')
self.SetInputMembers([
['Surface','i','vtkPolyData',1,'','the input surface','vmtksurfacereader'],
['CenterlineNormals','centerlinenormal','bool',1,'','toggle using centerline tangent for normal estimation'],
['Centerlines','centerlines','vtkPolyData',1,'','the input centerlines','vmtksurfacereader'],
['FrenetTangentArrayName','frenettangentarray','str',1,'','name of the array where centerline tangent vectors of the Frenet reference system are stored'],
['vmtkRenderer','renderer','vmtkRenderer',1,'','external renderer']
])
self.SetOutputMembers([
Expand All @@ -195,6 +228,9 @@ def Execute(self):
if self.Surface == None:
self.PrintError('Error: no Surface.')

if (self.CenterlineNormals) and (self.Centerlines == None):
self.PrintError('Error: No input centerlines.')

if not self.vmtkRenderer:
self.vmtkRenderer = vmtkrenderer.vmtkRenderer()
self.vmtkRenderer.Initialize()
Expand All @@ -204,6 +240,8 @@ def Execute(self):
self.SeedSelector.vmtkRenderer = self.vmtkRenderer
self.SeedSelector.Script = self

if (self.CenterlineNormals):
self.SeedSelector.SetOutlets = 1
self.SeedSelector.SetSurface(self.Surface)
self.SeedSelector.InputInfo = self.InputInfo
self.SeedSelector.InputText = self.InputText
Expand All @@ -212,11 +250,11 @@ def Execute(self):
self.SeedSelector.PrintLog = self.PrintLog
self.SeedSelector.Execute()

mainBodySeedIds = self.SeedSelector.GetSourceSeedIds()
mainBodySeedIds = self.SeedSelector.GetMainBodySeedIds()
mainBodySeedId = mainBodySeedIds.GetId(0)
mainBodyPoint = self.Surface.GetPoint(mainBodySeedId)

clipSeedIds = self.SeedSelector.GetTargetSeedIds()
clipSeedIds = self.SeedSelector.GetSourceSeedIds()

surfaceCleaner = vtk.vtkCleanPolyData()
surfaceCleaner.SetInputData(self.Surface)
Expand All @@ -230,25 +268,45 @@ def Execute(self):

clippedSurface = surfaceTriangulator.GetOutput()

n_seeds = clipSeedIds.GetNumberOfIds() # get the number of inlets
if (self.CenterlineNormals):
targetSeedIds = self.SeedSelector.GetTargetSeedIds()
for i in range(targetSeedIds.GetNumberOfIds()):
clipSeedIds.InsertNextId(targetSeedIds.GetId(i))
locator_ctr = vtk.vtkPointLocator()
locator_ctr.SetDataSet(self.Centerlines)
locator_ctr.BuildLocator()

for i in range(clipSeedIds.GetNumberOfIds()):

seedId = clipSeedIds.GetId(i)

locator = vtk.vtkPointLocator()
locator.SetDataSet(clippedSurface)
locator.BuildLocator()

seedPoint = self.Surface.GetPoint(seedId)
seedPointId = locator.FindClosestPoint(seedPoint)

planeEstimator = vtkvmtk.vtkvmtkPolyDataNormalPlaneEstimator()
planeEstimator.SetInputData(clippedSurface)
planeEstimator.SetOriginPointId(seedPointId)
planeEstimator.Update()
# the frenet tangent must be inverted as it is directed outwards
# the seam filter requires an inward facing normal
if (self.CenterlineNormals):
centerlinePointId = locator_ctr.FindClosestPoint(seedPoint)
origin = self.Centerlines.GetPoint(centerlinePointId)
normal = self.Centerlines.GetPointData().GetArray(self.FrenetTangentArrayName).GetTuple(centerlinePointId)
if( i >= n_seeds ):
# invert outward facing normals
normal = tuple( -p for p in normal)
else:
locator = vtk.vtkPointLocator()
locator.SetDataSet(clippedSurface)
locator.BuildLocator()
seedPointId = locator.FindClosestPoint(seedPoint)

planeEstimator = vtkvmtk.vtkvmtkPolyDataNormalPlaneEstimator()
planeEstimator.SetInputData(clippedSurface)
planeEstimator.SetOriginPointId(seedPointId)
planeEstimator.Update()
origin = planeEstimator.GetOrigin()
normal = planeEstimator.GetNormal()

plane = vtk.vtkPlane()
plane.SetOrigin(planeEstimator.GetOrigin())
plane.SetNormal(planeEstimator.GetNormal())
plane.SetOrigin(origin)
plane.SetNormal(normal)

seamFilter = vtkvmtk.vtkvmtkTopologicalSeamFilter()
seamFilter.SetInputData(clippedSurface)
Expand Down