I export scene from ParaView to get a mesh like the following image.
Let’s take edge lists from different parts and form two independent meshes.
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCellData.h>
#include <vtkNamedColors.h>
#include <vtkColorTransferFunction.h>
#include <vtkTriangleFilter.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkCharArray.h>
#include <vtkProperty.h>
#include <map>
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
using namespace std;
struct Edge
{
vtkIdType cellId;
vtkIdType edgePt1;
vtkIdType edgePt2;
};
std::vector<vtkSPtr<vtkPolyData>> GetSplitedPdsByConnected(vtkSPtr<vtkPolyData> pd,
std::vector< vtkSPtr<vtkIdList> > cellLists )
{
std::vector<vtkSPtr<vtkPolyData>> newPolyDatas;
for( int i = 0; i < cellLists.size(); ++i )
{
auto cellList = cellLists[i];
vtkSPtrNew( polyData, vtkPolyData );
vtkSPtrNew( points, vtkPoints );
vtkSPtrNew( cells, vtkCellArray );
std::map<int, int> ptMap;
for( int j = 0; j < cellList->GetNumberOfIds(); ++j )
{
auto cellId = cellList->GetId( j );
auto cell = pd->GetCell( cellId );
auto ptIds = cell->GetPointIds();
vtkSPtrNew( newPtIds, vtkIdList );
for( int k = 0; k < ptIds->GetNumberOfIds(); ++k )
{
auto ptId = ptIds->GetId( k );
if( ptMap.find( ptId ) != ptMap.end() )
{
newPtIds->InsertNextId( ptMap[ptId] );
}
else {
auto newPtId = points->InsertNextPoint( pd->GetPoint( ptId ) );
ptMap[ptId] = newPtId;
newPtIds->InsertNextId( newPtId );
}
}
cells->InsertNextCell( newPtIds );
}
polyData->SetPoints( points );
polyData->SetPolys( cells );
polyData->Modified();
newPolyDatas.push_back( polyData );
}
return newPolyDatas;
}
vtkSPtr<vtkIdList> GetConnectedCellIds( vtkPolyData *pd, vtkIdType seedCellId )
{
vtkIdType nPts;
const vtkIdType *pts;
pd->GetCellPoints( seedCellId, nPts, pts );
std::vector<Edge> currrentEdges;
for( int i = 0; i < 3; ++i )
{
Edge edge;
edge.cellId = seedCellId;
edge.edgePt1 = pts[i];
edge.edgePt2 = pts[ (i+1) % 3 ];
currrentEdges.push_back( edge );
}
vtkNew<vtkIdList> visitedCellIds;
visitedCellIds->InsertNextId( seedCellId );
std::vector<Edge> nextEdges;
while ( currrentEdges.size() > 0 )
{
for( int i = 0; i < currrentEdges.size(); ++i )
{
Edge edge = currrentEdges[i];
vtkNew<vtkIdList> neighborCellIds;
pd->GetCellEdgeNeighbors( edge.cellId, edge.edgePt1, edge.edgePt2, neighborCellIds );
for( int j = 0; j < neighborCellIds->GetNumberOfIds(); ++j )
{
auto neiCellId = neighborCellIds->GetId( j );
if( -1 != visitedCellIds->IsId( neiCellId ) )
{
continue;
}
pd->GetCellPoints( neiCellId, nPts, pts );
vtkIdType thirdPt = -1;
for( int k = 0; k < 3; ++k )
{
if( pts[k] != edge.edgePt1 && pts[k] != edge.edgePt2 )
{
thirdPt = pts[k];
break;
}
}
if( -1 == thirdPt )
{
continue;
}
Edge edge1;
edge1.cellId = neiCellId;
edge1.edgePt1 = edge.edgePt1;
edge1.edgePt2 = thirdPt;
Edge edge2;
edge2.cellId = neiCellId;
edge2.edgePt1 = edge.edgePt2;
edge2.edgePt2 = thirdPt;
nextEdges.push_back( edge1 );
nextEdges.push_back( edge2 );
visitedCellIds->InsertNextId( neiCellId );
}
}
currrentEdges.swap( nextEdges );
nextEdges.clear();
}
return visitedCellIds;
}
int main()
{
vtkSPtrNew( reader, vtkXMLPolyDataReader );
reader->SetFileName( "/Users/weiyang/Desktop/test.vtp" );
reader->Update();
auto *polyData = reader->GetOutput();
vtkSPtrNew( triangleFilter, vtkTriangleFilter );
triangleFilter->SetInputData( polyData );
triangleFilter->PassLinesOff();
triangleFilter->PassVertsOff();
triangleFilter->Update();
polyData = triangleFilter->GetOutput();
polyData->BuildCells();
polyData->BuildLinks();
// ============== start to split =================
vtkIdType pdCellCount = polyData->GetNumberOfCells();
vtkIdType visCellCount = 0;
std::vector<bool> markCellIds;
std::vector< vtkSPtr<vtkIdList> > visCellIdsList;
for( int i = 0; i < pdCellCount; ++i )
{
markCellIds.push_back( false );
}
while ( visCellCount != pdCellCount )
{
vtkIdType seedCellId = -1;
for( int i = 0; i < pdCellCount; ++i )
{
if( !markCellIds[i] )
{
seedCellId = i;
}
}
if( -1 == seedCellId )
{
break;
}
vtkSPtr<vtkIdList> visitedCells = GetConnectedCellIds( polyData, seedCellId );
visCellCount += visitedCells->GetNumberOfIds();
visCellIdsList.push_back( visitedCells );
for( int i = 0; i < visitedCells->GetNumberOfIds(); ++i )
{
auto id = visitedCells->GetId( i );
markCellIds[id] = true;
}
}
std::cout << visCellIdsList.size() << std::endl;
auto newPds = GetSplitedPdsByConnected( polyData, visCellIdsList );
std::cout << newPds.size() << std::endl;
vtkSPtrNew( renderer, vtkRenderer );
for( int i = 0; i < newPds.size(); ++i )
{
vtkSPtrNew( mapper, vtkPolyDataMapper );
mapper->SetInputData( newPds[i] );
vtkSPtrNew( actor, vtkActor );
actor->SetMapper( mapper );
double color[3] = { double( ((i+1)&1) > 0 ), double( ((i+1)&2) > 0 ), double( ((i+1)&3) > 0 ) };
actor->GetProperty()->SetColor( color );
renderer->AddActor(actor);
}
// ============== finish: split =================
renderer->SetBackground( 0, 0, 0 );
vtkSPtrNew( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
We can also use vtkPolyDataConnectivityFilter to seperate the mesh.
int main()
{
vtkSPtrNew( reader, vtkXMLPolyDataReader );
reader->SetFileName( "/Users/weiyang/Desktop/test.vtp" );
reader->Update();
auto *polyData = reader->GetOutput();
vtkSPtrNew( triangleFilter, vtkTriangleFilter );
triangleFilter->SetInputData( polyData );
triangleFilter->PassLinesOff();
triangleFilter->PassVertsOff();
triangleFilter->Update();
polyData = triangleFilter->GetOutput();
polyData->BuildCells();
polyData->BuildLinks();
vtkSPtrNew( renderer, vtkRenderer );
// ============== start to split =================
vtkNew<vtkPolyDataConnectivityFilter> connectivityFilter;
connectivityFilter->SetInputData( polyData );
connectivityFilter->SetExtractionModeToAllRegions();
connectivityFilter->Update();
int regionsCount = connectivityFilter->GetNumberOfExtractedRegions();
cout << regionsCount << endl;
for( int i = 0; i < regionsCount; ++i )
{
connectivityFilter->InitializeSpecifiedRegionList();
connectivityFilter->SetExtractionModeToSpecifiedRegions();
connectivityFilter->AddSpecifiedRegion(i); // select the region to extrac
connectivityFilter->Update();
vtkSPtrNew( data, vtkPolyData );
data->DeepCopy( connectivityFilter->GetOutput() );
vtkSPtrNew( mapper, vtkPolyDataMapper );
mapper->SetInputData( data );
mapper->SetScalarVisibility( false );
vtkSPtrNew( actor, vtkActor );
actor->SetMapper( mapper );
double color[3] = { double( ((i+1)&1) > 0 ), double( ((i+1)&2) > 0 ), double( ((i+1)&3) > 0 ) };
cout << color[0] << ", " << color[1] << ", " << color[2] << endl;
actor->GetProperty()->SetColor( color[0], color[1], color[2] );
renderer->AddActor(actor);
}
// ============== finish: split =================
renderer->SetBackground( 0, 0, 0 );
vtkSPtrNew( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}