Your problem might have been partly resolved with this branch of forked SlicerVMTK. The latter branch has a hard dependency on this extension that is awaiting approval for merge in the extension index.
Said branch is written to calculate arterial stenosis measurement by volume between 2 arbitrary points. It calculates volumes of an arterial wall and a lumen. In your case, you need the volume of a segment only, that of a nerve, it’s the same for Slicer, just a segment. You could have been using it for your requirements even though that branch requires a second surface that is drawn by above mentionned pending extension.
As for modifying Cross-section analysis module to allow volume measurements between points, it does not seem reasonable after second thought, because it would deface this module. Much is already implemented in this module already, and as the name suggests, it’s for ‘cross-section analysis’, and not volume analysis.
However, you may get a volume with this code. Adjust object names and point indices.
def clipBetweenPoints(centerlinePolyData, surfacePolyData, p1Index, p2Index, outputPolyData):
centerlinePoints = centerlinePolyData.GetPoints()
p1 = [ 0.0 ] * 3
p2 = [ 0.0 ] * 3
centerlinePoints.GetPoint(p1Index, p1)
centerlinePoints.GetPoint(p2Index, p2)
p1Neighbour = [ 0.0 ] * 3
p2Neighbour = [ 0.0 ] * 3
centerlinePoints.GetPoint(p1Index + 1, p1Neighbour)
centerlinePoints.GetPoint(p2Index - 1, p2Neighbour)
if p1Index > p2Index:
centerlinePoints.GetPoint(p1Index - 1, p1Neighbour)
centerlinePoints.GetPoint(p2Index + 1, p2Neighbour)
startNormal = [ 0.0 ] * 3
endNormal = [ 0.0 ] * 3
vtk.vtkMath().Subtract(p1Neighbour, p1, startNormal)
vtk.vtkMath().Subtract(p2Neighbour, p2, endNormal);
startPlane = vtk.vtkPlane()
startPlane.SetOrigin(p1)
startPlane.SetNormal(startNormal)
endPlane = vtk.vtkPlane()
endPlane.SetOrigin(p2)
endPlane.SetNormal(endNormal)
planes = vtk.vtkPlaneCollection()
planes.AddItem(startPlane)
planes.AddItem(endPlane)
clipper = vtk.vtkClipClosedSurface()
clipper.SetClippingPlanes(planes)
clipper.SetInputData(surfacePolyData)
clipper.Update()
triangleFilter = vtk.vtkTriangleFilter()
triangleFilter.SetInputConnection(clipper.GetOutputPort())
triangleFilter.Update()
outputPolyData.DeepCopy(triangleFilter.GetOutput())
segmentationNode = slicer.util.getNode("Segmentation")
segmentationNode.CreateClosedSurfaceRepresentation()
segmentSurface = vtk.vtkPolyData()
segmentationNode.GetClosedSurfaceRepresentation("Segment_1", segmentSurface)
centerlineNode = slicer.util.getNode("Centerline model")
centerlinePolyData = centerlineNode.GetPolyData()
clippedPolyData = vtk.vtkPolyData()
clipBetweenPoints(centerlinePolyData, segmentSurface, 10, 50, clippedPolyData)
mp = vtk.vtkMassProperties()
mp.SetInputData(clippedPolyData)
mp.Update()
volume = mp.GetVolume()