# Bounding volume of cylinder path

**URL:** https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498
**Category:** Support
**Tags:** python
**Created:** [May 15, 2022, 6:05pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498 "2022-05-15T18:05:34Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [May 15, 2022, 6:05pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/1 "2022-05-15T18:05:34Z")

</div>

Hello All,

I am trying to build a volumetric polydata traversed by a cylinder along given path. I am currently creating cylinders at every point in the path and appending them using vtkAppendPolyData. But this gives be too big polydata at the end. I tried using boolean filter, but it fails to create the union of all the cylinders. It just crashes or too intense operation. Let me know if there are diiferent ways of achieving the same.

Thank you

---

<div class="post-metadata">

### Author: ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)
#### Post date: [May 15, 2022, 6:39pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/2 "2022-05-15T18:39:06Z")

</div>

Particularly, I think this code snippet would be interesting for you:

> <https://github.com/SlicerIGT/SlicerMarkupsToModel/blob/835453f30c0da005853d5175aa8980928da5cd49/MarkupsToModel/Logic/vtkSlicerMarkupsToModelLogic.cxx#L730>

Also, I think you may be interested in this example:  
[https://kitware.github.io/vtk-examples/site/Cxx/VisualizationAlgorithms/OfficeTube/](https://kitware.github.io/vtk-examples/site/Cxx/VisualizationAlgorithms/OfficeTube/)

Hope it helps

Mauro

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [May 16, 2022, 5:48pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/3 "2022-05-16T17:48:21Z")

</div>

I think you can use `vtkTubeFiler` for that. In addition to the example posted above, you can find others in the internet.

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [May 16, 2022, 10:06pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/4 "2022-05-16T22:06:49Z")

</div>

It solves the problem if I can create union of all cylinders.

Here is my path along which the cylinder traverses:  
 ![Path](https://discourse.vtk.org/uploads/default/original/2X/e/e34eb55adfa93929ba5607f52cbff78b9f4c0fb4.jpeg)

And here are the appended cylinders. The cylinder direction may change along the path.  
 ![AppendedCylinders](https://discourse.vtk.org/uploads/default/original/2X/b/b4800a3924f0b70a945f88222be1679fc752ad47.jpeg)

Thanks

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [May 16, 2022, 11:14pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/5 "2022-05-16T23:14:06Z")

</div>

FYI- There is a concept in computational geometry called a “swept surface.” (See this [article](https://www.semanticscholar.org/paper/Implicit-modeling-of-swept-surfaces-and-volumes-Schroeder-Lorensen/5984558edf36475ce7def7d5b740b1303e19c9f0) for example.) It is a powerful construct for doing things like path planning, or analyzing robot motion, in complex geometric situations. It can be used to compute bounding boxes too 🙂 One very fun past project was using swept surfaces to figure out how to remove an oil filter (or other parts) from a jet engine - it’s not easy to get tools in, move the tools appropriately, and get the part out. But I digress.

The basic idea is that an object is placed into a sampling volume, and then “rasterized” repeatedly, using a distance field and union set operations, as small steps are taken to move the object along its path (the path typically being a sequence of interpolated transformations) to accumulate the surface position of the object over time. . I’m sure this is way overkill for what you are trying to do, but maybe it will prompt a useful idea…

---

<div class="post-metadata">

### Author: ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)
#### Post date: [May 17, 2022, 12:15am UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/6 "2022-05-17T00:15:02Z")

</div>

I think you could do a continous approximation of your picture example by projecting the oriented cylinder into the path normal plane and using a linear extrusion filter if your path-direction and cylinder-orientation don’t vary too frequently. I think you could use vtkCutter passing through the cylinder-center to get the projection.  
Path-direction change points should be appended as cylinders.  
Cylinder-orientation change (while translating or not) may be done using a rotation extrusion filter but you need to calculate some transforms to get the correct inputs for the filter.  
I think you may achieve near log(n) complexity relative to your current algorithm

I don’t know if this is what Will suggests.

I have done a custom path extrusion filter for myself so I have a little bit of experience, but this post still is a mental exercise for me. Could be wrong

Hope it helps

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [May 17, 2022, 7:35pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/7 "2022-05-17T19:35:44Z")

</div>

Try `myVtkTubeFilter->SidesShareVerticesOn()`.

regards,

Paulo

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [May 18, 2022, 5:49am UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/8 "2022-05-18T05:49:15Z")

</div>

Thank you Will. You pointed me to the right filter. I need cut volume polydata, cut by a cylindrical cutter traversing along the given path of points. I don’t find this SweptSurface filter in my vtk (python). Is it still under patent rights? Any work arounds?

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [May 27, 2022, 2:07pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/9 "2022-05-27T14:07:47Z")

</div>

I created vtkImageData from the appended cylinders using vtkVoxelModeller and then used vtkMarchingCubes to extract surface. **It works, but the model accuracy is not great**. Here is the code:

```
def ConvertPolyData(self, appendedPolyData):
            
    voxel_modeller = vtk.vtkVoxelModeller()
    voxel_modeller.SetSampleDimensions(100,100,100)
    voxel_modeller.SetModelBounds(appendedPolyData.GetBounds())
    voxel_modeller.SetScalarTypeToFloat()
    voxel_modeller.SetMaximumDistance(0.1)
    voxel_modeller.SetInputData(appendedPolyData)
    voxel_modeller.Update()
    
    surface = vtk.vtkMarchingCubes()
    surface.ComputeNormalsOn()
    surface.SetInputData(voxel_modeller.GetOutput())
    iso_value = 0.1
    surface.SetValue(0, iso_value)
    surface.Update()
    
    return surface.GetOutput()
```

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [May 27, 2022, 2:14pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/10 "2022-05-27T14:14:04Z")

</div>

Up your sample dimensions, and use flying edges (it’s way faster especially when built threaded with TBB or STDThread).

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [May 27, 2022, 7:54pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/11 "2022-05-27T19:54:31Z")

</div>

Thanks Will. I see the impact of Flying edges. But VoxelModeller is the time killer, especially when I bump the dimensions.

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [May 28, 2022, 5:50am UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/12 "2022-05-28T05:50:49Z")

</div>

vtkImplicitModeller and flying edges works way better. But still there is place to improve the final polydata accuracy.

BTW, Is there a way to remove internal cells from a polydata? These cells are coming from appending several polydatas.

---

<div class="post-metadata">

### Author: ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)
#### Post date: [May 28, 2022, 2:11pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/13 "2022-05-28T14:11:25Z")

</div>

Here is same code implementing the first steps of the idea I suggested… It’s complex but I think if you put some work into it, it should work releably… The script was made to be executed on Slicer’s python interactor but you can avoid those lines and set your own mappers.

The greatest benefit of this approach is that a linear extrusion only doubles the original number of points of your original polygon, and you would do only one extrusion per uniform path direction, instead of placing n cylinders over that line

```auto
#cylinder path extrusion

import vtk

#create cylinder
cylinderSource = vtk.vtkCylinderSource()
cylinderSource.SetRadius(15)
cylinderSource.SetHeight(40)
cylinderSource.SetCenter([0,0,0])
cylinderSource.SetResolution(100)
cylinderSource.CappingOn()
cylinderSource.Update()

#add model
cylinderModel = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
cylinderModel.SetName('cylinderModel')
cylinderModel.SetAndObservePolyData(cylinderSource.GetOutput())

import numpy as np
cylinderPathDirection = np.array([-5,3,6])/np.linalg.norm(np.array([-5,3,6]))

v1 = [0,0,0]
v2 = [0,0,0]
vtk.vtkMath.Perpendiculars(cylinderPathDirection,v1,v2,30)

rowMatrix = np.array([v1,v2])
columnMatrix = np.array([v1,v2]).T
projectionMatrix = columnMatrix @ rowMatrix

projectionMatrix4x4 = np.eye(4)
projectionMatrix4x4[:3,:3] = projectionMatrix

projectionMatrix4x4_vtk = slicer.util.vtkMatrixFromArray(projectionMatrix4x4)

finalTransform = vtk.vtkTransform()
finalTransform.PostMultiply()
finalTransform.Concatenate(projectionMatrix4x4_vtk)

transformPolyDataFilter = vtk.vtkTransformPolyDataFilter()
transformPolyDataFilter.SetInputData(cylinderSource.GetOutput())
transformPolyDataFilter.SetTransform(finalTransform)
transformPolyDataFilter.Update()

cylinderModelProjection = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
cylinderModelProjection.SetName('cylinderModelProjection')
cylinderModelProjection.SetAndObservePolyData(transformPolyDataFilter.GetOutput())

featureEdges = vtk.vtkFeatureEdges()
featureEdges.BoundaryEdgesOn()
featureEdges.FeatureEdgesOff()
featureEdges.NonManifoldEdgesOff()
featureEdges.ManifoldEdgesOff()
featureEdges.SetInputData(transformPolyDataFilter.GetOutput())
featureEdges.Update()

cylinderModelProjectionContourCircles = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
cylinderModelProjectionContourCircles.SetName('cylinderModelProjectionContourCircles')
cylinderModelProjectionContourCircles.SetAndObservePolyData(featureEdges.GetOutput())

featureEdges2 = vtk.vtkFeatureEdges()
featureEdges2.BoundaryEdgesOff()
featureEdges2.FeatureEdgesOn()
featureEdges2.NonManifoldEdgesOff()
featureEdges2.ManifoldEdgesOff()
featureEdges2.SetInputData(transformPolyDataFilter.GetOutput())
featureEdges2.Update()

cylinderModelProjectionContourLines = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
cylinderModelProjectionContourLines.SetName('cylinderModelProjectionContourLines')
cylinderModelProjectionContourLines.SetAndObservePolyData(featureEdges2.GetOutput())

#polyLoops = vtk.vtkContourLoopExtraction()
#polyLoops.ScalarThresholdingOff()
#polyLoops.SetOutputModeToBoth()
#polyLoops.CleanPointsOff()
#polyLoops.SetNormal(cylinderPathDirection)
#polyLoops.SetInputData(featureEdges.GetOutput())
#polyLoops.Update()

#triangleFilter = vtk.vtkTriangleFilter()
#triangleFilter.SetInputData(featureEdges.GetOutput())
#triangleFilter.Update()

#stripperFilter = vtk.vtkStripper()
#stripperFilter.JoinContiguousSegmentsOn()
#stripperFilter.SetInputData(featureEdges.GetOutput())
#stripperFilter.Update()

#cylinderModelProjectionFace = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
#cylinderModelProjectionFace.SetName('cylinderModelProjectionFace')
#cylinderModelProjectionFace.SetAndObservePolyData(polyLoops.GetOutput())

linearExtrusion = vtk.vtkLinearExtrusionFilter()
linearExtrusion.SetExtrusionTypeToVectorExtrusion()
linearExtrusion.SetScaleFactor(40)
linearExtrusion.SetVector(cylinderPathDirection)
linearExtrusion.SetInputData(featureEdges.GetOutput())
linearExtrusion.Update()

cylinderModelProjectionCirclesExtrusion = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
cylinderModelProjectionCirclesExtrusion.SetName('cylinderModelProjectionCirclesExtrusion')
cylinderModelProjectionCirclesExtrusion.SetAndObservePolyData(linearExtrusion.GetOutput())

linearExtrusion2 = vtk.vtkLinearExtrusionFilter()
linearExtrusion2.SetExtrusionTypeToVectorExtrusion()
linearExtrusion2.SetScaleFactor(40)
linearExtrusion2.SetVector(cylinderPathDirection)
linearExtrusion2.SetInputData(featureEdges2.GetOutput())
linearExtrusion2.Update()

cylinderModelProjectionLinesExtrusion = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
cylinderModelProjectionLinesExtrusion.SetName('cylinderModelProjectionLinesExtrusion')
cylinderModelProjectionLinesExtrusion.SetAndObservePolyData(linearExtrusion2.GetOutput())

```

 ![cylinderPathExtrusion](https://discourse.vtk.org/uploads/default/original/2X/3/3fda65c94344413bef70921510d12fa7f47aa09e.png)

Please give feedback if you think this approach have a conceptual error or you think it won’t work. Thank you

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 1, 2022, 3:59am UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/14 "2022-06-01T03:59:39Z")

</div>

Thank you Mauro. I’m impressed with the results and the performance. Model size reduced lot.

I am still appending extruded models for each line though. I need to work on deleting the points and facets inside the final appended polygon. Here is the code snippet I tried.

def ExtrudeCylinder(cylinderPolyData, scaleFactor, pathVector):

```
featureEdges = vtk.vtkFeatureEdges()
featureEdges.BoundaryEdgesOn()
featureEdges.FeatureEdgesOff()
featureEdges.NonManifoldEdgesOff()
featureEdges.ManifoldEdgesOff()
featureEdges.SetInputData(cylinderPolyData)
featureEdges.Update()
    
featureEdges2 = vtk.vtkFeatureEdges()
featureEdges2.BoundaryEdgesOff()
featureEdges2.FeatureEdgesOn()
featureEdges2.SetFeatureAngle(1)
featureEdges2.NonManifoldEdgesOff()
featureEdges2.ManifoldEdgesOff()
featureEdges2.SetInputData(cylinderPolyData)
featureEdges2.Update()

vtk.vtkMath.Normalize(pathVector)

linearExtrusion = vtk.vtkLinearExtrusionFilter()
linearExtrusion.SetExtrusionTypeToVectorExtrusion()
linearExtrusion.SetScaleFactor(scaleFactor)
linearExtrusion.SetVector(pathVector)
linearExtrusion.CappingOn()
linearExtrusion.SetInputData(cylinderPolyData)

```

# linearExtrusion.SetInputData(featureEdges.GetOutput()) #This leaves the end cylinders not closed

```
linearExtrusion.Update()

linearExtrusion2 = vtk.vtkLinearExtrusionFilter()
linearExtrusion2.SetExtrusionTypeToVectorExtrusion()
linearExtrusion2.SetScaleFactor(scaleFactor)
linearExtrusion2.SetVector(pathVector)
linearExtrusion2.CappingOn()
linearExtrusion2.SetInputData(featureEdges2.GetOutput())
linearExtrusion2.Update()

```

return linearExtrusion.GetOutput(), linearExtrusion2.GetOutput()

---

<div class="post-metadata">

### Author: ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)
#### Post date: [June 1, 2022, 1:17pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/15 "2022-06-01T13:17:55Z")

</div>

Hi. Glad it was useful

Can you post a picture of how the work envelope (or the result of your append filter) looks like?

Thank you

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 1, 2022, 4:32pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/16 "2022-06-01T16:32:08Z")

</div>

Here is the input cut path:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/d/d747ef3e0cd84b843650497011a17e12e8e0b4d1.png)

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 1, 2022, 4:33pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/17 "2022-06-01T16:33:36Z")

</div>

And here is the resultant cut volume model:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/9/9e5a7d59c0af41e8157591b9f3be75deb5327242.png)

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 1, 2022, 4:35pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/18 "2022-06-01T16:35:49Z")

</div>

Here are the cross orthogonal sections of the model:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/7/76c686826a7b5946a508af57286ea406f7b662c3.png)

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 1, 2022, 4:37pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/19 "2022-06-01T16:37:05Z")

</div>

As you can see from the cross sections, the model is not hollow.

---

<div class="post-metadata">

### Author: ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)
#### Post date: [June 1, 2022, 4:41pm UTC](https://discourse.vtk.org/t/bounding-volume-of-cylinder-path/8498/20 "2022-06-01T16:41:54Z")

</div>

Congratrulations, I think you achieved your goal…

Very nice pictures!

Maybe now you can use vtkbool library to merge all the appended models into one with less points. Or you could put more work in some kind of extrusion algorithm
