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;
}

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

3D Model Viewer: add grid plane and convex hull.
Add google translate tool at right-bottom position.

X
A prohibited operation
0
Would love your thoughts, please comment.x
()
x