# ClipDataSetWithPolyData

VTKExamples/Cxx/Meshes/ClipDataSetWithPolyData

### Description

Note

This example was translated to C++ from the Python example here.

The example that shows how to use the vtkClipDataSet to clip a vtkRectilinearGrid with an arbitrary polydata. vtkImplicitPolyDataDistance is used to turn the polydata into an implicit function. Every point of the grid is evaluated before sending to vtkClipDataSet. This example uses a vtkConeSource to generate polydata to use, however any polydata could be used, including stl files.

The left part of the image shows the inside clip and the distance field on a center slice. The right side shows the outside clip. When the program exits using the "e: key, the example will report the cell type for both the inside and outside clips.

Note

vtkClipDataSet tetrahedralizes the volume before clipping. Contrast this with the vtkTableBasedClipDataSet example: TableBasedClipDataSetWithPolyData.

Here is the summary reported when the example exits: ``

The clipped dataset(inside) contains a vtkUnstructuredGrid that has 49514 cells Cell type vtkTetra occurs 41034 times. Cell type vtkWedge occurs 8480 times.

The clipped dataset(outside) contains a vtkUnstructuredGrid that has 714434 cells Cell type vtkTetra occurs 705090 times. Cell type vtkWedge occurs 9344 times.

### Code

ClipDataSetWithPolyData.cxx

    #include <vtkVersion.h>
    #include <vtkSmartPointer.h>

    #include <vtkClipDataSet.h>
    #include <vtkImplicitPolyDataDistance.h>
    #include <vtkConeSource.h>
    #include <vtkPointData.h>
    #include <vtkUnstructuredGrid.h>
    #include <vtkFloatArray.h>
    #include <vtkRectilinearGrid.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkProperty.h>
    #include <vtkActor.h>
    #include <vtkCamera.h>
    #include <vtkRectilinearGridGeometryFilter.h>
    #include <vtkDataSetMapper.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>

    #include <map>

    int main (int, char *[])
    {
      // Create polydata to slice the grid with. In this case, use a cone. This could
      // be any polydata including a stl file.
      vtkSmartPointer<vtkConeSource> cone =
        vtkSmartPointer<vtkConeSource>::New();
      cone->SetResolution(50);
      cone->SetDirection(0,0,-1);
      cone->SetHeight(3.0);
      cone->CappingOn();
      cone->Update();

      // Implicit function that will be used to slice the mesh
      vtkSmartPointer<vtkImplicitPolyDataDistance> implicitPolyDataDistance =
        vtkSmartPointer<vtkImplicitPolyDataDistance>::New();
      implicitPolyDataDistance->SetInput(cone->GetOutput());

      // create a grid
      unsigned int dimension = 51;
      vtkSmartPointer<vtkFloatArray> xCoords =
        vtkSmartPointer<vtkFloatArray>::New();
      for (unsigned int i = 0; i < dimension; ++i)
      {
        xCoords->InsertNextValue(-1.0 + i * 2.0 / static_cast<float>(dimension-1));
      }
      vtkSmartPointer<vtkFloatArray> yCoords =
        vtkSmartPointer<vtkFloatArray>::New();
      for (unsigned int i = 0; i < dimension; ++i)
      {
        yCoords->InsertNextValue(-1.0 + i * 2.0 / static_cast<float>(dimension-1));
      }
      vtkSmartPointer<vtkFloatArray> zCoords =
        vtkSmartPointer<vtkFloatArray>::New();
      for (unsigned int i = 0; i < dimension; ++i)
      {
        zCoords->InsertNextValue(-1.0 + i * 2.0 / static_cast<float>(dimension-1));
      }
      // The coordinates are assigned to the rectilinear grid. Make sure that
      // the number of values in each of the XCoordinates, YCoordinates,
      // and ZCoordinates is equal to what is defined in SetDimensions().
      vtkSmartPointer<vtkRectilinearGrid> rgrid =
        vtkSmartPointer<vtkRectilinearGrid>::New();
      rgrid->SetDimensions(xCoords->GetNumberOfTuples(),
                           yCoords->GetNumberOfTuples(),
                           zCoords->GetNumberOfTuples());
      rgrid->SetXCoordinates(xCoords);
      rgrid->SetYCoordinates(yCoords);
      rgrid->SetZCoordinates(zCoords);

      // Create an array to hold distance information
      vtkSmartPointer<vtkFloatArray> signedDistances =
        vtkSmartPointer<vtkFloatArray>::New();
      signedDistances->SetNumberOfComponents(1);
      signedDistances->SetName("SignedDistances");

      // Evaluate the signed distance function at all of the grid points
      for (vtkIdType pointId = 0; pointId < rgrid->GetNumberOfPoints(); ++pointId)
      {
        double p[3];
        rgrid->GetPoint(pointId, p);
        double signedDistance = implicitPolyDataDistance->EvaluateFunction(p);
        signedDistances->InsertNextValue(signedDistance);
      }

      // Add the SignedDistances to the grid
      rgrid->GetPointData()->SetScalars(signedDistances);

      // Use vtkClipDataSet to slice the grid with the polydata
      vtkSmartPointer<vtkClipDataSet> clipper =
        vtkSmartPointer<vtkClipDataSet>::New();
    #if VTK_MAJOR_VERSION <= 5
      clipper->SetInput(rgrid);
    #else
      clipper->SetInputData(rgrid);
    #endif
      clipper->InsideOutOn();
      clipper->SetValue(0.0);
      clipper->GenerateClippedOutputOn();
      clipper->Update();

      // --- mappers, actors, render, etc. ---
      // mapper and actor to view the cone
      vtkSmartPointer<vtkPolyDataMapper> coneMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
      coneMapper->SetInputConnection(cone->GetOutputPort());
      vtkSmartPointer<vtkActor> coneActor =
        vtkSmartPointer<vtkActor>::New();
      coneActor->SetMapper(coneMapper);

      // geometry filter to view the background grid
      vtkSmartPointer<vtkRectilinearGridGeometryFilter> geometryFilter =
        vtkSmartPointer<vtkRectilinearGridGeometryFilter>::New();
    #if VTK_MAJOR_VERSION <= 5
      geometryFilter->SetInput(rgrid);
    #else
      geometryFilter->SetInputData(rgrid);
    #endif
      geometryFilter->SetExtent(0, dimension, 0, dimension, dimension/2, dimension/2);
      geometryFilter->Update();

      vtkSmartPointer<vtkPolyDataMapper> rgridMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
      rgridMapper->SetInputConnection(geometryFilter->GetOutputPort());
      rgridMapper->SetScalarRange(rgrid->GetPointData()->GetArray("SignedDistances")->GetRange());

      vtkSmartPointer<vtkActor> wireActor =
        vtkSmartPointer<vtkActor>::New();
      wireActor->SetMapper(rgridMapper);
      wireActor->GetProperty()->SetRepresentationToWireframe();

      // mapper and actor to view the clipped mesh
      vtkSmartPointer<vtkDataSetMapper> clipperMapper =
        vtkSmartPointer<vtkDataSetMapper>::New();
      clipperMapper->SetInputConnection(clipper->GetOutputPort());
      clipperMapper->ScalarVisibilityOff();

      vtkSmartPointer<vtkDataSetMapper> clipperOutsideMapper =
        vtkSmartPointer<vtkDataSetMapper>::New();
      clipperOutsideMapper->SetInputConnection(clipper->GetOutputPort(1));
      clipperOutsideMapper->ScalarVisibilityOff();

      vtkSmartPointer<vtkActor> clipperActor =
        vtkSmartPointer<vtkActor>::New();
      clipperActor->SetMapper(clipperMapper);
      clipperActor->GetProperty()->SetColor(0.89,0.81,0.34); // banana

      vtkSmartPointer<vtkActor> clipperOutsideActor =
        vtkSmartPointer<vtkActor>::New();
      clipperOutsideActor->SetMapper(clipperOutsideMapper);
      clipperOutsideActor->GetProperty()->SetColor(0.89,0.81,0.34); // banana

      // A renderer and render window
      // Create a renderer, render window, and interactor
      double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
      vtkSmartPointer<vtkRenderer> leftRenderer =
        vtkSmartPointer<vtkRenderer>::New();
      leftRenderer->SetViewport(leftViewport);
      leftRenderer->SetBackground(.4, .5, .6);

      double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
      vtkSmartPointer<vtkRenderer> rightRenderer =
        vtkSmartPointer<vtkRenderer>::New();
      rightRenderer->SetViewport(rightViewport);
      rightRenderer->SetBackground(.5, .6, .6);

      // add the actors
      leftRenderer->AddActor(wireActor);
      leftRenderer->AddActor(clipperActor);
      rightRenderer->AddActor(clipperOutsideActor);

      vtkSmartPointer<vtkRenderWindow> renwin =
        vtkSmartPointer<vtkRenderWindow>::New();
      renwin->SetSize(640, 480);
      renwin->AddRenderer(leftRenderer);
      renwin->AddRenderer(rightRenderer);

      // An interactor
      vtkSmartPointer<vtkRenderWindowInteractor> interactor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
      interactor->SetRenderWindow(renwin);

      // Share the camera

      leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
      leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
      leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
      leftRenderer->GetActiveCamera()->Azimuth(30);
      leftRenderer->GetActiveCamera()->Elevation(30);
      leftRenderer->ResetCamera();
      rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());

      renwin->Render();
      interactor->Start();

      // Generate a report
      vtkIdType numberOfCells = clipper->GetOutput()->GetNumberOfCells();
      std::cout << "------------------------" << std::endl;
      std::cout << "The clipped dataset(inside) contains a " << std::endl
                << clipper->GetOutput()->GetClassName()
                <<  " that has " << numberOfCells << " cells" << std::endl;
      typedef std::map<int,int> CellContainer;
      CellContainer cellMap;
      for (vtkIdType i = 0; i < numberOfCells; i++)
      {
        cellMap[clipper->GetOutput()->GetCellType(i)]++;
      }

      CellContainer::const_iterator it = cellMap.begin();
      while (it != cellMap.end())
      {
        std::cout << "\tCell type "
                  << vtkCellTypes::GetClassNameFromTypeId(it->first)
                  << " occurs " << it->second << " times." << std::endl;
        ++it;
      }

      numberOfCells = clipper->GetClippedOutput()->GetNumberOfCells();
      std::cout << "------------------------" << std::endl;
      std::cout << "The clipped dataset(outside) contains a " << std::endl
                << clipper->GetClippedOutput()->GetClassName()
                <<  " that has " << numberOfCells << " cells" << std::endl;
      typedef std::map<int,int> OutsideCellContainer;
      CellContainer outsideCellMap;
      for (vtkIdType i = 0; i < numberOfCells; i++)
      {
        outsideCellMap[clipper->GetClippedOutput()->GetCellType(i)]++;
      }

      it = outsideCellMap.begin();
      while (it != outsideCellMap.end())
      {
        std::cout << "\tCell type "
                  << vtkCellTypes::GetClassNameFromTypeId(it->first)
                  << " occurs " << it->second << " times." << std::endl;
        ++it;
      }

      return EXIT_SUCCESS;
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)

    PROJECT(ClipDataSetWithPolyData)

    find_package(VTK REQUIRED)
    include(${VTK_USE_FILE})

    add_executable(ClipDataSetWithPolyData MACOSX_BUNDLE ClipDataSetWithPolyData.cxx )

    target_link_libraries(ClipDataSetWithPolyData ${VTK_LIBRARIES})

### Download and Build ClipDataSetWithPolyData

Click here to download ClipDataSetWithPolyData and its CMakeLists.txt file. Once the tarball ClipDataSetWithPolyData.tar has been downloaded and extracted,

    cd ClipDataSetWithPolyData/build

If VTK is installed:

    cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

    cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

    make

and run it:

    ./ClipDataSetWithPolyData

WINDOWS USERS PLEASE NOTE: Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.