Punching a polygonal hole into a triangulated surface

Possible, but not trivial. I tried to simplify the problem, but whatever I do, the cookie cutter does simply sensible. The most simple case I generated is a “topo” made up of two triangles, out of which I am cutting a triangle. Result: No cutting happens at all. Anyway, below I will add as much as I can in the way that you are asking.

Possible other ways further:

  • Is there somewhere on the net a working test case for that cookie cutter that I could use as a starting point for my code?

  • I am working with the vtkCookieCutter from the ParaView 5.9.1 “official release”, but this seems to be far less powerful than what I find in the most recent online documentation of ther VTK classes. Looks like it is really “work in progress”, and next thing I will try is to get the most recent code of that specific class, try if it compiles with my current 5.9.1 code here, and see what it does. The older code does not have for example the options to handle cell or point attributes.

These are the boundary line and the “topo” surface that I am using

boundaryline.vtp (3.9 KB)
surface.vtp (8.1 KB)

And this is the function that I wrote inside an existing filter class that does something else:(some very temporary and messy construction site for a new filter class actually). But maybe reading my code tells you already something:

vtkPolyData* vtkAtgClipGeometry::insertClipperPointsIfTopo(vtkPolyData* inPolyData, vtkPolyData* clipper)
{
    // this we are going to return: make a shallow copy in case we fail
    vtkPolyData* outSurface = vtkPolyData::New();
    outSurface->ShallowCopy(inPolyData);

    // here should now follow some code to check the conditions:
    // - inPolyData is a "topo" - see some code below
    // - clipper is a polyline or best polygon

    // a temporary shallow copy for adding another point attribute and as input for
    // the cookie cutter filter
    vtkSmartPointer<vtkPolyData> tempSurface = vtkSmartPointer<vtkPolyData>::New();
    tempSurface->DeepCopy(inPolyData);

    // add a point attribute containing the altitudes that we are going to flatten away
    vtkSmartPointer<vtkDoubleArray> alti = vtkSmartPointer<vtkDoubleArray>::New();
    alti->SetName("_TEMP_ALTITUDES_");
    vtkPoints* points = tempSurface->GetPoints();
    alti->SetNumberOfTuples(points->GetNumberOfPoints());
    for(vtkIdType p = 0; p < points->GetNumberOfPoints(); ++p)
    {
        double pt[3];
        points->GetPoint(p, pt);
        alti->SetValue(p, pt[2]);
        pt[2] = 0.;
        //points->SetPoint(p, pt);
    }
    outSurface->GetPointData()->AddArray(alti);

    // generate the loop polygons for the clipping
    vtkSmartPointer<vtkPolyData> flatClipper = vtkSmartPointer<vtkPolyData>::New();
    flatClipper->Allocate();
    vtkPoints* clipPts = clipper->GetPoints();
    flatClipper->SetPoints(clipPts);
    vtkSmartPointer<vtkIdList> clipPtIds = vtkSmartPointer<vtkIdList>::New();
    for(vtkIdType id = 0; id < clipPts->GetNumberOfPoints(); ++id)
        clipPtIds->InsertNextId(id);
    flatClipper->InsertNextCell(VTK_POLYGON, clipPtIds);

    // now let's get hold of the cookie cutter filter
    vtkSmartPointer<vtkCookieCutter> ccutter = vtkSmartPointer<vtkCookieCutter>::New();
    ccutter->SetInputData(tempSurface);
    ccutter->SetLoopsData(flatClipper);
    ccutter->Update();

    // get the new surface, as a deep copy
    outSurface->DeepCopy(ccutter->GetOutput());

    // put the altitudes back in and remove the temporary array

    return outSurface;
}