How to extract surface from polydata

I use vtkCylinderSource and vtkAppendPolyData to create some cylinders that intersect. Now I want to extract the surface of them. How can I do that.

The data looks like the following.

vtkAppendPolyData produces a surface, so there may not be anything you need to do.

Or do you mean you wish to get the surface of the union of the two cylinders? If that’s the case you can use vtkBooleanOperationPolyDataFilter, though be forewarned that the filter is a little unstable.

Thank you for your help. But I still get some problem.

I want to get tube connection ultimately. I tried to use vtkAppendPolyData to append two tubes that intersected. But inside the junction there are some face I do not need. So I have a idea that create two intersected cylinder and extract their outside face.

I run the following code but get some error and output nothing.

    auto c1 = vtkSmartPointer<vtkCylinderSource>::New();
    auto c2 = vtkSmartPointer<vtkCylinderSource>::New();

    c1->SetHeight(20);
    c2->SetHeight(20);

// rotate c1
    auto transform = vtkSmartPointer<vtkTransform>::New();
    auto transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
    transform->RotateZ(90);
    transformFilter->SetTransform(transform);
    transformFilter->SetInputConnection(c1->GetOutputPort());

//    auto append = vtkSmartPointer<vtkAppendPolyData>::New();
//    append->AddInputConnection(transformFilter->GetOutputPort());
//    append->AddInputConnection(c2->GetOutputPort());

    auto filter = vtkSmartPointer<vtkBooleanOperationPolyDataFilter>::New();
    filter->AddInputConnection(c1->GetOutputPort());
    filter->AddInputConnection(c2->GetOutputPort());
    filter->SetOperationToUnion();

    auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(filter->GetOutputPort());

    auto actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);

    auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);
    interactor->SetInteractorStyle(style);
    interactor->Start();

The following is error info.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 719
vtkCompositeDataPipeline (0x5612405a9790): Input port 0 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 2 connections but is not repeatable.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 709
vtkCompositeDataPipeline (0x5612405a9790): Input port 1 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 0 connections but is not optional.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 719
vtkCompositeDataPipeline (0x5612405a9790): Input port 0 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 2 connections but is not repeatable.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 709
vtkCompositeDataPipeline (0x5612405a9790): Input port 1 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 0 connections but is not optional.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 719
vtkCompositeDataPipeline (0x5612405a9790): Input port 0 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 2 connections but is not repeatable.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 709
vtkCompositeDataPipeline (0x5612405a9790): Input port 1 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 0 connections but is not optional.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 719
vtkCompositeDataPipeline (0x5612405a9790): Input port 0 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 2 connections but is not repeatable.

ERROR: In /opt/VTK/VTK-8.2.0.rc2/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 709
vtkCompositeDataPipeline (0x5612405a9790): Input port 1 of algorithm vtkBooleanOperationPolyDataFilter(0x5612405a8d50) has 0 connections but is not optional.

@cory.quammen, I also cannot get the vtk.vtkBooleanOperationPolyDataFilter filter to work:
The vtk.vtkBooleanOperationPolyDataFilter needs triangulated poly data as inputs.

import vtki
import vtk

# create cylinders and triangulate the meshes
c1 = vtki.Cylinder((0,0,0), (1,0,0), 2, 20).tri_filter()
c2 = vtki.Cylinder((0,0,0), (1,1,0), 2, 20).tri_filter()

tubes = vtki.MultiBlock([c1, c2])
merged = tubes.combine()
merged.plot(show_edges=True)

Apply the filter

# Get the intersection:
alg = vtk.vtkBooleanOperationPolyDataFilter()
alg.SetInputData(0, c1)
alg.SetInputData(1, c2)
alg.SetOperationToIntersection()
alg.Update()
intersection = vtki.wrap(alg.GetOutput())
alg.SetOperationToUnion()
alg.Update()
union = vtki.wrap(alg.GetOutput())

And plot up the result:

p = vtki.Plotter()
p.add_mesh(union, opacity=0.75, color='w')
p.add_mesh(intersection, color='r')
p.show()

@cory.quammen @banesullivan I tried but get some black strips on the union. The strips disappear when tubes are orthogonal.

I have another question. Since vtkBooleanOperationPolyDataFilter can only handle with two polydata. How can I get more than two tubes union

 auto l1 = vtkSmartPointer<vtkLineSource>::New();
    auto l2 = vtkSmartPointer<vtkLineSource>::New();
    l1->SetPoint1(-2, 0, 0);
    l1->SetPoint2(2, 0, 0);
    l2->SetPoint1(1, -2, 0);
    l2->SetPoint2(-1, 2, 0);

    auto c1 = vtkSmartPointer<vtkTubeFilter>::New();
    auto c2 = vtkSmartPointer<vtkTubeFilter>::New();

    c1->SetInputConnection(l1->GetOutputPort());
    c1->SetNumberOfSides(30);
    c2->SetInputConnection(l2->GetOutputPort());
    c2->SetNumberOfSides(30);

    auto triFilter1 = vtkSmartPointer<vtkTriangleFilter>::New();
    triFilter1->SetInputConnection(c1->GetOutputPort());

    auto triFilter2 = vtkSmartPointer<vtkTriangleFilter>::New();
    triFilter2->SetInputConnection(c2->GetOutputPort());

    auto filter = vtkSmartPointer<vtkBooleanOperationPolyDataFilter>::New();
    filter->SetInputConnection(0, triFilter1->GetOutputPort());
    filter->SetInputConnection(1, triFilter2->GetOutputPort());
    filter->SetOperationToUnion();

The dark strips could just be incorrect normals produced by the filter. Recall I mentioned that the filter is a little unstable - geometric algorithms are hard to get right! You could try to generate new normals by adding a vtkPolyDataNormals filter to the output of the boolean operations filter.

You’ll need to create additional boolean operation filters, setting one input to the accumulating running union object and the other input to the additional tube.

2 Likes

Thank you. vtkPolyDataNormals works well

Hi,

If I use vtkBooleanOperationPolyDataFilter to get the union of multiple vtkAppendPolyData, can I pass it to vtkDelaunay3D to graph it? What would be the syntax for passing in arguments, etc. Thanks.

Sure.

What have you tried so far?

This is what I have done so far:

code.txt (2.4 KB)

I keep getting these errors:

ERROR: In /work/standalone-x64-build/VTK-source/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 709
vtkCompositeDataPipeline (0x915f840): Input port 0 of algorithm vtkBooleanOperationPolyDataFilter(0x7f48bc00eda0) has 0 connections but is not optional.

ERROR: In /work/standalone-x64-build/VTK-source/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 709
vtkCompositeDataPipeline (0x915f840): Input port 1 of algorithm vtkBooleanOperationPolyDataFilter(0x7f48bc00eda0) has 0 connections but is not optional.

@at123 : please avoid asking the same question in multiple posts.

One of your vtkBooleanOperationPolyDataFilter objects doesn’t have any inputs when it is being updated. There is probably a logic error in your loop. You can check which filter has no input on port 0 by calling booleanOperation->GetNumberOfInputConnections(0). I suggest tracking down which one does this and going from there.

1 Like