Extracting regions as PolyData

Hi,

I am having a polydata containing multiple regions. I want to extract these regions as individual polydata.
Using “vtkPolyDataConnectivityFilter”, I am able to get the total count of extracted regions and able to visualize them as separate regions by setting ColorRegions to ‘On’. Is there any way of accessing the polydata for extracted regions by region id or so?

InputData
From the attached image, you can find the poly data having three regions(differentiated by colors).
I need to extract these three regions as three different polydata.

Thanks,
Srihitha.

Yes, with SetExtractionModeToSpecifiedRegions, InitializeSpecifiedRegionList and AddSpecifiedRegion.

Thanks, Ronald for the help!

I tried using all the methods you suggested. I am getting each of the individual lines as a region, which is not expected.

Hi,

This is the piece of code I am using to obtain the extracted region’s polydata.

Code snippet:
vtkPolyDataConnectivityFilter* connectivityFilter = vtkPolyDataConnectivityFilter::New() ;
//The reader’s output will the input polydata attached
connectivityFilter->SetInputData(this->reader->GetOutput());
connectivityFilter->SetExtractionModeToAllRegions();
connectivityFilter->ScalarConnectivityOff();
connectivityFilter->Update();
int regCount = connectivityFilter->GetNumberOfExtractedRegions();
//Iterating all the extracted regions to get the region’s polydata
for (int i = 0; i < regCount; i++)
{
connectivityFilter->SetInputData(this->reader->GetOutput());
connectivityFilter->SetExtractionModeToSpecifiedRegions();
connectivityFilter->InitializeSpecifiedRegionList();
connectivityFilter->AddSpecifiedRegion(i);
connectivityFilter->ScalarConnectivityOff();
connectivityFilter->Update();
}

InputData:


PS: I am not able to attach .vtk format of InputData. So, just attached an image.

From the above image, I need to obtain the polydata of all the extracted regions differentiated by colors(29 regions).

Thanks,
Srihitha.

Please upload your vtk file to paste.ee and I will help you.

Thank you, Ronald for your time!

Sadly, I am not allowed to upload any attachments except images.
So, please find the drive link for the input data.

Thanks,
Srihitha.

Hi,

I hope you are able to download the vtk file, which I shared. If you are having any issues downloading the file, please let me know.

Thanks,
Srihitha.

Hello. I’m sorry, I had no time for it. Have you solved it yet?

Hi,

I am trying different ways to solve it. But, couldn’t reach the expected result.

Thanks,
Srihitha.

The solution for your problem is this Python script:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from collections import defaultdict
import math
import vtk

r = vtk.vtkPolyDataReader()
r.SetFileName('InputData.vtk')

c = vtk.vtkCleanPolyData()
c.SetInputConnection(r.GetOutputPort())
c.ToleranceIsAbsoluteOn()
c.SetAbsoluteTolerance(1e-5)
c.Update()

pd = c.GetOutput()

cells = defaultdict(list)

# remove duplicates

for i in range(pd.GetNumberOfCells()):
    cell = vtk.vtkIdList()
    pd.GetCellPoints(i, cell)
    if pd.GetCellType(i) in [vtk.VTK_LINE, vtk.VTK_POLY_LINE]:
        ids = [ cell.GetId(j) for j in range(cell.GetNumberOfIds()) ]
        if ids[0] > ids[-1]:
            ids.reverse()

        cells[tuple(ids)].append(i)

to_keep = list(zip(*cells.values()))[0]

_pd = vtk.vtkPolyData()
_pd.DeepCopy(pd)

lines = []

for i in range(_pd.GetNumberOfCells()):
    if i not in to_keep:
        _pd.DeleteCell(i)
    else:
        # vertically?
        if _pd.GetCellType(i) == vtk.VTK_LINE:
            line = vtk.vtkIdList()
            _pd.GetCellPoints(i, line)

            a = _pd.GetPoint(line.GetId(0))
            b = _pd.GetPoint(line.GetId(1))

            rev = vtk.vtkIdList()
            rev.SetNumberOfIds(2)
            rev.SetId(0, line.GetId(1))
            rev.SetId(1, line.GetId(0))

            if abs(a[0]-b[0]) < 1e-5:
                lines.extend([i, _pd.InsertNextCell(vtk.VTK_LINE, rev)])
                

_pd.BuildLinks()

used = []

for l in lines:
    line = vtk.vtkIdList()
    _pd.GetCellPoints(l, line)

    linksA = vtk.vtkIdList()
    linksB = vtk.vtkIdList()

    _pd.GetPointCells(line.GetId(0), linksA)
    _pd.GetPointCells(line.GetId(1), linksB)

    _linksA = [ linksA.GetId(i) for i in range(linksA.GetNumberOfIds()) if linksA.GetId(i) not in lines ]
    _linksB = [ linksB.GetId(i) for i in range(linksB.GetNumberOfIds()) if linksB.GetId(i) not in lines ]

    pA = _pd.GetPoint(line.GetId(0))
    pB = _pd.GetPoint(line.GetId(1))

    v = [pB[0]-pA[0], pB[1]-pA[1]]

    n = -v[1]/abs(v[1])
    d = n*pA[0]

    poly = []

    for _l in _linksA:
        if _l in used:
            continue

        link = vtk.vtkIdList()
        _pd.GetCellPoints(_l, link)

        pts = [ link.GetId(i) for i in range(link.GetNumberOfIds()) ]

        if pts[-1] == line.GetId(0):
            pts.reverse()

        pt = _pd.GetPoint(pts[-1])

        _d = n*pt[0]-d

        assert(abs(_d) > 1e-5)

        if _d > 0:
            poly.extend(reversed(pts[1:]))
            used.append(_l)
            break

    poly.extend([line.GetId(0), line.GetId(1)])

    for _l in _linksB:
        if _l in used:
            continue

        link = vtk.vtkIdList()
        _pd.GetCellPoints(_l, link)

        pts = [ link.GetId(i) for i in range(link.GetNumberOfIds()) ]

        if pts[-1] == line.GetId(1):
            pts.reverse()

        pt = _pd.GetPoint(pts[-1])

        _d = n*pt[0]-d

        assert(abs(_d) > 1e-5)

        if _d > 0:
            poly.extend(pts[1:])
            used.append(_l)
            break

    if len(poly) == 2:
        continue

    if poly[0] == poly[-1]:
        del poly[-1]
    else:
        _links0 = vtk.vtkIdList()
        _pd.GetPointCells(poly[0], _links0)

        _links1 = vtk.vtkIdList()
        _pd.GetPointCells(poly[-1], _links1)

        try:
            for i in range(_links0.GetNumberOfIds()):
                for j in range(_links1.GetNumberOfIds()):
                    if _pd.GetCellType(_links0.GetId(i)) == vtk.VTK_POLY_LINE \
                        and _pd.GetCellType(_links1.GetId(j)) == vtk.VTK_POLY_LINE:

                        if _links0.GetId(i) == _links1.GetId(j):

                            pl = vtk.vtkIdList()
                            _pd.GetCellPoints(_links0.GetId(i), pl)

                            _pl = [ pl.GetId(k) for k in range(pl.GetNumberOfIds()) ]

                            if _pl[1] == poly[-1]:
                                _pl.reverse()

                            poly.extend(_pl[1:-1])

                            raise StopIteration

                        elif _links0.GetId(i) != _links1.GetId(j):

                            cellA = vtk.vtkIdList()
                            _pd.GetCellPoints(_links0.GetId(i), cellA)

                            cellB = vtk.vtkIdList()
                            _pd.GetCellPoints(_links1.GetId(j), cellB)

                            plA = [ cellA.GetId(k) for k in range(cellA.GetNumberOfIds()) ]
                            plB = [ cellB.GetId(k) for k in range(cellB.GetNumberOfIds()) ]

                            if plA[-1] == poly[0]:
                                plA.reverse()

                            if plB[-1] == poly[-1]:
                                plB.reverse()

                            if plA[-1] != poly[-1] \
                                and plB[-1] != poly[0] \
                                and plA[-1] == plB[-1]:

                                    poly.extend(plB[1:])
                                    poly.extend(plA[1:-1][::-1])

                                    raise StopIteration
        except StopIteration:
            pass

    _poly = vtk.vtkIdList()
    [ _poly.InsertNextId(p) for p in poly ]
    _pd.InsertNextCell(vtk.VTK_POLYGON, _poly)

for i in range(_pd.GetNumberOfCells()):
    if _pd.GetCellType(i) != vtk.VTK_POLYGON:
        _pd.DeleteCell(i)

_pd.RemoveDeletedCells()

print(_pd.GetNumberOfCells())

c2 = vtk.vtkCleanPolyData()
c2.SetInputData(_pd)

_if = vtk.vtkIdFilter()
_if.SetInputConnection(c2.GetOutputPort())
_if.CellIdsOn()
_if.PointIdsOff()

w = vtk.vtkPolyDataWriter()
w.SetInputConnection(_if.GetOutputPort())
w.SetFileName('OutputData.vtk')
w.Update()

This is the result:

InputData.vtk (87.6 KB)
OutputData.vtk (13.9 KB)