Hi all,
I am having difficulty clipping my polydata along a specific path and would be very grateful for some assistance.
As shown in the image below, I am trying to clip my (green) polydata along a path corresponding to the widest points along the head in the z-direction. I have projected my polydata onto a z-plane, obtained a convex hull, then extracted the widest positions along the sides of the head in 3D. Using those points, I have created a ribbon on each side of the head that I would like to use to clip my polydata so I may discard the data towards the back of the head. How can I clip my polydata along this ribbon?
So far, I have tried using those points to define a vtkImplicitSelectionLoop which I then used as the clip function with vtkClipPolyData, but this didn’t work. Perhaps the issue here is the orientation of my loop since the examples I’ve seen appear to define the loop on the surface to essentially punch a hole in the surface. I also tried using the selection loop with vtkSelectPolyData and vtkCutter, but did not obtain any sensible results.
I have also tried using vtkIntersectionPolyDataFilter to split the polydata along the intersection of the ribbon. However, that gives a warning stating “No intersection between objects”, and the number of intersection points and lines are equal to 0. The polydata are clearly intersecting so I’m not sure why there are 0 intersections.
How can I clip my polydata along the points that I’ve identified to be the widest positions around the head?
Thank you for your time!
Matthew
Hello,
If I understood it right, both your input and ribbon are polydata objects, so I suggest using vtkBooleanOperationPolyDataFilter
(https://vtk.org/doc/nightly/html/classvtkBooleanOperationPolyDataFilter.html#details) to perform the operation you want. Also, I’d check the tolerance parameters of the classes you’re using. Other than those, drawing a figure illustrating what you’re trying to achieve may help people help you.
best,
PC
Hi Paulo,
Correct, they are both polydata objects. I tried the vtkBooleanOperationPolyDataFilter
and all operations return an empty polydata object in the first and second outputs when I use booleanOperation.GetOutput()
. Perhaps this is expected behaviour since the BooleanOperationPolyDataFilter example also returns empty polydata objects, although the identical lines renders the difference between the two spheres in the example.
To better describe my problem, I have a 3D head that I am trying to cut along the outermost points of the head when viewed along the z-axis. The remaining region of the face I would like to use as a mask.
Here is my code:
booleanOperation = vtk.vtkBooleanOperationPolyDataFilter()
booleanOperation.SetOperationToDifference()
booleanOperation.SetInputData( 0, mask )
booleanOperation.SetInputData( 1, ribbon )
#booleanOperation.SetTolerance( 0 ) # 0, default 1e-6, and 1, have no effect; documentation unclear
booleanOperationMapper = vtk.vtkPolyDataMapper()
booleanOperationMapper.SetInputConnection(booleanOperation.GetOutputPort())
booleanOperationMapper.ScalarVisibilityOff()
booleanOperationActor = vtk.vtkActor()
booleanOperationActor.SetMapper(booleanOperationMapper)
booleanOperationActor.GetProperty().SetDiffuseColor(colors.GetColor3d('Banana'))
renderer = vtkRenderer()
renderer.AddViewProp(booleanOperationActor)
This returns an error (see below) that doesn’t appear when I execute the example using spheres.
What am I doing wrong?
Cheers,
Matthew
Hello,
Make sure you call Update()
, on all your algorithms, including vtkBooleanOperationPolyDataFilter
.
regards,
PC
I have added booleanOperation.Update()
but still receive the errors. The input polydata objects appear to be okay as they render correctly, but they are non-manifold. The documentation says that unexpected results may be obtained with non-manifold surfaces.
Do you have any suggestions as to how I can obtain my desired output, maybe using another approach, or possibly specifying the appropriate (manifold?) polydata object instead of a ribbon?
M
When mysterious issues like that arise, try to reduce the test case to a trivial one. I mean, use very simple geometries as the two inputs and observe whether you reproduce the observed behavior.
If your ribbon is a flat strip of triangles, for example, it represents an object that can’t exist in reality. So we say it is non-manifold geometry. In the figure below, the leftmost is what I think is your ribbon. It is non-manifold as zero-thickness ribbons can’t exist. You either have to enclose the volume it occupies (middle) or make it a non-zero thickness (rightmost). Choose the one that suits your objective. There are VTK filters that can do both for you.
Indeed, which is why I went back to the boolean sphere example and inspected the output.
What filter would you recommend to create thickness?
My ribbon doesn’t loop back on itself, but you’re right that it has zero thickness. The vtkRibbonFilter
doesn’t have a thickness parameter, and although the vtkTubeFilter
creates a manifold object enclosing the outermost points along the head, the boolean operation creates the same error. I envision creating a parallel ribbon a large enough distance away, closing the volume that it occupies (middle object above), then taking the boolean difference to obtain the mask.
Is there a filter to extrude a surface along a normal to create an enclosed volume?
Before trying that, make sure you have good quality meshes before applying a boolean operation. I mean, making sure the geomeytries not only are manifold, but also watertight, free from duplicate vertexes, degenerate faces, etc. For that, you can use vtkCleanPolyData
.
Please, check vtkLinearExtrusionFilter
(or its vtkPLinearExtrusionFilter
subclass if you wish to go parallel).
1 Like
Thanks, Paulo.
I was able to extrude and clean my ribbon to create a volume that envelopes the data I would like to subtract. I do not seen any non-manifold edges in this bounding volume according to vtkFeatureEdges
and MeshMixer. However, I cannot perform boolean operations on it. My mask does contain some non-manifold edges, and I tried to extrude my mask by a minuscule amount then apply vtkCleanPolyData
, but I still see some non-manifold edges. Again, I cannot perform boolean operations on it and receive the “No points to subdivide” error.
My input data comes from a 3D scanner and is non-manifold - I cannot avoid this. I know that VTK is capable of cutting out the (non-manifold) mask since I am able to use vtkClipPolyData
to extract the mask from the input data with nice clean edges using a bounding box. I’m not sure what I need to do to make my volumes compatible for boolean operations after trying your directions to create a closed or non-zero thickness volume.
Regards,
Matthew
Hi Paulo,
I just wanted to let you know that I solved my problem. Here’s my workflow:
- Extract points to clip along (I’ll call it crossline).
- Extract points from largest edge (i.e., perimeter of mask).
- Determine nearest neighbours from crossline to perimeter.
- Create closed loop bound by crossline and perimeter and convert to polydata.
- Use
vtkSelectPolyData
then vtkClipPolyData
to clip mask along loop.
The image shows the clipped mask in green, the perimiter in white, and the closed loop for clipping in red.
Thanks for discussing and helping me improve my understanding!
Positively,
Matthew
1 Like